mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Merge m-c to fx-team, a=merge
This commit is contained in:
commit
aac6bd4fa7
@ -4351,6 +4351,7 @@
|
||||
case "Browser:WindowCreated": {
|
||||
let tab = this.getTabForBrowser(browser);
|
||||
if (tab && data.userContextId) {
|
||||
ContextualIdentityService.telemetry(data.userContextId);
|
||||
tab.setUserContextId(data.userContextId);
|
||||
}
|
||||
|
||||
|
@ -21,22 +21,26 @@ this.ContextualIdentityService = {
|
||||
icon: "chrome://browser/skin/usercontext/personal.svg",
|
||||
color: "#00a7e0",
|
||||
label: "userContextPersonal.label",
|
||||
accessKey: "userContextPersonal.accesskey" },
|
||||
accessKey: "userContextPersonal.accesskey",
|
||||
alreadyOpened: false },
|
||||
{ userContextId: 2,
|
||||
icon: "chrome://browser/skin/usercontext/work.svg",
|
||||
color: "#f89c24",
|
||||
label: "userContextWork.label",
|
||||
accessKey: "userContextWork.accesskey" },
|
||||
accessKey: "userContextWork.accesskey",
|
||||
alreadyOpened: false },
|
||||
{ userContextId: 3,
|
||||
icon: "chrome://browser/skin/usercontext/banking.svg",
|
||||
color: "#7dc14c",
|
||||
label: "userContextBanking.label",
|
||||
accessKey: "userContextBanking.accesskey" },
|
||||
accessKey: "userContextBanking.accesskey",
|
||||
alreadyOpened: false },
|
||||
{ userContextId: 4,
|
||||
icon: "chrome://browser/skin/usercontext/shopping.svg",
|
||||
color: "#ee5195",
|
||||
label: "userContextShopping.label",
|
||||
accessKey: "userContextShopping.accesskey" },
|
||||
accessKey: "userContextShopping.accesskey",
|
||||
alreadyOpened: false },
|
||||
],
|
||||
|
||||
_cssRule: false,
|
||||
@ -72,4 +76,20 @@ this.ContextualIdentityService = {
|
||||
tab.style.backgroundSize = "auto 2px";
|
||||
tab.style.backgroundRepeat = "no-repeat";
|
||||
},
|
||||
|
||||
telemetry(userContextId) {
|
||||
let identity = this.getIdentityFromId(userContextId);
|
||||
|
||||
// Let's ignore unknown identities for now.
|
||||
if (!identity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!identity.alreadyOpened) {
|
||||
identity.alreadyOpened = true;
|
||||
Services.telemetry.getHistogramById("UNIQUE_CONTAINERS_OPENED").add(1);
|
||||
}
|
||||
|
||||
Services.telemetry.getHistogramById("TOTAL_CONTAINERS_OPENED").add(1);
|
||||
},
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
# Avoid duplication if the file happens to be included twice.
|
||||
if test -z "$bucket" -a -z "$NO_CACHE"; then
|
||||
|
||||
# buildbot (or builders that use buildprops.json):
|
||||
if [ -f $topsrcdir/../buildprops.json ]; then
|
||||
read branch platform master <<EOF
|
||||
$(python2.7 -c 'import json; p = json.loads(open("'"$topsrcdir"'/../buildprops.json").read())["properties"]; print p["branch"], p["platform"], p["master"]' 2> /dev/null)
|
||||
EOF
|
||||
@ -40,6 +42,46 @@ if test -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z
|
||||
esac
|
||||
fi
|
||||
|
||||
# taskcluster:
|
||||
else
|
||||
# timeout after 1 second, and don't retry (failure indicates instance is not in ec2 or wget, network issue)
|
||||
# availability_zone is of the form <region><letter> where region is e.g. us-west-2, and az is us-west-2a
|
||||
availability_zone=$(wget -T 1 -t 1 -q -O - http://169.254.169.254/latest/meta-data/placement/availability-zone)
|
||||
# region is az with last letter trimmed
|
||||
region=${availability_zone%?}
|
||||
if test -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z "$MOZ_PGO"; then
|
||||
# set S3 bucket according to tree (level)
|
||||
case "${GECKO_HEAD_REPOSITORY}" in
|
||||
*hg.mozilla.org/try*)
|
||||
bucket=taskcluster-level-1-sccache-${region}
|
||||
;;
|
||||
*hg.mozilla.org/integration/mozilla-inbound*|*hg.mozilla.org/integration/fx-team*)
|
||||
bucket=taskcluster-level-3-sccache-${region}
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# set a dummy master
|
||||
case "${region}" in
|
||||
us-east-1)
|
||||
master=dummy.use1.mozilla.com
|
||||
;;
|
||||
us-west-1)
|
||||
master=dummy.usw1.mozilla.com
|
||||
;;
|
||||
us-west-2)
|
||||
master=dummy.usw2.mozilla.com
|
||||
;;
|
||||
esac
|
||||
|
||||
# set platform based on the SYSTEMROOT env var
|
||||
case "${SYSTEMROOT}" in
|
||||
*Windows)
|
||||
platform=windows
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test -z "$bucket"; then
|
||||
case "$platform" in
|
||||
win*) : ;;
|
||||
@ -53,7 +95,7 @@ else
|
||||
fi
|
||||
mk_add_options "export SCCACHE_BUCKET=$bucket"
|
||||
case "$master" in
|
||||
*use1.mozilla.com*|*usw2.mozilla.com*)
|
||||
*us[ew][12].mozilla.com*)
|
||||
mk_add_options "export SCCACHE_NAMESERVER=169.254.169.253"
|
||||
;;
|
||||
esac
|
||||
|
@ -957,6 +957,11 @@ public:
|
||||
return mAttrsAndChildren.GetAttr(aAttr);
|
||||
}
|
||||
|
||||
const nsAttrValue* GetParsedAttr(nsIAtom* aAttr, int32_t aNameSpaceID) const
|
||||
{
|
||||
return mAttrsAndChildren.GetAttr(aAttr, aNameSpaceID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute map, if there is one.
|
||||
*
|
||||
|
@ -3075,7 +3075,7 @@ nsDOMWindowUtils::FlushPendingFileDeletions()
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::IsIncrementalGCEnabled(JSContext* cx, bool* aResult)
|
||||
{
|
||||
*aResult = JS::IsIncrementalGCEnabled(JS_GetRuntime(cx));
|
||||
*aResult = JS::IsIncrementalGCEnabled(cx);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,8 @@ static nsScriptNameSpaceManager *gNameSpaceManager;
|
||||
|
||||
static PRTime sFirstCollectionTime;
|
||||
|
||||
static JSRuntime *sRuntime;
|
||||
static JSRuntime* sRuntime;
|
||||
static JSContext* sContext;
|
||||
|
||||
static bool sIsInitialized;
|
||||
static bool sDidShutdown;
|
||||
@ -351,7 +352,7 @@ nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
} else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) {
|
||||
nsJSContext::KillShrinkingGCTimer();
|
||||
if (sIsCompactingOnUserInactive) {
|
||||
JS::AbortIncrementalGC(sRuntime);
|
||||
JS::AbortIncrementalGC(sContext);
|
||||
}
|
||||
MOZ_ASSERT(!sIsCompactingOnUserInactive);
|
||||
} else if (!nsCRT::strcmp(aTopic, "quit-application") ||
|
||||
@ -1204,8 +1205,8 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason,
|
||||
|
||||
if (sCCLockedOut && aIncremental == IncrementalGC) {
|
||||
// We're in the middle of incremental GC. Do another slice.
|
||||
JS::PrepareForIncrementalGC(sRuntime);
|
||||
JS::IncrementalGCSlice(sRuntime, aReason, aSliceMillis);
|
||||
JS::PrepareForIncrementalGC(sContext);
|
||||
JS::IncrementalGCSlice(sContext, aReason, aSliceMillis);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1213,15 +1214,15 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason,
|
||||
|
||||
if (sNeedsFullGC || aReason != JS::gcreason::CC_WAITING) {
|
||||
sNeedsFullGC = false;
|
||||
JS::PrepareForFullGC(sRuntime);
|
||||
JS::PrepareForFullGC(sContext);
|
||||
} else {
|
||||
CycleCollectedJSRuntime::Get()->PrepareWaitingZonesForGC();
|
||||
}
|
||||
|
||||
if (aIncremental == IncrementalGC) {
|
||||
JS::StartIncrementalGC(sRuntime, gckind, aReason, aSliceMillis);
|
||||
JS::StartIncrementalGC(sContext, gckind, aReason, aSliceMillis);
|
||||
} else {
|
||||
JS::GCForReason(sRuntime, gckind, aReason);
|
||||
JS::GCForReason(sContext, gckind, aReason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1234,7 +1235,7 @@ nsJSContext::ShrinkGCBuffersNow()
|
||||
|
||||
KillShrinkGCBuffersTimer();
|
||||
|
||||
JS::ShrinkGCBuffers(sRuntime);
|
||||
JS::ShrinkGCBuffers(sContext);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1244,8 +1245,8 @@ FinishAnyIncrementalGC()
|
||||
|
||||
if (sCCLockedOut) {
|
||||
// We're in the middle of an incremental GC, so finish it.
|
||||
JS::PrepareForIncrementalGC(sRuntime);
|
||||
JS::FinishIncrementalGC(sRuntime, JS::gcreason::CC_FORCED);
|
||||
JS::PrepareForIncrementalGC(sContext);
|
||||
JS::FinishIncrementalGC(sContext, JS::gcreason::CC_FORCED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2295,6 +2296,7 @@ mozilla::dom::StartupJSEnvironment()
|
||||
sNeedsGCAfterCC = false;
|
||||
gNameSpaceManager = nullptr;
|
||||
sRuntime = nullptr;
|
||||
sContext = nullptr;
|
||||
sIsInitialized = false;
|
||||
sDidShutdown = false;
|
||||
sShuttingDown = false;
|
||||
@ -2309,7 +2311,7 @@ SetMemoryHighWaterMarkPrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
{
|
||||
int32_t highwatermark = Preferences::GetInt(aPrefName, 128);
|
||||
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_MAX_MALLOC_BYTES,
|
||||
JS_SetGCParameter(sContext, JSGC_MAX_MALLOC_BYTES,
|
||||
highwatermark * 1024L * 1024L);
|
||||
}
|
||||
|
||||
@ -2319,7 +2321,7 @@ SetMemoryMaxPrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
int32_t pref = Preferences::GetInt(aPrefName, -1);
|
||||
// handle overflow and negative pref values
|
||||
uint32_t max = (pref <= 0 || pref >= 0x1000) ? -1 : (uint32_t)pref * 1024 * 1024;
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_MAX_BYTES, max);
|
||||
JS_SetGCParameter(sContext, JSGC_MAX_BYTES, max);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2335,7 +2337,7 @@ SetMemoryGCModePrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
} else {
|
||||
mode = JSGC_MODE_GLOBAL;
|
||||
}
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_MODE, mode);
|
||||
JS_SetGCParameter(sContext, JSGC_MODE, mode);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2344,14 +2346,14 @@ SetMemoryGCSliceTimePrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
int32_t pref = Preferences::GetInt(aPrefName, -1);
|
||||
// handle overflow and negative pref values
|
||||
if (pref > 0 && pref < 100000)
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_SLICE_TIME_BUDGET, pref);
|
||||
JS_SetGCParameter(sContext, JSGC_SLICE_TIME_BUDGET, pref);
|
||||
}
|
||||
|
||||
static void
|
||||
SetMemoryGCCompactingPrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
{
|
||||
bool pref = Preferences::GetBool(aPrefName);
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_COMPACTING_ENABLED, pref);
|
||||
JS_SetGCParameter(sContext, JSGC_COMPACTING_ENABLED, pref);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2360,28 +2362,28 @@ SetMemoryGCPrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
int32_t pref = Preferences::GetInt(aPrefName, -1);
|
||||
// handle overflow and negative pref values
|
||||
if (pref >= 0 && pref < 10000)
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), (JSGCParamKey)(intptr_t)aClosure, pref);
|
||||
JS_SetGCParameter(sContext, (JSGCParamKey)(intptr_t)aClosure, pref);
|
||||
}
|
||||
|
||||
static void
|
||||
SetMemoryGCDynamicHeapGrowthPrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
{
|
||||
bool pref = Preferences::GetBool(aPrefName);
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_DYNAMIC_HEAP_GROWTH, pref);
|
||||
JS_SetGCParameter(sContext, JSGC_DYNAMIC_HEAP_GROWTH, pref);
|
||||
}
|
||||
|
||||
static void
|
||||
SetMemoryGCDynamicMarkSlicePrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
{
|
||||
bool pref = Preferences::GetBool(aPrefName);
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_DYNAMIC_MARK_SLICE, pref);
|
||||
JS_SetGCParameter(sContext, JSGC_DYNAMIC_MARK_SLICE, pref);
|
||||
}
|
||||
|
||||
static void
|
||||
SetMemoryGCRefreshFrameSlicesEnabledPrefChangedCallback(const char* aPrefName, void* aClosure)
|
||||
{
|
||||
bool pref = Preferences::GetBool(aPrefName);
|
||||
JS_SetGCParameter(JS_GetContext(sRuntime), JSGC_REFRESH_FRAME_SLICES_ENABLED, pref);
|
||||
JS_SetGCParameter(sContext, JSGC_REFRESH_FRAME_SLICES_ENABLED, pref);
|
||||
}
|
||||
|
||||
|
||||
@ -2442,10 +2444,12 @@ nsJSContext::EnsureStatics()
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
sContext = JS_GetContext(sRuntime);
|
||||
|
||||
// Let's make sure that our main thread is the same as the xpcom main thread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
sPrevGCSliceCallback = JS::SetGCSliceCallback(sRuntime, DOMGCSliceCallback);
|
||||
sPrevGCSliceCallback = JS::SetGCSliceCallback(sContext, DOMGCSliceCallback);
|
||||
|
||||
// Set up the asm.js cache callbacks
|
||||
static const JS::AsmJSCacheOps asmJSCacheOps = {
|
||||
@ -2454,7 +2458,7 @@ nsJSContext::EnsureStatics()
|
||||
AsmJSCacheOpenEntryForWrite,
|
||||
asmjscache::CloseEntryForWrite
|
||||
};
|
||||
JS::SetAsmJSCacheOps(JS_GetContext(sRuntime), &asmJSCacheOps);
|
||||
JS::SetAsmJSCacheOps(sContext, &asmJSCacheOps);
|
||||
|
||||
// Set these global xpconnect options...
|
||||
Preferences::RegisterCallbackAndCall(SetMemoryHighWaterMarkPrefChangedCallback,
|
||||
|
@ -116,10 +116,19 @@ nsNameSpaceManager::GetNameSpaceID(const nsAString& aURI)
|
||||
return kNameSpaceID_None; // xmlns="", see bug 75700 for details
|
||||
}
|
||||
|
||||
int32_t nameSpaceID;
|
||||
|
||||
nsCOMPtr<nsIAtom> atom = NS_Atomize(aURI);
|
||||
if (mURIToIDTable.Get(atom, &nameSpaceID)) {
|
||||
return GetNameSpaceID(atom);
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsNameSpaceManager::GetNameSpaceID(nsIAtom* aURI)
|
||||
{
|
||||
if (aURI == nsGkAtoms::_empty) {
|
||||
return kNameSpaceID_None; // xmlns="", see bug 75700 for details
|
||||
}
|
||||
|
||||
int32_t nameSpaceID;
|
||||
if (mURIToIDTable.Get(aURI, &nameSpaceID)) {
|
||||
NS_POSTCONDITION(nameSpaceID >= 0, "Bogus namespace ID");
|
||||
return nameSpaceID;
|
||||
}
|
||||
|
@ -33,21 +33,21 @@ class nsAString;
|
||||
class nsNameSpaceManager final
|
||||
{
|
||||
public:
|
||||
virtual ~nsNameSpaceManager() {}
|
||||
~nsNameSpaceManager() {}
|
||||
|
||||
virtual nsresult RegisterNameSpace(const nsAString& aURI,
|
||||
int32_t& aNameSpaceID);
|
||||
nsresult RegisterNameSpace(const nsAString& aURI, int32_t& aNameSpaceID);
|
||||
|
||||
virtual nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
|
||||
nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
|
||||
|
||||
nsIAtom* NameSpaceURIAtom(int32_t aNameSpaceID) {
|
||||
MOZ_ASSERT(aNameSpaceID > 0 && (int64_t) aNameSpaceID <= (int64_t) mURIArray.Length());
|
||||
return mURIArray.ElementAt(aNameSpaceID - 1); // id is index + 1
|
||||
}
|
||||
|
||||
virtual int32_t GetNameSpaceID(const nsAString& aURI);
|
||||
int32_t GetNameSpaceID(const nsAString& aURI);
|
||||
int32_t GetNameSpaceID(nsIAtom* aURI);
|
||||
|
||||
virtual bool HasElementCreator(int32_t aNameSpaceID);
|
||||
bool HasElementCreator(int32_t aNameSpaceID);
|
||||
|
||||
static nsNameSpaceManager* GetInstance();
|
||||
private:
|
||||
|
@ -19,6 +19,24 @@
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
TexUnpackBlob::TexUnpackBlob(const WebGLContext* webgl, uint32_t alignment,
|
||||
uint32_t rowLength, uint32_t imageHeight, uint32_t width,
|
||||
uint32_t height, uint32_t depth, bool hasData)
|
||||
: mAlignment(alignment)
|
||||
, mRowLength(rowLength)
|
||||
, mImageHeight(imageHeight)
|
||||
|
||||
, mSkipPixels(webgl->mPixelStore_UnpackSkipPixels)
|
||||
, mSkipRows(webgl->mPixelStore_UnpackSkipRows)
|
||||
, mSkipImages(webgl->mPixelStore_UnpackSkipImages)
|
||||
|
||||
, mWidth(width)
|
||||
, mHeight(height)
|
||||
, mDepth(depth)
|
||||
|
||||
, mHasData(hasData)
|
||||
{ }
|
||||
|
||||
static GLenum
|
||||
DoTexOrSubImage(bool isSubImage, gl::GLContext* gl, TexImageTarget target, GLint level,
|
||||
const DriverUnpackInfo* dui, GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
@ -48,33 +66,21 @@ TexUnpackBlob::OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackBytes
|
||||
|
||||
bool
|
||||
TexUnpackBytes::ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi)
|
||||
static uint32_t
|
||||
FallbackOnZero(uint32_t val, uint32_t fallback)
|
||||
{
|
||||
if (!mBytes)
|
||||
return true;
|
||||
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
const auto bytesNeeded = webgl->GetUnpackSize(isFunc3D, mWidth, mHeight, mDepth,
|
||||
bytesPerPixel);
|
||||
if (!bytesNeeded.isValid()) {
|
||||
webgl->ErrorInvalidOperation("%s: Overflow while computing the needed buffer"
|
||||
" size.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mByteCount < bytesNeeded.value()) {
|
||||
webgl->ErrorInvalidOperation("%s: Provided buffer is too small. (needs %u, has"
|
||||
" %u)",
|
||||
funcName, bytesNeeded.value(), mByteCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return (val ? val : fallback);
|
||||
}
|
||||
|
||||
TexUnpackBytes::TexUnpackBytes(const WebGLContext* webgl, uint32_t width, uint32_t height,
|
||||
uint32_t depth, const void* bytes)
|
||||
: TexUnpackBlob(webgl, webgl->mPixelStore_UnpackAlignment,
|
||||
FallbackOnZero(webgl->mPixelStore_UnpackRowLength, width),
|
||||
FallbackOnZero(webgl->mPixelStore_UnpackImageHeight, height),
|
||||
width, height, depth, bool(bytes))
|
||||
, mBytes(bytes)
|
||||
{ }
|
||||
|
||||
static bool
|
||||
UnpackFormatHasAlpha(GLenum unpackFormat)
|
||||
{
|
||||
@ -136,11 +142,11 @@ FormatFromPacking(const webgl::PackingInfo& pi)
|
||||
return WebGLTexelFormat::FormatNotSupportingAnyConversion;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_glError)
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_error) const
|
||||
{
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
gl::GLContext* gl = webgl->gl;
|
||||
@ -167,35 +173,63 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
if (!needsYFlip && !needsAlphaPremult)
|
||||
break;
|
||||
|
||||
////////////
|
||||
// This is literally the worst.
|
||||
|
||||
if (mSkipPixels || mSkipRows || mSkipImages ||
|
||||
mRowLength != mWidth ||
|
||||
mImageHeight != mHeight)
|
||||
{
|
||||
webgl->ErrorInvalidOperation("%s: FLIP_Y and PREMULTIPLY_ALPHA are"
|
||||
" incompatible with WebGL 2's new UNPACK_*"
|
||||
" settings.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mDepth != 1) {
|
||||
webgl->ErrorInvalidOperation("%s: FLIP_Y and PREMULTIPLY_ALPHA are"
|
||||
" incompatible with 3D textures.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
webgl->GenerateWarning("%s: Uploading ArrayBuffers with FLIP_Y or"
|
||||
" PREMULTIPLY_ALPHA is slow.",
|
||||
funcName);
|
||||
|
||||
tempBuffer = malloc(mByteCount);
|
||||
if (!tempBuffer) {
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
|
||||
const auto bytesPerRow = CheckedUint32(mRowLength) * bytesPerPixel;
|
||||
const auto rowStride = RoundUpToMultipleOf(bytesPerRow, mAlignment);
|
||||
const auto imageStride = rowStride * mImageHeight;
|
||||
|
||||
if (!imageStride.isValid()) {
|
||||
webgl->ErrorOutOfMemory("%s: Invalid calculation during"
|
||||
" FLIP_Y/PREMULTIPLY_ALPHA handling.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
const auto rowByteAlignment = webgl->mPixelStore_UnpackAlignment;
|
||||
|
||||
const size_t bytesPerRow = bytesPerPixel * mWidth;
|
||||
const size_t rowStride = RoundUpToMultipleOf(bytesPerRow, rowByteAlignment);
|
||||
tempBuffer = malloc(imageStride.value());
|
||||
if (!tempBuffer) {
|
||||
webgl->ErrorOutOfMemory("%s: OOM during FLIP_Y/PREMULTIPLY_ALPHA handling.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!needsAlphaPremult) {
|
||||
MOZ_ASSERT(needsYFlip);
|
||||
|
||||
const uint8_t* src = (const uint8_t*)mBytes;
|
||||
const uint8_t* const srcEnd = src + rowStride * mHeight;
|
||||
const uint8_t* const srcEnd = src + rowStride.value() * mHeight;
|
||||
|
||||
uint8_t* dst = (uint8_t*)tempBuffer.get() + rowStride * (mHeight - 1);
|
||||
uint8_t* dst = (uint8_t*)tempBuffer.get() + rowStride.value() * (mHeight - 1);
|
||||
|
||||
while (src != srcEnd) {
|
||||
memcpy(dst, src, bytesPerRow);
|
||||
src += rowStride;
|
||||
dst -= rowStride;
|
||||
memcpy(dst, src, bytesPerRow.value());
|
||||
src += rowStride.value();
|
||||
dst -= rowStride.value();
|
||||
}
|
||||
|
||||
uploadBytes = tempBuffer.get();
|
||||
@ -205,8 +239,10 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
const auto texelFormat = FormatFromPacking(pi);
|
||||
if (texelFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion) {
|
||||
MOZ_ASSERT(false, "Bad texelFormat from pi.");
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
webgl->ErrorOutOfMemory("%s: FormatFromPacking failed during"
|
||||
" PREMULTIPLY_ALPHA handling.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto srcOrigin = gl::OriginPos::BottomLeft;
|
||||
@ -220,44 +256,46 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
MOZ_ASSERT(srcOrigin != dstOrigin || srcPremultiplied != dstPremultiplied);
|
||||
bool unused_wasTrivial;
|
||||
if (!ConvertImage(mWidth, mHeight,
|
||||
mBytes, rowStride, srcOrigin, texelFormat, srcPremultiplied,
|
||||
tempBuffer.get(), rowStride, dstOrigin, texelFormat,
|
||||
mBytes, rowStride.value(), srcOrigin, texelFormat,
|
||||
srcPremultiplied,
|
||||
tempBuffer.get(), rowStride.value(), dstOrigin, texelFormat,
|
||||
dstPremultiplied, &unused_wasTrivial))
|
||||
{
|
||||
MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
webgl->ErrorOutOfMemory("%s: ConvertImage failed during PREMULTIPLY_ALPHA"
|
||||
" handling.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
uploadBytes = tempBuffer.get();
|
||||
} while (false);
|
||||
|
||||
GLenum error = DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, mWidth, mHeight, mDepth, uploadBytes);
|
||||
*out_glError = error;
|
||||
*out_error = DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, mWidth, mHeight, mDepth, uploadBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackImage
|
||||
|
||||
TexUnpackImage::TexUnpackImage(const RefPtr<layers::Image>& image, bool isAlphaPremult)
|
||||
: TexUnpackBlob(image->GetSize().width, image->GetSize().height, 1, true)
|
||||
TexUnpackImage::TexUnpackImage(const WebGLContext* webgl, uint32_t imageHeight,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
const RefPtr<layers::Image>& image, bool isAlphaPremult)
|
||||
: TexUnpackBlob(webgl, 0, image->GetSize().width, imageHeight, width, height, depth,
|
||||
true)
|
||||
, mImage(image)
|
||||
, mIsAlphaPremult(isAlphaPremult)
|
||||
{ }
|
||||
|
||||
TexUnpackImage::~TexUnpackImage()
|
||||
{ }
|
||||
|
||||
void
|
||||
bool
|
||||
TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_glError)
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_error) const
|
||||
{
|
||||
MOZ_ASSERT_IF(needsRespec, !isSubImage);
|
||||
*out_glError = 0;
|
||||
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
|
||||
@ -265,14 +303,11 @@ TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
gl->MakeCurrent();
|
||||
|
||||
if (needsRespec) {
|
||||
GLenum error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth,
|
||||
nullptr);
|
||||
if (error) {
|
||||
MOZ_ASSERT(!error);
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
*out_error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth,
|
||||
nullptr);
|
||||
if (*out_error)
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
@ -309,7 +344,9 @@ TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
break;
|
||||
}
|
||||
|
||||
return; // Blitting was successful, so we're done!
|
||||
// Blitting was successful, so we're done!
|
||||
*out_error = 0;
|
||||
return true;
|
||||
} while (false);
|
||||
|
||||
webgl->GenerateWarning("%s: Failed to hit GPU-copy fast-path. Falling back to CPU"
|
||||
@ -318,20 +355,34 @@ TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
|
||||
|
||||
RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
|
||||
if (!surface) {
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
webgl->ErrorOutOfMemory("%s: GetAsSourceSurface failed after blit failed for"
|
||||
" TexUnpackImage.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
TexUnpackSurface surfBlob(surface, mIsAlphaPremult);
|
||||
TexUnpackSurface surfBlob(webgl, mImageHeight, mWidth, mHeight, mDepth, surface,
|
||||
mIsAlphaPremult);
|
||||
|
||||
surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level, dui,
|
||||
xOffset, yOffset, zOffset, out_glError);
|
||||
return surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level,
|
||||
dui, xOffset, yOffset, zOffset, out_error);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TexUnpackSurface
|
||||
|
||||
TexUnpackSurface::TexUnpackSurface(const WebGLContext* webgl, uint32_t imageHeight,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
gfx::SourceSurface* surf, bool isAlphaPremult)
|
||||
: TexUnpackBlob(webgl, 0, surf->GetSize().width, imageHeight, width, height, depth,
|
||||
true)
|
||||
, mSurf(surf)
|
||||
, mIsAlphaPremult(isAlphaPremult)
|
||||
{ }
|
||||
|
||||
//////////
|
||||
|
||||
static bool
|
||||
GuessAlignment(const void* data, size_t bytesPerRow, size_t stride, size_t maxAlignment,
|
||||
size_t* const out_alignment)
|
||||
@ -745,24 +796,13 @@ TexUnpackSurface::ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackI
|
||||
|
||||
////////////////////
|
||||
|
||||
TexUnpackSurface::TexUnpackSurface(const RefPtr<gfx::SourceSurface>& surf,
|
||||
bool isAlphaPremult)
|
||||
: TexUnpackBlob(surf->GetSize().width, surf->GetSize().height, 1, true)
|
||||
, mSurf(surf)
|
||||
, mIsAlphaPremult(isAlphaPremult)
|
||||
{ }
|
||||
|
||||
TexUnpackSurface::~TexUnpackSurface()
|
||||
{ }
|
||||
|
||||
void
|
||||
bool
|
||||
TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum* const out_glError)
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_error) const
|
||||
{
|
||||
*out_glError = 0;
|
||||
|
||||
WebGLContext* webgl = tex->mContext;
|
||||
|
||||
// MakeCurrent is a big mess in here, because mapping (and presumably unmapping) on
|
||||
@ -770,23 +810,18 @@ TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* f
|
||||
// call into GL, instead of trying to keep MakeCurrent-ed.
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> dataSurf = mSurf->GetDataSurface();
|
||||
|
||||
if (!dataSurf) {
|
||||
// Since GetDataSurface didn't return error code, assume system
|
||||
// is out of memory
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
webgl->ErrorOutOfMemory("%s: OOM in GetDataSurface for TexUnpackSurface.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum error;
|
||||
if (UploadDataSurface(isSubImage, webgl, target, level, dui, xOffset, yOffset,
|
||||
zOffset, mWidth, mHeight, dataSurf, mIsAlphaPremult, &error))
|
||||
zOffset, mWidth, mHeight, dataSurf, mIsAlphaPremult, out_error))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (error == LOCAL_GL_OUT_OF_MEMORY) {
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// CPU conversion. (++numCopies)
|
||||
@ -798,13 +833,9 @@ TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* f
|
||||
if (!ConvertSurface(webgl, dui, dataSurf, mIsAlphaPremult, &convertedBuffer,
|
||||
&convertedAlignment, &wasTrivial, &outOfMemory))
|
||||
{
|
||||
if (outOfMemory) {
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
} else {
|
||||
NS_ERROR("Failed to convert surface.");
|
||||
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
|
||||
}
|
||||
return;
|
||||
webgl->ErrorOutOfMemory("%s: %s in ConvertSurface for TexUnpackSurface.",
|
||||
funcName, outOfMemory ? "OOM" : "Failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wasTrivial) {
|
||||
@ -817,10 +848,10 @@ TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* f
|
||||
ScopedUnpackReset scopedReset(webgl);
|
||||
webgl->gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, convertedAlignment);
|
||||
|
||||
error = DoTexOrSubImage(isSubImage, webgl->gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth,
|
||||
convertedBuffer.get());
|
||||
*out_glError = error;
|
||||
*out_error = DoTexOrSubImage(isSubImage, webgl->gl, target.get(), level, dui, xOffset,
|
||||
yOffset, zOffset, mWidth, mHeight, mDepth,
|
||||
convertedBuffer.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webgl
|
||||
|
@ -47,30 +47,30 @@ struct DriverUnpackInfo;
|
||||
class TexUnpackBlob
|
||||
{
|
||||
public:
|
||||
const GLsizei mWidth;
|
||||
const GLsizei mHeight;
|
||||
const GLsizei mDepth;
|
||||
const uint32_t mAlignment;
|
||||
const uint32_t mRowLength;
|
||||
const uint32_t mImageHeight;
|
||||
const uint32_t mSkipPixels;
|
||||
const uint32_t mSkipRows;
|
||||
const uint32_t mSkipImages;
|
||||
const uint32_t mWidth;
|
||||
const uint32_t mHeight;
|
||||
const uint32_t mDepth;
|
||||
const bool mHasData;
|
||||
|
||||
protected:
|
||||
TexUnpackBlob(GLsizei width, GLsizei height, GLsizei depth, bool hasData)
|
||||
: mWidth(width)
|
||||
, mHeight(height)
|
||||
, mDepth(depth)
|
||||
, mHasData(hasData)
|
||||
{ }
|
||||
TexUnpackBlob(const WebGLContext* webgl, uint32_t alignment, uint32_t rowLength,
|
||||
uint32_t imageHeight, uint32_t width, uint32_t height, uint32_t depth,
|
||||
bool hasData);
|
||||
|
||||
public:
|
||||
virtual ~TexUnpackBlob() {}
|
||||
virtual ~TexUnpackBlob() { }
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) = 0;
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) = 0;
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_error) const = 0;
|
||||
|
||||
static void OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
|
||||
gl::OriginPos* const out_dst);
|
||||
@ -79,24 +79,16 @@ public:
|
||||
class TexUnpackBytes : public TexUnpackBlob
|
||||
{
|
||||
public:
|
||||
const size_t mByteCount;
|
||||
const void* const mBytes;
|
||||
|
||||
TexUnpackBytes(GLsizei width, GLsizei height, GLsizei depth, size_t byteCount,
|
||||
const void* bytes)
|
||||
: TexUnpackBlob(width, height, depth, bool(bytes))
|
||||
, mByteCount(byteCount)
|
||||
, mBytes(bytes)
|
||||
{ }
|
||||
TexUnpackBytes(const WebGLContext* webgl, uint32_t width, uint32_t height,
|
||||
uint32_t depth, const void* bytes);
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) override;
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) override;
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_error) const override;
|
||||
};
|
||||
|
||||
class TexUnpackImage : public TexUnpackBlob
|
||||
@ -105,20 +97,15 @@ public:
|
||||
const RefPtr<layers::Image> mImage;
|
||||
const bool mIsAlphaPremult;
|
||||
|
||||
TexUnpackImage(const RefPtr<layers::Image>& image, bool isAlphaPremult);
|
||||
virtual ~TexUnpackImage() override;
|
||||
TexUnpackImage(const WebGLContext* webgl, uint32_t imageHeight, uint32_t width,
|
||||
uint32_t height, uint32_t depth, const RefPtr<layers::Image>& image,
|
||||
bool isAlphaPremult);
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) override;
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_error) const override;
|
||||
};
|
||||
|
||||
class TexUnpackSurface : public TexUnpackBlob
|
||||
@ -127,20 +114,15 @@ public:
|
||||
const RefPtr<gfx::SourceSurface> mSurf;
|
||||
const bool mIsAlphaPremult;
|
||||
|
||||
TexUnpackSurface(const RefPtr<gfx::SourceSurface>& surf, bool isAlphaPremult);
|
||||
virtual ~TexUnpackSurface() override;
|
||||
TexUnpackSurface(const WebGLContext* webgl, uint32_t imageHeight, uint32_t width,
|
||||
uint32_t height, uint32_t depth, gfx::SourceSurface* surf,
|
||||
bool isAlphaPremult);
|
||||
|
||||
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
|
||||
const webgl::PackingInfo& pi) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_glError) override;
|
||||
virtual bool TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
|
||||
WebGLTexture* tex, TexImageTarget target, GLint level,
|
||||
const webgl::DriverUnpackInfo* dui, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
GLenum* const out_error) const override;
|
||||
|
||||
protected:
|
||||
static bool ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackInfo* dui,
|
||||
|
@ -940,7 +940,13 @@ public:
|
||||
&elem, &out_error);
|
||||
}
|
||||
|
||||
//////
|
||||
// WebGLTextureUpload.cpp
|
||||
public:
|
||||
bool ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
|
||||
uint32_t tailPixels, const webgl::TexUnpackBlob* blob);
|
||||
|
||||
protected:
|
||||
bool ValidateTexImageSpecification(const char* funcName, uint8_t funcDims,
|
||||
GLenum texImageTarget, GLint level,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
@ -956,6 +962,13 @@ public:
|
||||
WebGLTexture** const out_texture,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo);
|
||||
|
||||
bool GetUnpackValuesForImage(const char* funcName, uint32_t srcImageWidth,
|
||||
uint32_t srcImageHeight, uint32_t* const out_rowLength,
|
||||
uint32_t* const out_imageHeight);
|
||||
|
||||
bool ValidateUnpackInfo(const char* funcName, GLenum format, GLenum type,
|
||||
webgl::PackingInfo* const out);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Vertices Feature (WebGLContextVertices.cpp)
|
||||
public:
|
||||
|
@ -812,10 +812,6 @@ WebGLTexture::GetTexParameter(TexTarget texTarget, GLenum pname)
|
||||
case LOCAL_GL_TEXTURE_COMPARE_MODE:
|
||||
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
|
||||
case LOCAL_GL_TEXTURE_MAX_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_A:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_B:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_G:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_R:
|
||||
case LOCAL_GL_TEXTURE_WRAP_R:
|
||||
mContext->gl->fGetTexParameteriv(texTarget.get(), pname, &i);
|
||||
return JS::NumberValue(uint32_t(i));
|
||||
@ -1027,6 +1023,10 @@ WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, GLint* maybeIntPar
|
||||
mWrapT = intParam;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_COMPARE_MODE:
|
||||
mTexCompareMode = intParam;
|
||||
break;
|
||||
|
||||
// We don't actually need to store the WRAP_R, since it doesn't change texture
|
||||
// completeness rules.
|
||||
}
|
||||
|
@ -237,31 +237,34 @@ public:
|
||||
dom::Element* elem, ErrorResult* const out_error);
|
||||
|
||||
protected:
|
||||
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType, webgl::TexUnpackBlob* blob);
|
||||
void TexOrSubImageBlob(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& pi,
|
||||
const webgl::TexUnpackBlob* blob);
|
||||
|
||||
bool ValidateTexImageSpecification(const char* funcName, TexImageTarget target,
|
||||
GLint level, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
GLint level, uint32_t width, uint32_t height,
|
||||
uint32_t depth,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo);
|
||||
bool ValidateTexImageSelection(const char* funcName, TexImageTarget target,
|
||||
GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth,
|
||||
GLint zOffset, uint32_t width, uint32_t height,
|
||||
uint32_t depth,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo);
|
||||
|
||||
bool ValidateUnpack(const char* funcName, const webgl::TexUnpackBlob* blob,
|
||||
bool isFunc3D, const webgl::PackingInfo& srcPI) const;
|
||||
public:
|
||||
void TexStorage(const char* funcName, TexTarget target, GLsizei levels,
|
||||
GLenum sizedFormat, GLsizei width, GLsizei height, GLsizei depth);
|
||||
protected:
|
||||
void TexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType, webgl::TexUnpackBlob* blob);
|
||||
GLenum internalFormat, const webgl::PackingInfo& pi,
|
||||
const webgl::TexUnpackBlob* blob);
|
||||
void TexSubImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, webgl::TexUnpackBlob* blob);
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& pi, const webgl::TexUnpackBlob* blob);
|
||||
public:
|
||||
void CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
|
@ -55,6 +55,33 @@ namespace mozilla {
|
||||
* height)
|
||||
*/
|
||||
|
||||
static bool
|
||||
ValidateExtents(WebGLContext* webgl, const char* funcName, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border, uint32_t* const out_width,
|
||||
uint32_t* const out_height, uint32_t* const out_depth)
|
||||
{
|
||||
// Check border
|
||||
if (border != 0) {
|
||||
webgl->ErrorInvalidValue("%s: `border` must be 0.", funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width < 0 || height < 0 || depth < 0) {
|
||||
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
|
||||
* "If wt and ht are the specified image width and height,
|
||||
* and if either wt or ht are less than zero, then the error
|
||||
* INVALID_VALUE is generated."
|
||||
*/
|
||||
webgl->ErrorInvalidValue("%s: `width`/`height`/`depth` must be >= 0.", funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_width = width;
|
||||
*out_height = height;
|
||||
*out_depth = depth;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// ArrayBufferView?
|
||||
|
||||
@ -98,82 +125,165 @@ DoesJSTypeMatchUnpackType(GLenum unpackType, js::Scalar::Type jsType)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ValidateUnpackArrayType(WebGLContext* webgl, const char* funcName, GLenum unpackType,
|
||||
js::Scalar::Type jsType)
|
||||
bool
|
||||
WebGLContext::ValidateUnpackPixels(const char* funcName, uint32_t fullRows,
|
||||
uint32_t tailPixels, const webgl::TexUnpackBlob* blob)
|
||||
{
|
||||
if (DoesJSTypeMatchUnpackType(unpackType, jsType))
|
||||
return true;
|
||||
const auto usedPixelsPerRow = CheckedUint32(blob->mSkipPixels) + blob->mWidth;
|
||||
const auto usedRowsPerImage = CheckedUint32(blob->mSkipRows) + blob->mHeight;
|
||||
const auto usedImages = CheckedUint32(blob->mSkipImages) + blob->mDepth;
|
||||
|
||||
const auto& fua = webgl->mFormatUsage;
|
||||
const GLenum fakeUnpackFormat = LOCAL_GL_RGBA;
|
||||
if (!fua->AreUnpackEnumsValid(fakeUnpackFormat, unpackType)) {
|
||||
webgl->ErrorInvalidEnum("%s: Invalid unpack type: 0x%04x", funcName, unpackType);
|
||||
if (!usedPixelsPerRow.isValid() ||
|
||||
!usedRowsPerImage.isValid() ||
|
||||
!usedImages.isValid())
|
||||
{
|
||||
ErrorOutOfMemory("%s: Invalid calculation for e.g. UNPACK_SKIP_PIXELS + width.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
webgl->ErrorInvalidOperation("%s: `pixels` be compatible with unpack `type`.",
|
||||
funcName);
|
||||
//////
|
||||
|
||||
if (usedPixelsPerRow.value() > blob->mRowLength ||
|
||||
usedRowsPerImage.value() > blob->mImageHeight)
|
||||
{
|
||||
ErrorInvalidOperation("%s: UNPACK_ROW_LENGTH or UNPACK_IMAGE_HEIGHT too small.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
auto fullRowsNeeded = (usedImages - 1) * blob->mImageHeight;
|
||||
fullRowsNeeded += usedRowsPerImage - 1;
|
||||
|
||||
if (!fullRowsNeeded.isValid()) {
|
||||
ErrorOutOfMemory("%s: Invalid calculation for required row count.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fullRows > fullRowsNeeded.value())
|
||||
return true;
|
||||
|
||||
if (fullRows == fullRowsNeeded.value() && tailPixels >= usedPixelsPerRow.value())
|
||||
return true;
|
||||
|
||||
ErrorInvalidOperation("%s: Desired upload requires more data than is available: (%u"
|
||||
" rows plus %u pixels needed, %u rows plus %u pixels"
|
||||
" available)",
|
||||
funcName, fullRowsNeeded.value(), usedPixelsPerRow.value(),
|
||||
fullRows, tailPixels);
|
||||
return false;
|
||||
}
|
||||
|
||||
static UniquePtr<webgl::TexUnpackBlob>
|
||||
UnpackBlobFromMaybeView(WebGLContext* webgl, const char* funcName, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView)
|
||||
BlobFromView(WebGLContext* webgl, const char* funcName, uint32_t width, uint32_t height,
|
||||
uint32_t depth, const webgl::PackingInfo& pi,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView)
|
||||
{
|
||||
size_t dataSize;
|
||||
const void* data;
|
||||
if (maybeView.IsNull()) {
|
||||
dataSize = 0;
|
||||
data = nullptr;
|
||||
} else {
|
||||
const void* bytes = nullptr;
|
||||
uint32_t byteCount = 0;
|
||||
|
||||
if (!maybeView.IsNull()) {
|
||||
const auto& view = maybeView.Value();
|
||||
view.ComputeLengthAndData();
|
||||
data = view.DataAllowShared();
|
||||
dataSize = view.LengthAllowShared();
|
||||
js::Scalar::Type jsType = JS_GetArrayBufferViewType(view.Obj());
|
||||
if (!ValidateUnpackArrayType(webgl, funcName, unpackType, jsType))
|
||||
|
||||
const auto jsType = JS_GetArrayBufferViewType(view.Obj());
|
||||
if (!DoesJSTypeMatchUnpackType(pi.type, jsType)) {
|
||||
webgl->ErrorInvalidOperation("%s: `pixels` must be compatible with `type`.",
|
||||
funcName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (width && height && depth) {
|
||||
view.ComputeLengthAndData();
|
||||
|
||||
bytes = view.DataAllowShared();
|
||||
byteCount = view.LengthAllowShared();
|
||||
}
|
||||
}
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob> ret;
|
||||
// Warning: Possibly shared memory. See bug 1225033.
|
||||
ret.reset(new webgl::TexUnpackBytes(width, height, depth, dataSize, data));
|
||||
return Move(ret);
|
||||
UniquePtr<webgl::TexUnpackBlob> blob(new webgl::TexUnpackBytes(webgl, width, height,
|
||||
depth, bytes));
|
||||
|
||||
//////
|
||||
|
||||
if (bytes) {
|
||||
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
|
||||
const auto bytesPerRow = CheckedUint32(blob->mRowLength) * bytesPerPixel;
|
||||
const auto rowStride = RoundUpToMultipleOf(bytesPerRow, blob->mAlignment);
|
||||
|
||||
const auto fullRows = byteCount / rowStride;
|
||||
if (!fullRows.isValid()) {
|
||||
webgl->ErrorOutOfMemory("%s: Unacceptable upload size calculated.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto bodyBytes = fullRows.value() * rowStride.value();
|
||||
const auto tailPixels = (byteCount - bodyBytes) / bytesPerPixel;
|
||||
|
||||
if (!webgl->ValidateUnpackPixels(funcName, fullRows.value(), tailPixels,
|
||||
blob.get()))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
return Move(blob);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateUnpackInfo(const char* funcName, GLenum format, GLenum type,
|
||||
webgl::PackingInfo* const out)
|
||||
{
|
||||
if (!mFormatUsage->AreUnpackEnumsValid(format, type)) {
|
||||
ErrorInvalidEnum("%s: Invalid unpack format/type: 0x%04x/0x%04x", funcName,
|
||||
format, type);
|
||||
return false;
|
||||
}
|
||||
|
||||
out->format = format;
|
||||
out->type = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
GLint yOffset, GLint zOffset, GLsizei rawWidth,
|
||||
GLsizei rawHeight, GLsizei rawDepth, GLint border,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView)
|
||||
{
|
||||
UniquePtr<webgl::TexUnpackBlob> blob;
|
||||
blob = UnpackBlobFromMaybeView(mContext, funcName, width, height, depth, unpackType,
|
||||
uint32_t width, height, depth;
|
||||
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
|
||||
&width, &height, &depth))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
webgl::PackingInfo pi;
|
||||
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
|
||||
return;
|
||||
|
||||
const auto blob = BlobFromView(mContext, funcName, width, height, depth, pi,
|
||||
maybeView);
|
||||
if (!blob)
|
||||
return;
|
||||
|
||||
TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset, yOffset,
|
||||
zOffset, border, unpackFormat, unpackType, blob.get());
|
||||
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, pi, blob.get());
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// ImageData
|
||||
|
||||
static UniquePtr<webgl::TexUnpackBlob>
|
||||
UnpackBlobFromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
|
||||
dom::ImageData* imageData, dom::Uint8ClampedArray* scopedArr)
|
||||
static already_AddRefed<gfx::SourceSurface>
|
||||
FromImageData(WebGLContext* webgl, const char* funcName, GLenum unpackType,
|
||||
dom::ImageData* imageData, dom::Uint8ClampedArray* scopedArr)
|
||||
{
|
||||
if (!imageData) {
|
||||
// Spec says to generate an INVALID_VALUE error
|
||||
webgl->ErrorInvalidValue("%s: null ImageData", funcName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DebugOnly<bool> inited = scopedArr->Init(imageData->GetDataObject());
|
||||
MOZ_ASSERT(inited);
|
||||
|
||||
@ -189,20 +299,46 @@ UnpackBlobFromImageData(WebGLContext* webgl, const char* funcName, GLenum unpack
|
||||
|
||||
uint8_t* wrappableData = (uint8_t*)data;
|
||||
|
||||
const RefPtr<gfx::SourceSurface> surf =
|
||||
RefPtr<gfx::SourceSurface> surf =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(wrappableData,
|
||||
stride,
|
||||
size,
|
||||
surfFormat);
|
||||
if (!surf) {
|
||||
webgl->ErrorOutOfMemory("%s: OOM in FromImageData.", funcName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
const bool surfIsAlphaPremult = false;
|
||||
return surf.forget();
|
||||
}
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob> ret;
|
||||
ret.reset(new webgl::TexUnpackSurface(surf, surfIsAlphaPremult));
|
||||
return Move(ret);
|
||||
bool
|
||||
WebGLContext::GetUnpackValuesForImage(const char* funcName, uint32_t srcImageWidth,
|
||||
uint32_t srcImageHeight,
|
||||
uint32_t* const out_rowLength,
|
||||
uint32_t* const out_imageHeight)
|
||||
{
|
||||
uint32_t rowLength = mPixelStore_UnpackRowLength;
|
||||
if (!rowLength) {
|
||||
rowLength = srcImageWidth;
|
||||
} else if (rowLength != srcImageWidth) {
|
||||
ErrorInvalidOperation("%s: UNPACK_ROW_LENGTH, if set, must be == width of"
|
||||
" object.");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t imageHeight = mPixelStore_UnpackImageHeight;
|
||||
if (!imageHeight) {
|
||||
imageHeight = srcImageHeight;
|
||||
} else if (imageHeight > srcImageHeight) {
|
||||
ErrorInvalidOperation("%s: UNPACK_IMAGE_HEIGHT, if set, must be <= height of"
|
||||
" object");
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_rowLength = rowLength;
|
||||
*out_imageHeight = imageHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -211,17 +347,50 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
|
||||
GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::ImageData* imageData)
|
||||
{
|
||||
dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(
|
||||
nsContentUtils::RootingCxForThread());
|
||||
|
||||
UniquePtr<webgl::TexUnpackBlob> blob;
|
||||
blob = UnpackBlobFromImageData(mContext, funcName, unpackType, imageData, &scopedArr);
|
||||
if (!blob)
|
||||
webgl::PackingInfo pi;
|
||||
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
|
||||
return;
|
||||
|
||||
const GLint border = 0;
|
||||
TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset, yOffset,
|
||||
zOffset, border, unpackFormat, unpackType, blob.get());
|
||||
if (!imageData) {
|
||||
// Spec says to generate an INVALID_VALUE error
|
||||
mContext->ErrorInvalidValue("%s: Null ImageData.", funcName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Eventually, these will be args.
|
||||
const uint32_t width = imageData->Width();
|
||||
const uint32_t height = imageData->Height();
|
||||
const uint32_t depth = 1;
|
||||
|
||||
uint32_t rowLength, imageHeight;
|
||||
if (!mContext->GetUnpackValuesForImage(funcName, imageData->Width(),
|
||||
imageData->Height(), &rowLength, &imageHeight))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dom::RootedTypedArray<dom::Uint8ClampedArray> scopedArr(
|
||||
nsContentUtils::RootingCxForThread());
|
||||
const RefPtr<gfx::SourceSurface> surf = FromImageData(mContext, funcName, unpackType,
|
||||
imageData, &scopedArr);
|
||||
if (!surf)
|
||||
return;
|
||||
|
||||
// WhatWG "HTML Living Standard" (30 October 2015):
|
||||
// "The getImageData(sx, sy, sw, sh) method [...] Pixels must be returned as
|
||||
// non-premultiplied alpha values."
|
||||
const bool surfIsAlphaPremult = false;
|
||||
|
||||
const webgl::TexUnpackSurface blob(mContext, imageHeight, width, height, depth, surf,
|
||||
surfIsAlphaPremult);
|
||||
|
||||
const uint32_t fullRows = imageData->Height();
|
||||
const uint32_t tailPixels = 0;
|
||||
if (!mContext->ValidateUnpackPixels(funcName, fullRows, tailPixels, &blob))
|
||||
return;
|
||||
|
||||
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, pi, &blob);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
@ -234,78 +403,113 @@ WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarge
|
||||
GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_error)
|
||||
{
|
||||
webgl::PackingInfo pi;
|
||||
if (!mContext->ValidateUnpackInfo(funcName, unpackFormat, unpackType, &pi))
|
||||
return;
|
||||
|
||||
auto sfer = mContext->SurfaceFromElement(elem);
|
||||
|
||||
uint32_t elemWidth = 0;
|
||||
uint32_t elemHeight = 0;
|
||||
layers::Image* layersImage = nullptr;
|
||||
if (!gfxPrefs::WebGLDisableDOMBlitUploads() && sfer.mLayersImage) {
|
||||
layersImage = sfer.mLayersImage;
|
||||
elemWidth = layersImage->GetSize().width;
|
||||
elemHeight = layersImage->GetSize().height;
|
||||
}
|
||||
|
||||
gfx::SourceSurface* surf = nullptr;
|
||||
if (!layersImage && sfer.GetSourceSurface()) {
|
||||
surf = sfer.GetSourceSurface();
|
||||
elemWidth = surf->GetSize().width;
|
||||
elemHeight = surf->GetSize().height;
|
||||
}
|
||||
|
||||
// Eventually, these will be args.
|
||||
const uint32_t width = elemWidth;
|
||||
const uint32_t height = elemHeight;
|
||||
const uint32_t depth = 1;
|
||||
|
||||
// While it's counter-intuitive, the shape of the SFEResult API means that we should
|
||||
// try to pull out a surface first, and then, if we do pull out a surface, check
|
||||
// CORS/write-only/etc..
|
||||
UniquePtr<webgl::TexUnpackBlob> blob;
|
||||
const bool isAlphaPremult = sfer.mIsPremultiplied;
|
||||
|
||||
const auto& layersImage = sfer.mLayersImage;
|
||||
if (layersImage && !gfxPrefs::WebGLDisableDOMBlitUploads()) {
|
||||
blob.reset(new webgl::TexUnpackImage(layersImage, isAlphaPremult));
|
||||
} else if (sfer.GetSourceSurface()) {
|
||||
blob.reset(new webgl::TexUnpackSurface(sfer.GetSourceSurface(), isAlphaPremult));
|
||||
if (!layersImage && !surf) {
|
||||
webgl::TexUnpackBytes blob(mContext, width, height, depth, nullptr);
|
||||
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, pi, &blob);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blob) {
|
||||
if (!sfer.mCORSUsed) {
|
||||
auto& srcPrincipal = sfer.mPrincipal;
|
||||
nsIPrincipal* dstPrincipal = mContext->GetCanvas()->NodePrincipal();
|
||||
//////
|
||||
|
||||
if (!dstPrincipal->Subsumes(srcPrincipal)) {
|
||||
mContext->GenerateWarning("%s: Cross-origin elements require CORS.",
|
||||
funcName);
|
||||
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!sfer.mCORSUsed) {
|
||||
auto& srcPrincipal = sfer.mPrincipal;
|
||||
nsIPrincipal* dstPrincipal = mContext->GetCanvas()->NodePrincipal();
|
||||
|
||||
if (sfer.mIsWriteOnly) {
|
||||
// mIsWriteOnly defaults to true, and so will be true even if SFE merely
|
||||
// failed. Thus we must test mIsWriteOnly after successfully retrieving an
|
||||
// Image or SourceSurface.
|
||||
mContext->GenerateWarning("%s: Element is write-only, thus cannot be"
|
||||
" uploaded.",
|
||||
if (!dstPrincipal->Subsumes(srcPrincipal)) {
|
||||
mContext->GenerateWarning("%s: Cross-origin elements require CORS.",
|
||||
funcName);
|
||||
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mContext->GenerateWarning("%s: Failed to get data from DOM element. Implicit"
|
||||
" width and height for this upload will be zero.",
|
||||
funcName);
|
||||
|
||||
const uint32_t width = 0;
|
||||
const uint32_t height = 0;
|
||||
const uint32_t depth = 1; // Implicit depth for DOM uploads is always 1.
|
||||
const size_t byteCount = 0;
|
||||
blob.reset(new webgl::TexUnpackBytes(width, height, depth, byteCount, nullptr));
|
||||
}
|
||||
MOZ_ASSERT(blob);
|
||||
|
||||
const GLint border = 0;
|
||||
TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset, yOffset,
|
||||
zOffset, border, unpackFormat, unpackType, blob.get());
|
||||
if (sfer.mIsWriteOnly) {
|
||||
// mIsWriteOnly defaults to true, and so will be true even if SFE merely
|
||||
// failed. Thus we must test mIsWriteOnly after successfully retrieving an
|
||||
// Image or SourceSurface.
|
||||
mContext->GenerateWarning("%s: Element is write-only, thus cannot be"
|
||||
" uploaded.",
|
||||
funcName);
|
||||
out_error->Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
//////
|
||||
// Ok, we're good!
|
||||
|
||||
uint32_t rowLength, imageHeight;
|
||||
if (!mContext->GetUnpackValuesForImage(funcName, elemWidth, elemHeight, &rowLength,
|
||||
&imageHeight))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UniquePtr<const webgl::TexUnpackBlob> blob;
|
||||
const bool isAlphaPremult = sfer.mIsPremultiplied;
|
||||
|
||||
if (layersImage) {
|
||||
blob.reset(new webgl::TexUnpackImage(mContext, imageHeight, width, height, depth,
|
||||
layersImage, isAlphaPremult));
|
||||
} else {
|
||||
MOZ_ASSERT(surf);
|
||||
blob.reset(new webgl::TexUnpackSurface(mContext, imageHeight, width, height,
|
||||
depth, surf, isAlphaPremult));
|
||||
}
|
||||
|
||||
const uint32_t fullRows = elemHeight;
|
||||
const uint32_t tailPixels = 0;
|
||||
if (!mContext->ValidateUnpackPixels(funcName, fullRows, tailPixels, blob.get()))
|
||||
return;
|
||||
|
||||
TexOrSubImageBlob(isSubImage, funcName, target, level, internalFormat, xOffset,
|
||||
yOffset, zOffset, pi, blob.get());
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
WebGLTexture::TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
|
||||
GLint level, GLenum internalFormat, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLint border,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
webgl::TexUnpackBlob* blob)
|
||||
WebGLTexture::TexOrSubImageBlob(bool isSubImage, const char* funcName,
|
||||
TexImageTarget target, GLint level, GLenum internalFormat,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
const webgl::PackingInfo& pi,
|
||||
const webgl::TexUnpackBlob* blob)
|
||||
{
|
||||
if (isSubImage) {
|
||||
TexSubImage(funcName, target, level, xOffset, yOffset, zOffset, unpackFormat,
|
||||
unpackType, blob);
|
||||
TexSubImage(funcName, target, level, xOffset, yOffset, zOffset, pi, blob);
|
||||
} else {
|
||||
TexImage(funcName, target, level, internalFormat, border, unpackFormat,
|
||||
unpackType, blob);
|
||||
TexImage(funcName, target, level, internalFormat, pi, blob);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,12 +538,11 @@ ValidateTexImage(WebGLContext* webgl, WebGLTexture* texture, const char* funcNam
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// For *TexImage*
|
||||
bool
|
||||
WebGLTexture::ValidateTexImageSpecification(const char* funcName, TexImageTarget target,
|
||||
GLint level, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
GLint level, uint32_t width, uint32_t height,
|
||||
uint32_t depth,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo)
|
||||
{
|
||||
if (mImmutable) {
|
||||
@ -352,23 +555,6 @@ WebGLTexture::ValidateTexImageSpecification(const char* funcName, TexImageTarget
|
||||
if (!ValidateTexImage(mContext, this, funcName, target, level, &imageInfo))
|
||||
return false;
|
||||
|
||||
// Check border
|
||||
if (border != 0) {
|
||||
mContext->ErrorInvalidValue("%s: `border` must be 0.", funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width < 0 || height < 0 || depth < 0) {
|
||||
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
|
||||
* "If wt and ht are the specified image width and height,
|
||||
* and if either wt or ht are less than zero, then the error
|
||||
* INVALID_VALUE is generated."
|
||||
*/
|
||||
mContext->ErrorInvalidValue("%s: `width`/`height`/`depth` must be >= 0.",
|
||||
funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP &&
|
||||
width != height)
|
||||
{
|
||||
@ -419,9 +605,9 @@ WebGLTexture::ValidateTexImageSpecification(const char* funcName, TexImageTarget
|
||||
break;
|
||||
}
|
||||
|
||||
if (uint32_t(width) > maxWidthHeight ||
|
||||
uint32_t(height) > maxWidthHeight ||
|
||||
uint32_t(depth) > maxDepth)
|
||||
if (width > maxWidthHeight ||
|
||||
height > maxWidthHeight ||
|
||||
depth > maxDepth)
|
||||
{
|
||||
mContext->ErrorInvalidValue("%s: Requested size at this level is unsupported.",
|
||||
funcName);
|
||||
@ -439,7 +625,7 @@ WebGLTexture::ValidateTexImageSpecification(const char* funcName, TexImageTarget
|
||||
bool requirePOT = (!mContext->IsWebGL2() && level != 0);
|
||||
|
||||
if (requirePOT) {
|
||||
if (!IsPowerOfTwo(uint32_t(width)) || !IsPowerOfTwo(uint32_t(height))) {
|
||||
if (!IsPowerOfTwo(width) || !IsPowerOfTwo(height)) {
|
||||
mContext->ErrorInvalidValue("%s: For level > 0, width and height must be"
|
||||
" powers of two.",
|
||||
funcName);
|
||||
@ -456,15 +642,13 @@ WebGLTexture::ValidateTexImageSpecification(const char* funcName, TexImageTarget
|
||||
bool
|
||||
WebGLTexture::ValidateTexImageSelection(const char* funcName, TexImageTarget target,
|
||||
GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth,
|
||||
GLint zOffset, uint32_t width, uint32_t height,
|
||||
uint32_t depth,
|
||||
WebGLTexture::ImageInfo** const out_imageInfo)
|
||||
{
|
||||
// The conformance test wants bad arg checks before imageInfo checks.
|
||||
if (xOffset < 0 || yOffset < 0 || zOffset < 0 ||
|
||||
width < 0 || height < 0 || depth < 0)
|
||||
{
|
||||
mContext->ErrorInvalidValue("%s: Offsets and dimensions must be >=0.", funcName);
|
||||
if (xOffset < 0 || yOffset < 0 || zOffset < 0) {
|
||||
mContext->ErrorInvalidValue("%s: Offsets must be >=0.", funcName);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -718,8 +902,10 @@ DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffs
|
||||
static inline GLenum
|
||||
DoCompressedTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLsizei dataSize, const void* data)
|
||||
GLsizei dataSize, const void* data)
|
||||
{
|
||||
const GLint border = 0;
|
||||
|
||||
gl::GLContext::LocalErrorScope errorScope(*gl);
|
||||
|
||||
if (Is3D(target)) {
|
||||
@ -758,9 +944,10 @@ DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level,
|
||||
|
||||
static inline GLenum
|
||||
DoCopyTexImage2D(gl::GLContext* gl, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint border)
|
||||
GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
{
|
||||
const GLint border = 0;
|
||||
|
||||
gl::GLContext::LocalErrorScope errorScope(*gl);
|
||||
|
||||
MOZ_ASSERT(!Is3D(target));
|
||||
@ -928,11 +1115,10 @@ WebGLTexture::TexStorage(const char* funcName, TexTarget target, GLsizei levels,
|
||||
const TexImageTarget testTarget = IsCubeMap() ? LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
|
||||
: target.get();
|
||||
const GLint testLevel = 0;
|
||||
const GLint border = 0;
|
||||
|
||||
WebGLTexture::ImageInfo* testImageInfo;
|
||||
if (!ValidateTexImageSpecification(funcName, testTarget, testLevel, width, height,
|
||||
depth, border, &testImageInfo))
|
||||
depth, &testImageInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -1015,39 +1201,30 @@ WebGLTexture::TexStorage(const char* funcName, TexTarget target, GLsizei levels,
|
||||
|
||||
void
|
||||
WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType, webgl::TexUnpackBlob* blob)
|
||||
GLenum internalFormat, const webgl::PackingInfo& pi,
|
||||
const webgl::TexUnpackBlob* blob)
|
||||
{
|
||||
////////////////////////////////////
|
||||
// Get dest info
|
||||
|
||||
WebGLTexture::ImageInfo* imageInfo;
|
||||
if (!ValidateTexImageSpecification(funcName, target, level, blob->mWidth,
|
||||
blob->mHeight, blob->mDepth, border, &imageInfo))
|
||||
blob->mHeight, blob->mDepth, &imageInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(imageInfo);
|
||||
|
||||
const webgl::PackingInfo srcPacking = { unpackFormat, unpackType };
|
||||
|
||||
const auto& fua = mContext->mFormatUsage;
|
||||
if (!fua->IsInternalFormatEnumValid(internalFormat)) {
|
||||
mContext->ErrorInvalidValue("%s: Invalid internalformat: 0x%04x",
|
||||
funcName, internalFormat);
|
||||
return;
|
||||
}
|
||||
|
||||
auto dstUsage = fua->GetSizedTexUsage(internalFormat);
|
||||
if (!dstUsage) {
|
||||
if (internalFormat != unpackFormat) {
|
||||
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
|
||||
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
|
||||
" 0x%04x/0x%04x",
|
||||
funcName, unpackFormat, unpackType);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fua->IsInternalFormatEnumValid(internalFormat)) {
|
||||
mContext->ErrorInvalidValue("%s: Invalid internalformat: 0x%04x",
|
||||
funcName, internalFormat);
|
||||
return;
|
||||
}
|
||||
|
||||
if (internalFormat != pi.format) {
|
||||
/* GL ES Version 3.0.4 - 3.8.3 Texture Image Specification
|
||||
* "Specifying a combination of values for format, type, and
|
||||
* internalformat that is not listed as a valid combination
|
||||
@ -1059,45 +1236,24 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
return;
|
||||
}
|
||||
|
||||
dstUsage = fua->GetUnsizedTexUsage(srcPacking);
|
||||
dstUsage = fua->GetUnsizedTexUsage(pi);
|
||||
}
|
||||
|
||||
if (!dstUsage) {
|
||||
if (!fua->IsInternalFormatEnumValid(internalFormat)) {
|
||||
mContext->ErrorInvalidValue("%s: Invalid internalformat: 0x%04x",
|
||||
funcName, internalFormat);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
|
||||
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
|
||||
" 0x%04x/0x%04x",
|
||||
funcName, unpackFormat, unpackType);
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->ErrorInvalidOperation("%s: Invalid internalformat/format/type:"
|
||||
" 0x%04x/0x%04x/0x%04x",
|
||||
funcName, internalFormat, unpackFormat,
|
||||
unpackType);
|
||||
funcName, internalFormat, pi.format, pi.type);
|
||||
return;
|
||||
}
|
||||
|
||||
const webgl::DriverUnpackInfo* driverUnpackInfo;
|
||||
if (!dstUsage->IsUnpackValid(srcPacking, &driverUnpackInfo)) {
|
||||
if (!dstUsage->IsUnpackValid(pi, &driverUnpackInfo)) {
|
||||
mContext->ErrorInvalidOperation("%s: Mismatched internalFormat and format/type:"
|
||||
" 0x%04x and 0x%04x/0x%04x",
|
||||
funcName, internalFormat, unpackFormat,
|
||||
unpackType);
|
||||
funcName, internalFormat, pi.format, pi.type);
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Get source info
|
||||
const bool isFunc3D = Is3D(target);
|
||||
if (!blob->ValidateUnpack(mContext, funcName, isFunc3D, srcPacking))
|
||||
return;
|
||||
|
||||
////////////////////////////////////
|
||||
// Check that source and dest info are compatible
|
||||
auto dstFormat = dstUsage->format;
|
||||
@ -1167,8 +1323,7 @@ WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
void
|
||||
WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
webgl::TexUnpackBlob* blob)
|
||||
const webgl::PackingInfo& pi, const webgl::TexUnpackBlob* blob)
|
||||
{
|
||||
////////////////////////////////////
|
||||
// Get dest info
|
||||
@ -1200,28 +1355,14 @@ WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint lev
|
||||
////////////////////////////////////
|
||||
// Get source info
|
||||
|
||||
const webgl::PackingInfo srcPacking = { unpackFormat, unpackType };
|
||||
const webgl::DriverUnpackInfo* driverUnpackInfo;
|
||||
if (!dstUsage->IsUnpackValid(srcPacking, &driverUnpackInfo)) {
|
||||
const auto& fua = mContext->mFormatUsage;
|
||||
if (!fua->AreUnpackEnumsValid(unpackFormat, unpackType)) {
|
||||
mContext->ErrorInvalidEnum("%s: Invalid unpack format/type:"
|
||||
" 0x%04x/0x%04x",
|
||||
funcName, unpackFormat, unpackType);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dstUsage->IsUnpackValid(pi, &driverUnpackInfo)) {
|
||||
mContext->ErrorInvalidOperation("%s: Mismatched internalFormat and format/type:"
|
||||
" %s and 0x%04x/0x%04x",
|
||||
funcName, dstFormat->name, unpackFormat,
|
||||
unpackType);
|
||||
funcName, dstFormat->name, pi.format, pi.type);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isFunc3D = Is3D(target);
|
||||
if (!blob->ValidateUnpack(mContext, funcName, isFunc3D, srcPacking))
|
||||
return;
|
||||
|
||||
////////////////////////////////////
|
||||
// Do the thing!
|
||||
|
||||
@ -1269,16 +1410,23 @@ WebGLTexture::TexSubImage(const char* funcName, TexImageTarget target, GLint lev
|
||||
|
||||
void
|
||||
WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
GLenum internalFormat, GLsizei rawWidth,
|
||||
GLsizei rawHeight, GLsizei rawDepth, GLint border,
|
||||
const dom::ArrayBufferView& view)
|
||||
{
|
||||
uint32_t width, height, depth;
|
||||
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, border,
|
||||
&width, &height, &depth))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Get dest info
|
||||
|
||||
WebGLTexture::ImageInfo* imageInfo;
|
||||
if (!ValidateTexImageSpecification(funcName, target, level, width, height, depth,
|
||||
border, &imageInfo))
|
||||
&imageInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -1330,7 +1478,7 @@ WebGLTexture::CompressedTexImage(const char* funcName, TexImageTarget target, GL
|
||||
|
||||
// Warning: Possibly shared memory. See bug 1225033.
|
||||
GLenum error = DoCompressedTexImage(mContext->gl, target, level, internalFormat,
|
||||
width, height, depth, border, dataSize, data);
|
||||
width, height, depth, dataSize, data);
|
||||
if (error == LOCAL_GL_OUT_OF_MEMORY) {
|
||||
mContext->ErrorOutOfMemory("%s: Ran out of memory during upload.", funcName);
|
||||
return;
|
||||
@ -1375,10 +1523,17 @@ IsSubImageBlockAligned(const webgl::CompressedFormatInfo* compression,
|
||||
void
|
||||
WebGLTexture::CompressedTexSubImage(const char* funcName, TexImageTarget target,
|
||||
GLint level, GLint xOffset, GLint yOffset,
|
||||
GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLenum sizedUnpackFormat,
|
||||
GLint zOffset, GLsizei rawWidth, GLsizei rawHeight,
|
||||
GLsizei rawDepth, GLenum sizedUnpackFormat,
|
||||
const dom::ArrayBufferView& view)
|
||||
{
|
||||
uint32_t width, height, depth;
|
||||
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, rawDepth, 0, &width,
|
||||
&height, &depth))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Get dest info
|
||||
|
||||
@ -1698,19 +1853,24 @@ ScopedCopyTexImageSource::~ScopedCopyTexImageSource()
|
||||
// There is no CopyTexImage3D.
|
||||
void
|
||||
WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeight,
|
||||
GLint border)
|
||||
{
|
||||
const char funcName[] = "CopyTexImage2D";
|
||||
|
||||
const uint8_t depth = 1;
|
||||
|
||||
////////////////////////////////////
|
||||
// Get dest info
|
||||
|
||||
uint32_t width, height, depth;
|
||||
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, 1, border, &width,
|
||||
&height, &depth))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLTexture::ImageInfo* imageInfo;
|
||||
if (!ValidateTexImageSpecification(funcName, target, level, width, height, depth,
|
||||
border, &imageInfo))
|
||||
&imageInfo))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -1800,8 +1960,8 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
|
||||
GLenum error;
|
||||
if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height)) {
|
||||
MOZ_ASSERT(dstUsage->idealUnpack);
|
||||
error = DoCopyTexImage2D(gl, target, level, dstUsage->idealUnpack->internalFormat, x, y, width, height,
|
||||
border);
|
||||
error = DoCopyTexImage2D(gl, target, level, dstUsage->idealUnpack->internalFormat,
|
||||
x, y, width, height);
|
||||
} else {
|
||||
// 1. Zero the texture data.
|
||||
// 2. CopyTexSubImage the subrect.
|
||||
@ -1851,9 +2011,14 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
|
||||
void
|
||||
WebGLTexture::CopyTexSubImage(const char* funcName, TexImageTarget target, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset, GLint x,
|
||||
GLint y, GLsizei width, GLsizei height)
|
||||
GLint y, GLsizei rawWidth, GLsizei rawHeight)
|
||||
{
|
||||
const GLsizei depth = 1;
|
||||
uint32_t width, height, depth;
|
||||
if (!ValidateExtents(mContext, funcName, rawWidth, rawHeight, 1, 0, &width,
|
||||
&height, &depth))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Get dest info
|
||||
|
@ -37,9 +37,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=332246
|
||||
|
||||
/** Test for Bug 332246 **/
|
||||
|
||||
function isWithFuzz(itIs, itShouldBe, fuzz, description) {
|
||||
ok(Math.abs(itIs - itShouldBe) <= fuzz, `${description} - expected a value between ${itShouldBe - fuzz} and ${itShouldBe + fuzz}, got ${itIs}`);
|
||||
}
|
||||
|
||||
var a1 = document.getElementById('a1');
|
||||
var a2 = document.getElementById('a2');
|
||||
is(a1.scrollHeight, 400, "Wrong a1.scrollHeight");
|
||||
isWithFuzz(a1.scrollHeight, 400, 1, "Wrong a1.scrollHeight");
|
||||
is(a1.offsetHeight, 100, "Wrong a1.offsetHeight");
|
||||
a2.scrollIntoView(true);
|
||||
is(a1.scrollTop, 100, "Wrong scrollTop value after a2.scrollIntoView(true)");
|
||||
@ -48,7 +52,7 @@ is(a1.scrollTop, 200, "Wrong scrollTop value after a2.scrollIntoView(false)");
|
||||
|
||||
var b1 = document.getElementById('b1');
|
||||
var b2 = document.getElementById('b2');
|
||||
is(b1.scrollHeight, 420, "Wrong b1.scrollHeight");
|
||||
isWithFuzz(b1.scrollHeight, 420, 1, "Wrong b1.scrollHeight");
|
||||
is(b1.offsetHeight, 100, "Wrong b1.offsetHeight");
|
||||
b2.scrollIntoView(true);
|
||||
is(b1.scrollTop, 100, "Wrong scrollTop value after b2.scrollIntoView(true)");
|
||||
@ -57,12 +61,12 @@ is(b1.scrollTop, 220, "Wrong scrollTop value after b2.scrollIntoView(false)");
|
||||
|
||||
var c1 = document.getElementById('c1');
|
||||
var c2 = document.getElementById('c2');
|
||||
is(c1.scrollHeight, 320, "Wrong c1.scrollHeight");
|
||||
isWithFuzz(c1.scrollHeight, 320, 1, "Wrong c1.scrollHeight");
|
||||
is(c1.offsetHeight, 100, "Wrong c1.offsetHeight");
|
||||
c2.scrollIntoView(true);
|
||||
is(c1.scrollTop, 100, "Wrong scrollTop value after c2.scrollIntoView(true)");
|
||||
c2.scrollIntoView(false);
|
||||
is(c1.scrollTop, 220, "Wrong scrollTop value after c2.scrollIntoView(false)");
|
||||
isWithFuzz(c1.scrollTop, 220, 1, "Wrong scrollTop value after c2.scrollIntoView(false)");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -1485,7 +1485,7 @@ void MediaDecoderStateMachine::ReaderSuspendedChanged()
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
DECODER_LOG("ReaderSuspendedChanged: suspended = %d", mIsReaderSuspended.Ref());
|
||||
|
||||
if (!HasVideo() || mIsReaderSuspended || IsDecodingFirstFrame()) {
|
||||
if (IsShutdown() || !HasVideo() || mIsReaderSuspended || IsDecodingFirstFrame()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -75,9 +75,6 @@
|
||||
#include "MediaPermissionGonk.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#include "nsCocoaFeatures.h"
|
||||
#endif
|
||||
#if defined (XP_WIN)
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include <winsock2.h>
|
||||
@ -2128,24 +2125,17 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
|
||||
case MediaSourceEnum::Window:
|
||||
// Deny screensharing request if support is disabled, or
|
||||
// the requesting document is not from a host on the whitelist, or
|
||||
// we're on Mac OSX 10.6 and WinXP until proved that they work
|
||||
// we're on WinXP until proved that it works
|
||||
if (!Preferences::GetBool(((videoType == MediaSourceEnum::Browser)?
|
||||
"media.getusermedia.browser.enabled" :
|
||||
"media.getusermedia.screensharing.enabled"),
|
||||
false) ||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
#if defined(XP_WIN)
|
||||
(
|
||||
// Allow tab sharing for all platforms including XP and OSX 10.6
|
||||
// Allow tab sharing for all platforms including XP
|
||||
(videoType != MediaSourceEnum::Browser) &&
|
||||
!Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms",
|
||||
false) &&
|
||||
#if defined(XP_MACOSX)
|
||||
!nsCocoaFeatures::OnLionOrLater()
|
||||
#endif
|
||||
#if defined (XP_WIN)
|
||||
!IsVistaOrLater()
|
||||
#endif
|
||||
) ||
|
||||
false) && !IsVistaOrLater()) ||
|
||||
#endif
|
||||
(!privileged && !HostIsHttps(*docURI)) ||
|
||||
!(loop || HostHasPermission(*docURI))) {
|
||||
|
@ -17,9 +17,6 @@
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "WMFDecoderModule.h"
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
#include "nsCocoaFeatures.h"
|
||||
#endif
|
||||
#include "nsContentCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozIGeckoMediaPluginService.h"
|
||||
@ -291,12 +288,6 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
|
||||
aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME");
|
||||
return MediaKeySystemStatus::Cdm_not_supported;
|
||||
}
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
if (!nsCocoaFeatures::OnLionOrLater()) {
|
||||
aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Adobe EME");
|
||||
return MediaKeySystemStatus::Cdm_not_supported;
|
||||
}
|
||||
#endif
|
||||
return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion);
|
||||
}
|
||||
@ -310,12 +301,6 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
|
||||
aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME");
|
||||
return MediaKeySystemStatus::Cdm_not_supported;
|
||||
}
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
if (!nsCocoaFeatures::OnLionOrLater()) {
|
||||
aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Widevine EME");
|
||||
return MediaKeySystemStatus::Cdm_not_supported;
|
||||
}
|
||||
#endif
|
||||
if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) {
|
||||
aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled");
|
||||
|
@ -10,10 +10,6 @@
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
#ifndef MOZ_WIDGET_UIKIT
|
||||
#include "nsCocoaFeatures.h"
|
||||
#endif
|
||||
|
||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
@ -51,11 +47,6 @@ AppleCMLinker::Link()
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_UIKIT
|
||||
if (true) {
|
||||
#else
|
||||
if (nsCocoaFeatures::OnLionOrLater()) {
|
||||
#endif
|
||||
#define LINK_FUNC2(func) \
|
||||
func = (typeof(func))dlsym(sLink, #func); \
|
||||
if (!func) { \
|
||||
@ -73,22 +64,6 @@ AppleCMLinker::Link()
|
||||
skPropFullRangeVideo =
|
||||
GetIOConst("kCMFormatDescriptionExtension_FullRangeVideo");
|
||||
|
||||
} else {
|
||||
#define LINK_FUNC2(cm, fig) \
|
||||
cm = (typeof(cm))dlsym(sLink, #fig); \
|
||||
if (!cm) { \
|
||||
NS_WARNING("Couldn't load CoreMedia function " #fig ); \
|
||||
goto fail; \
|
||||
}
|
||||
#define LINK_FUNC(func) LINK_FUNC2(CM ## func, Fig ## func)
|
||||
#include "AppleCMFunctions.h"
|
||||
#undef LINK_FUNC
|
||||
#undef LINK_FUNC2
|
||||
|
||||
skPropExtensionAtoms =
|
||||
GetIOConst("kFigFormatDescriptionExtension_SampleDescriptionExtensionAtoms");
|
||||
}
|
||||
|
||||
if (!skPropExtensionAtoms) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#ifndef MOZ_WIDGET_UIKIT
|
||||
#include "nsCocoaFeatures.h"
|
||||
#include "MacIOSurfaceImage.h"
|
||||
#endif
|
||||
|
||||
@ -67,10 +66,8 @@ AppleVDADecoder::AppleVDADecoder(const VideoInfo& aConfig,
|
||||
, mIsShutDown(false)
|
||||
#ifdef MOZ_WIDGET_UIKIT
|
||||
, mUseSoftwareImages(true)
|
||||
, mIs106(false)
|
||||
#else
|
||||
, mUseSoftwareImages(false)
|
||||
, mIs106(!nsCocoaFeatures::OnLionOrLater())
|
||||
#endif
|
||||
, mMonitor("AppleVideoDecoder")
|
||||
, mIsFlushing(false)
|
||||
@ -539,17 +536,6 @@ AppleVDADecoder::DoDecode(MediaRawData* aSample)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mIs106) {
|
||||
// TN2267:
|
||||
// frameInfo: A CFDictionaryRef containing information to be returned in
|
||||
// the output callback for this frame.
|
||||
// This dictionary can contain client provided information associated with
|
||||
// the frame being decoded, for example presentation time.
|
||||
// The CFDictionaryRef will be retained by the framework.
|
||||
// In 10.6, it is released one too many. So retain it.
|
||||
CFRetain(frameInfo);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,6 @@ private:
|
||||
Atomic<uint32_t> mInputIncoming;
|
||||
Atomic<bool> mIsShutDown;
|
||||
const bool mUseSoftwareImages;
|
||||
const bool mIs106;
|
||||
|
||||
// Protects mReorderQueue.
|
||||
Monitor mMonitor;
|
||||
|
@ -841,8 +841,9 @@ AudioContext::OnStateChanged(void* aPromise, AudioContextState aNewState)
|
||||
}
|
||||
|
||||
#ifndef WIN32 // Bug 1170547
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
#ifdef DEBUG
|
||||
|
||||
if (!((mAudioContextState == AudioContextState::Suspended &&
|
||||
aNewState == AudioContextState::Running) ||
|
||||
(mAudioContextState == AudioContextState::Running &&
|
||||
@ -859,6 +860,7 @@ AudioContext::OnStateChanged(void* aPromise, AudioContextState aNewState)
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
#endif // XP_MACOSX
|
||||
#endif // WIN32
|
||||
|
||||
MOZ_ASSERT(
|
||||
|
@ -12,8 +12,12 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<!-- We set a transform on the body element so that it creates a reference frame.
|
||||
This makes sure that snapping of scrolled areas for the contained elements
|
||||
is not influenced by offsets outside of this document. -->
|
||||
<body id="body" onload="setTimeout(testElements, 0, 'testelements', SimpleTest.finish);"
|
||||
style="margin: 1px; border: 2px solid black; padding: 4px;">
|
||||
style="margin: 1px; border: 2px solid black; padding: 4px; transform: translateY(1px);">
|
||||
|
||||
<div id="testelements" style="margin: 0; border: 0; padding: 0;">
|
||||
<div id="div1" style="margin: 0; margin-left: 6px; margin-top: 2px; border: 1px solid green; padding: 6px; width: 50px; height: 20px"
|
||||
@ -55,7 +59,7 @@
|
||||
</div>
|
||||
|
||||
<div id="scrollbox"
|
||||
style="overflow: scroll; padding-left: 0px; margin: 3px; border: 4px solid green; max-width: 80px; max-height: 70px;"
|
||||
style="overflow: scroll; padding-left: 0px; margin: 3px; border: 4px solid green; max-width: 80px; max-height: 70px"
|
||||
_scrollWidth="62" _scrollHeight="32"
|
||||
_clientLeft="1" _clientTop="1" _clientWidth="62" _clientHeight="32"><p id="p1" style="margin: 0; padding: 0;">One</p>
|
||||
<p id="p2">Two</p>
|
||||
|
@ -181,12 +181,25 @@ function checkCoord(element, type, val, testname)
|
||||
is(element[type], Math.round(val), testname + " " + type);
|
||||
}
|
||||
|
||||
function checkCoordFuzzy(element, type, val, fuzz, testname)
|
||||
{
|
||||
if (val != -10000)
|
||||
ok(Math.abs(element[type] - Math.round(val)) <= fuzz, testname + " " + type);
|
||||
}
|
||||
|
||||
function checkCoords(element, type, left, top, width, height, testname)
|
||||
{
|
||||
checkCoord(element, type + "Left", left, testname);
|
||||
checkCoord(element, type + "Top", top, testname);
|
||||
checkCoord(element, type + "Width", width, testname);
|
||||
checkCoord(element, type + "Height", height, testname);
|
||||
|
||||
if (type == "scroll") {
|
||||
// scrollWidth and scrollHeight can deviate by 1 pixel due to snapping.
|
||||
checkCoordFuzzy(element, type + "Width", width, 1, testname);
|
||||
checkCoordFuzzy(element, type + "Height", height, 1, testname);
|
||||
} else {
|
||||
checkCoord(element, type + "Width", width, testname);
|
||||
checkCoord(element, type + "Height", height, testname);
|
||||
}
|
||||
|
||||
if (element instanceof SVGElement)
|
||||
return;
|
||||
|
@ -4942,7 +4942,7 @@ WorkerPrivate::BlockAndCollectRuntimeStats(JS::RuntimeStats* aRtStats,
|
||||
if (mMemoryReporter) {
|
||||
// Don't hold the lock while doing the actual report.
|
||||
MutexAutoUnlock unlock(mMutex);
|
||||
succeeded = JS::CollectRuntimeStats(rt, aRtStats, nullptr, aAnonymize);
|
||||
succeeded = JS::CollectRuntimeStats(mJSContext, aRtStats, nullptr, aAnonymize);
|
||||
}
|
||||
|
||||
NS_ASSERTION(mMemoryReporterRunning, "This isn't possible!");
|
||||
@ -6397,18 +6397,17 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
|
||||
}
|
||||
|
||||
if (aShrinking || aCollectChildren) {
|
||||
JSRuntime* rt = JS_GetRuntime(aCx);
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(aCx);
|
||||
|
||||
if (aShrinking) {
|
||||
JS::GCForReason(rt, GC_SHRINK, JS::gcreason::DOM_WORKER);
|
||||
JS::GCForReason(aCx, GC_SHRINK, JS::gcreason::DOM_WORKER);
|
||||
|
||||
if (!aCollectChildren) {
|
||||
LOG(WorkerLog(), ("Worker %p collected idle garbage\n", this));
|
||||
}
|
||||
}
|
||||
else {
|
||||
JS::GCForReason(rt, GC_NORMAL, JS::gcreason::DOM_WORKER);
|
||||
JS::GCForReason(aCx, GC_NORMAL, JS::gcreason::DOM_WORKER);
|
||||
LOG(WorkerLog(), ("Worker %p collected garbage\n", this));
|
||||
}
|
||||
}
|
||||
|
@ -72,15 +72,9 @@ SharedSurface_ANGLEShareHandle::Create(GLContext* gl, EGLConfig config,
|
||||
&opaqueKeyedMutex);
|
||||
RefPtr<IDXGIKeyedMutex> keyedMutex = static_cast<IDXGIKeyedMutex*>(opaqueKeyedMutex);
|
||||
|
||||
GLuint fence = 0;
|
||||
if (gl->IsExtensionSupported(GLContext::NV_fence)) {
|
||||
gl->MakeCurrent();
|
||||
gl->fGenFences(1, &fence);
|
||||
}
|
||||
|
||||
typedef SharedSurface_ANGLEShareHandle ptrT;
|
||||
UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, pbuffer, shareHandle,
|
||||
keyedMutex, fence) );
|
||||
keyedMutex) );
|
||||
return Move(ret);
|
||||
}
|
||||
|
||||
@ -96,8 +90,7 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
|
||||
bool hasAlpha,
|
||||
EGLSurface pbuffer,
|
||||
HANDLE shareHandle,
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
|
||||
GLuint fence)
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex)
|
||||
: SharedSurface(SharedSurfaceType::EGLSurfaceANGLE,
|
||||
AttachmentType::Screen,
|
||||
gl,
|
||||
@ -108,7 +101,6 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
|
||||
, mPBuffer(pbuffer)
|
||||
, mShareHandle(shareHandle)
|
||||
, mKeyedMutex(keyedMutex)
|
||||
, mFence(fence)
|
||||
{
|
||||
}
|
||||
|
||||
@ -116,13 +108,6 @@ SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl,
|
||||
SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle()
|
||||
{
|
||||
mEGL->fDestroySurface(Display(), mPBuffer);
|
||||
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
if (mFence) {
|
||||
mGL->fDeleteFences(1, &mFence);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -40,7 +40,6 @@ public:
|
||||
const HANDLE mShareHandle;
|
||||
protected:
|
||||
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
||||
const GLuint mFence;
|
||||
|
||||
SharedSurface_ANGLEShareHandle(GLContext* gl,
|
||||
GLLibraryEGL* egl,
|
||||
@ -48,8 +47,7 @@ protected:
|
||||
bool hasAlpha,
|
||||
EGLSurface pbuffer,
|
||||
HANDLE shareHandle,
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
|
||||
GLuint fence);
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex);
|
||||
|
||||
EGLDisplay Display();
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "nsRect.h"
|
||||
#include "mozilla/gfx/Types.h" // for NS_SIDE_BOTTOM, etc
|
||||
#include "mozilla/CheckedInt.h" // for CheckedInt
|
||||
#include "nsDeviceContext.h" // for nsDeviceContext
|
||||
#include "nsString.h" // for nsAutoString, etc
|
||||
#include "nsMargin.h" // for nsMargin
|
||||
@ -20,6 +21,19 @@ const mozilla::gfx::IntRect& GetMaxSizedIntRect() {
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
bool nsRect::Overflows() const {
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
return false;
|
||||
#else
|
||||
mozilla::CheckedInt<int32_t> xMost = this->x;
|
||||
xMost += this->width;
|
||||
mozilla::CheckedInt<int32_t> yMost = this->y;
|
||||
yMost += this->height;
|
||||
return !xMost.isValid() || !yMost.isValid();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Diagnostics
|
||||
|
||||
|
@ -129,6 +129,9 @@ struct nsRect :
|
||||
*this = aRect1.SaturatingUnionEdges(aRect2);
|
||||
}
|
||||
|
||||
// Return whether this rect's right or bottom edge overflow int32.
|
||||
bool Overflows() const;
|
||||
|
||||
/**
|
||||
* Return this rect scaled to a different appunits per pixel (APP) ratio.
|
||||
* In the RoundOut version we make the rect the smallest rect containing the
|
||||
|
@ -161,7 +161,7 @@ PrepareZoneForGC(Zone* zone);
|
||||
* Schedule all zones to be collected in the next GC.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
PrepareForFullGC(JSRuntime* rt);
|
||||
PrepareForFullGC(JSContext* cx);
|
||||
|
||||
/**
|
||||
* When performing an incremental GC, the zones that were selected for the
|
||||
@ -169,14 +169,14 @@ PrepareForFullGC(JSRuntime* rt);
|
||||
* This function selects those slices automatically.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
PrepareForIncrementalGC(JSRuntime* rt);
|
||||
PrepareForIncrementalGC(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Returns true if any zone in the system has been scheduled for GC with one of
|
||||
* the functions above or by the JS engine.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
IsGCScheduled(JSRuntime* rt);
|
||||
IsGCScheduled(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Undoes the effect of the Prepare methods above. The given zone will not be
|
||||
@ -201,7 +201,7 @@ SkipZoneForGC(Zone* zone);
|
||||
* the system.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
GCForReason(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason);
|
||||
GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason);
|
||||
|
||||
/*
|
||||
* Incremental GC:
|
||||
@ -227,43 +227,43 @@ GCForReason(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason);
|
||||
* Begin an incremental collection and perform one slice worth of work. When
|
||||
* this function returns, the collection may not be complete.
|
||||
* IncrementalGCSlice() must be called repeatedly until
|
||||
* !IsIncrementalGCInProgress(rt).
|
||||
* !IsIncrementalGCInProgress(cx).
|
||||
*
|
||||
* Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
|
||||
* shorter than the requested interval.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
StartIncrementalGC(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason,
|
||||
StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason,
|
||||
int64_t millis = 0);
|
||||
|
||||
/**
|
||||
* Perform a slice of an ongoing incremental collection. When this function
|
||||
* returns, the collection may not be complete. It must be called repeatedly
|
||||
* until !IsIncrementalGCInProgress(rt).
|
||||
* until !IsIncrementalGCInProgress(cx).
|
||||
*
|
||||
* Note: SpiderMonkey's GC is not realtime. Slices in practice may be longer or
|
||||
* shorter than the requested interval.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
IncrementalGCSlice(JSRuntime* rt, gcreason::Reason reason, int64_t millis = 0);
|
||||
IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis = 0);
|
||||
|
||||
/**
|
||||
* If IsIncrementalGCInProgress(rt), this call finishes the ongoing collection
|
||||
* by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(rt),
|
||||
* If IsIncrementalGCInProgress(cx), this call finishes the ongoing collection
|
||||
* by performing an arbitrarily long slice. If !IsIncrementalGCInProgress(cx),
|
||||
* this is equivalent to GCForReason. When this function returns,
|
||||
* IsIncrementalGCInProgress(rt) will always be false.
|
||||
* IsIncrementalGCInProgress(cx) will always be false.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
FinishIncrementalGC(JSRuntime* rt, gcreason::Reason reason);
|
||||
FinishIncrementalGC(JSContext* cx, gcreason::Reason reason);
|
||||
|
||||
/**
|
||||
* If IsIncrementalGCInProgress(rt), this call aborts the ongoing collection and
|
||||
* If IsIncrementalGCInProgress(cx), this call aborts the ongoing collection and
|
||||
* performs whatever work needs to be done to return the collector to its idle
|
||||
* state. This may take an arbitrarily long time. When this function returns,
|
||||
* IsIncrementalGCInProgress(rt) will always be false.
|
||||
* IsIncrementalGCInProgress(cx) will always be false.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
AbortIncrementalGC(JSRuntime* rt);
|
||||
AbortIncrementalGC(JSContext* cx);
|
||||
|
||||
namespace dbg {
|
||||
|
||||
@ -356,7 +356,7 @@ typedef void
|
||||
* marking.
|
||||
*/
|
||||
extern JS_PUBLIC_API(GCSliceCallback)
|
||||
SetGCSliceCallback(JSRuntime* rt, GCSliceCallback callback);
|
||||
SetGCSliceCallback(JSContext* cx, GCSliceCallback callback);
|
||||
|
||||
/**
|
||||
* Describes the progress of an observed nursery collection.
|
||||
@ -384,7 +384,7 @@ using GCNurseryCollectionCallback = void(*)(JSRuntime* rt, GCNurseryProgress pro
|
||||
* be called at the start and end of every nursery collection.
|
||||
*/
|
||||
extern JS_PUBLIC_API(GCNurseryCollectionCallback)
|
||||
SetGCNurseryCollectionCallback(JSRuntime* rt, GCNurseryCollectionCallback callback);
|
||||
SetGCNurseryCollectionCallback(JSContext* cx, GCNurseryCollectionCallback callback);
|
||||
|
||||
/**
|
||||
* Incremental GC defaults to enabled, but may be disabled for testing or in
|
||||
@ -393,7 +393,7 @@ SetGCNurseryCollectionCallback(JSRuntime* rt, GCNurseryCollectionCallback callba
|
||||
* disabled on the runtime.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
DisableIncrementalGC(JSRuntime* rt);
|
||||
DisableIncrementalGC(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Returns true if incremental GC is enabled. Simply having incremental GC
|
||||
@ -404,14 +404,14 @@ DisableIncrementalGC(JSRuntime* rt);
|
||||
* collections are not happening incrementally when expected.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
IsIncrementalGCEnabled(JSRuntime* rt);
|
||||
IsIncrementalGCEnabled(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Returns true while an incremental GC is ongoing, both when actively
|
||||
* collecting and between slices.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
IsIncrementalGCInProgress(JSRuntime* rt);
|
||||
IsIncrementalGCInProgress(JSContext* cx);
|
||||
|
||||
/*
|
||||
* Returns true when writes to GC things must call an incremental (pre) barrier.
|
||||
@ -419,7 +419,7 @@ IsIncrementalGCInProgress(JSRuntime* rt);
|
||||
* At other times, the barrier may be elided for performance.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
IsIncrementalBarrierNeeded(JSRuntime* rt);
|
||||
IsIncrementalBarrierNeeded(JSContext* cx);
|
||||
|
||||
/*
|
||||
* Notify the GC that a reference to a GC thing is about to be overwritten.
|
||||
@ -438,7 +438,7 @@ IncrementalObjectBarrier(JSObject* obj);
|
||||
* Returns true if the most recent GC ran incrementally.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
WasIncrementalGC(JSRuntime* rt);
|
||||
WasIncrementalGC(JSContext* cx);
|
||||
|
||||
/*
|
||||
* Generational GC:
|
||||
@ -479,7 +479,7 @@ GetGCNumber();
|
||||
* GC to return this memory immediately.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
ShrinkGCBuffers(JSRuntime* rt);
|
||||
ShrinkGCBuffers(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Assert if a GC occurs while this class is live. This class does not disable
|
||||
@ -665,13 +665,13 @@ MarkStringAsLive(Zone* zone, JSString* string)
|
||||
* Note: this is not related to the PokeGC in nsJSEnvironment.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
PokeGC(JSRuntime* rt);
|
||||
PokeGC(JSContext* cx);
|
||||
|
||||
/*
|
||||
* Internal to Firefox.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
NotifyDidPaint(JSRuntime* rt);
|
||||
NotifyDidPaint(JSContext* cx);
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
|
@ -883,7 +883,7 @@ class ObjectPrivateVisitor
|
||||
};
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CollectRuntimeStats(JSRuntime* rt, RuntimeStats* rtStats, ObjectPrivateVisitor* opv, bool anonymize);
|
||||
CollectRuntimeStats(JSContext* cx, RuntimeStats* rtStats, ObjectPrivateVisitor* opv, bool anonymize);
|
||||
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
SystemCompartmentCount(JSRuntime* rt);
|
||||
@ -895,11 +895,11 @@ extern JS_PUBLIC_API(size_t)
|
||||
PeakSizeOfTemporary(const JSRuntime* rt);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
AddSizeOfTab(JSRuntime* rt, JS::HandleObject obj, mozilla::MallocSizeOf mallocSizeOf,
|
||||
AddSizeOfTab(JSContext* cx, JS::HandleObject obj, mozilla::MallocSizeOf mallocSizeOf,
|
||||
ObjectPrivateVisitor* opv, TabSizes* sizes);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
AddServoSizeOf(JSRuntime *rt, mozilla::MallocSizeOf mallocSizeOf,
|
||||
AddServoSizeOf(JSContext* cx, mozilla::MallocSizeOf mallocSizeOf,
|
||||
ObjectPrivateVisitor *opv, ServoSizes *sizes);
|
||||
|
||||
} // namespace JS
|
||||
|
@ -1089,17 +1089,13 @@ class JS_PUBLIC_API(ObjectPtr)
|
||||
/* Always call finalize before the destructor. */
|
||||
~ObjectPtr() { MOZ_ASSERT(!value); }
|
||||
|
||||
void finalize(JSRuntime* rt) {
|
||||
if (IsIncrementalBarrierNeeded(rt))
|
||||
IncrementalObjectBarrier(value);
|
||||
value = nullptr;
|
||||
}
|
||||
void finalize(JSRuntime* rt);
|
||||
|
||||
void init(JSObject* obj) { value = obj; }
|
||||
|
||||
JSObject* get() const { return value; }
|
||||
|
||||
void writeBarrierPre(JSRuntime* rt) {
|
||||
void writeBarrierPre(JSContext* cx) {
|
||||
IncrementalObjectBarrier(value);
|
||||
}
|
||||
|
||||
|
@ -309,10 +309,10 @@ GC(JSContext* cx, unsigned argc, Value* vp)
|
||||
if (compartment)
|
||||
PrepareForDebugGC(cx->runtime());
|
||||
else
|
||||
JS::PrepareForFullGC(cx->runtime());
|
||||
JS::PrepareForFullGC(cx);
|
||||
|
||||
JSGCInvocationKind gckind = shrinking ? GC_SHRINK : GC_NORMAL;
|
||||
JS::GCForReason(cx->runtime(), gckind, JS::gcreason::API);
|
||||
JS::GCForReason(cx, gckind, JS::gcreason::API);
|
||||
|
||||
char buf[256] = { '\0' };
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
@ -431,7 +431,7 @@ GCParameter(JSContext* cx, unsigned argc, Value* vp)
|
||||
}
|
||||
|
||||
uint32_t value = floor(d);
|
||||
if (param == JSGC_MARK_STACK_LIMIT && JS::IsIncrementalGCInProgress(cx->runtime())) {
|
||||
if (param == JSGC_MARK_STACK_LIMIT && JS::IsIncrementalGCInProgress(cx)) {
|
||||
JS_ReportError(cx, "attempt to set markStackLimit while a GC is in progress");
|
||||
return false;
|
||||
}
|
||||
@ -3281,8 +3281,8 @@ majorGC(JSRuntime* rt, JSGCStatus status, void* data)
|
||||
|
||||
if (info->depth > 0) {
|
||||
info->depth--;
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::GCForReason(rt, GC_NORMAL, JS::gcreason::API);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
JS::GCForReason(rt->contextFromMainThread(), GC_NORMAL, JS::gcreason::API);
|
||||
info->depth++;
|
||||
}
|
||||
}
|
||||
|
@ -165,11 +165,10 @@ GCRuntime::tryNewTenuredThing(ExclusiveContext* cx, AllocKind kind, size_t thing
|
||||
// We have no memory available for a new chunk; perform an
|
||||
// all-compartments, non-incremental, shrinking GC and wait for
|
||||
// sweeping to finish.
|
||||
JSRuntime *rt = cx->asJSContext()->runtime();
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(cx->asJSContext());
|
||||
AutoKeepAtoms keepAtoms(cx->perThreadData);
|
||||
rt->gc.gc(GC_SHRINK, JS::gcreason::LAST_DITCH);
|
||||
rt->gc.waitBackgroundSweepOrAllocEnd();
|
||||
cx->asJSContext()->gc.gc(GC_SHRINK, JS::gcreason::LAST_DITCH);
|
||||
cx->asJSContext()->gc.waitBackgroundSweepOrAllocEnd();
|
||||
|
||||
t = tryNewTenuredThing<T, NoGC>(cx, kind, thingSize);
|
||||
if (!t)
|
||||
|
@ -20,7 +20,7 @@
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
void FinishGC(JSRuntime* rt);
|
||||
void FinishGC(JSContext* cx);
|
||||
|
||||
/*
|
||||
* This class should be used by any code that needs to exclusive access to the
|
||||
@ -50,7 +50,7 @@ class MOZ_RAII AutoPrepareForTracing
|
||||
mozilla::Maybe<AutoTraceSession> session_;
|
||||
|
||||
public:
|
||||
AutoPrepareForTracing(JSRuntime* rt, ZoneSelector selector);
|
||||
AutoPrepareForTracing(JSContext* cx, ZoneSelector selector);
|
||||
AutoTraceSession& session() { return session_.ref(); }
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,7 @@ js::TraceRuntime(JSTracer* trc)
|
||||
|
||||
JSRuntime* rt = trc->runtime();
|
||||
rt->gc.evictNursery();
|
||||
AutoPrepareForTracing prep(rt, WithAtoms);
|
||||
AutoPrepareForTracing prep(rt->contextFromMainThread(), WithAtoms);
|
||||
gcstats::AutoPhase ap(rt->gc.stats, gcstats::PHASE_TRACE_HEAP);
|
||||
rt->gc.markRuntime(trc, GCRuntime::TraceRuntime, prep.session().lock);
|
||||
}
|
||||
@ -52,62 +52,62 @@ IterateCompartmentsArenasCells(JSRuntime* rt, Zone* zone, void* data,
|
||||
}
|
||||
|
||||
void
|
||||
js::IterateZonesCompartmentsArenasCells(JSRuntime* rt, void* data,
|
||||
js::IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback)
|
||||
{
|
||||
AutoPrepareForTracing prop(rt, WithAtoms);
|
||||
AutoPrepareForTracing prop(cx, WithAtoms);
|
||||
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
(*zoneCallback)(rt, data, zone);
|
||||
IterateCompartmentsArenasCells(rt, zone, data,
|
||||
for (ZonesIter zone(cx, WithAtoms); !zone.done(); zone.next()) {
|
||||
(*zoneCallback)(cx, data, zone);
|
||||
IterateCompartmentsArenasCells(cx, zone, data,
|
||||
compartmentCallback, arenaCallback, cellCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js::IterateZoneCompartmentsArenasCells(JSRuntime* rt, Zone* zone, void* data,
|
||||
js::IterateZoneCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
IterateCellCallback cellCallback)
|
||||
{
|
||||
AutoPrepareForTracing prop(rt, WithAtoms);
|
||||
AutoPrepareForTracing prop(cx, WithAtoms);
|
||||
|
||||
(*zoneCallback)(rt, data, zone);
|
||||
IterateCompartmentsArenasCells(rt, zone, data,
|
||||
(*zoneCallback)(cx, data, zone);
|
||||
IterateCompartmentsArenasCells(cx, zone, data,
|
||||
compartmentCallback, arenaCallback, cellCallback);
|
||||
}
|
||||
|
||||
void
|
||||
js::IterateChunks(JSRuntime* rt, void* data, IterateChunkCallback chunkCallback)
|
||||
js::IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback)
|
||||
{
|
||||
AutoPrepareForTracing prep(rt, SkipAtoms);
|
||||
AutoPrepareForTracing prep(cx, SkipAtoms);
|
||||
|
||||
for (auto chunk = rt->gc.allNonEmptyChunks(); !chunk.done(); chunk.next())
|
||||
chunkCallback(rt, data, chunk);
|
||||
for (auto chunk = cx->gc.allNonEmptyChunks(); !chunk.done(); chunk.next())
|
||||
chunkCallback(cx, data, chunk);
|
||||
}
|
||||
|
||||
void
|
||||
js::IterateScripts(JSRuntime* rt, JSCompartment* compartment,
|
||||
js::IterateScripts(JSContext* cx, JSCompartment* compartment,
|
||||
void* data, IterateScriptCallback scriptCallback)
|
||||
{
|
||||
MOZ_ASSERT(!rt->mainThread.suppressGC);
|
||||
AutoEmptyNursery empty(rt);
|
||||
AutoPrepareForTracing prep(rt, SkipAtoms);
|
||||
MOZ_ASSERT(!cx->mainThread().suppressGC);
|
||||
AutoEmptyNursery empty(cx);
|
||||
AutoPrepareForTracing prep(cx, SkipAtoms);
|
||||
|
||||
if (compartment) {
|
||||
Zone* zone = compartment->zone();
|
||||
for (auto script = zone->cellIter<JSScript>(empty); !script.done(); script.next()) {
|
||||
if (script->compartment() == compartment)
|
||||
scriptCallback(rt, data, script);
|
||||
scriptCallback(cx, data, script);
|
||||
}
|
||||
} else {
|
||||
for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
|
||||
for (ZonesIter zone(cx, SkipAtoms); !zone.done(); zone.next()) {
|
||||
for (auto script = zone->cellIter<JSScript>(empty); !script.done(); script.next())
|
||||
scriptCallback(rt, data, script);
|
||||
scriptCallback(cx, data, script);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -117,7 +117,7 @@ js::IterateGrayObjects(Zone* zone, GCThingCallback cellCallback, void* data)
|
||||
{
|
||||
JSRuntime* rt = zone->runtimeFromMainThread();
|
||||
AutoEmptyNursery empty(rt);
|
||||
AutoPrepareForTracing prep(rt, SkipAtoms);
|
||||
AutoPrepareForTracing prep(rt->contextFromMainThread(), SkipAtoms);
|
||||
|
||||
for (auto thingKind : ObjectAllocKinds()) {
|
||||
for (auto obj = zone->cellIter<JSObject>(thingKind, empty); !obj.done(); obj.next()) {
|
||||
|
@ -183,7 +183,7 @@ gc::GCRuntime::startVerifyPreBarriers()
|
||||
if (!trc)
|
||||
return;
|
||||
|
||||
AutoPrepareForTracing prep(rt, WithAtoms);
|
||||
AutoPrepareForTracing prep(rt->contextFromMainThread(), WithAtoms);
|
||||
|
||||
for (auto chunk = allNonEmptyChunks(); !chunk.done(); chunk.next())
|
||||
chunk->bitmap.clear();
|
||||
@ -312,7 +312,7 @@ gc::GCRuntime::endVerifyPreBarriers()
|
||||
|
||||
MOZ_ASSERT(!JS::IsGenerationalGCEnabled(rt));
|
||||
|
||||
AutoPrepareForTracing prep(rt, SkipAtoms);
|
||||
AutoPrepareForTracing prep(rt->contextFromMainThread(), SkipAtoms);
|
||||
|
||||
bool compartmentCreated = false;
|
||||
|
||||
|
@ -48,7 +48,7 @@ BEGIN_TEST(testGCAllocator)
|
||||
#endif
|
||||
|
||||
/* Finish any ongoing background free activity. */
|
||||
js::gc::FinishGC(rt);
|
||||
js::gc::FinishGC(cx);
|
||||
|
||||
bool growUp;
|
||||
CHECK(addressesGrowUp(&growUp));
|
||||
|
@ -23,11 +23,11 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
|
||||
/* Full GC, incremental. */
|
||||
FinalizeCalls = 0;
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000);
|
||||
JS::PrepareForFullGC(cx);
|
||||
JS::StartIncrementalGC(cx, GC_NORMAL, JS::gcreason::API, 1000000);
|
||||
while (rt->gc.isIncrementalGCInProgress()) {
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::IncrementalGCSlice(rt, JS::gcreason::API, 1000000);
|
||||
JS::PrepareForFullGC(cx);
|
||||
JS::IncrementalGCSlice(cx, JS::gcreason::API, 1000000);
|
||||
}
|
||||
CHECK(!rt->gc.isIncrementalGCInProgress());
|
||||
CHECK(rt->gc.isFullGc());
|
||||
@ -45,7 +45,7 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
/* Compartment GC, non-incremental, single compartment. */
|
||||
FinalizeCalls = 0;
|
||||
JS::PrepareZoneForGC(global1->zone());
|
||||
JS::GCForReason(rt, GC_NORMAL, JS::gcreason::API);
|
||||
JS::GCForReason(cx, GC_NORMAL, JS::gcreason::API);
|
||||
CHECK(!rt->gc.isFullGc());
|
||||
CHECK(checkSingleGroup());
|
||||
CHECK(checkFinalizeStatus());
|
||||
@ -56,7 +56,7 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
JS::PrepareZoneForGC(global1->zone());
|
||||
JS::PrepareZoneForGC(global2->zone());
|
||||
JS::PrepareZoneForGC(global3->zone());
|
||||
JS::GCForReason(rt, GC_NORMAL, JS::gcreason::API);
|
||||
JS::GCForReason(cx, GC_NORMAL, JS::gcreason::API);
|
||||
CHECK(!rt->gc.isFullGc());
|
||||
CHECK(checkSingleGroup());
|
||||
CHECK(checkFinalizeStatus());
|
||||
@ -65,10 +65,10 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
/* Compartment GC, incremental, single compartment. */
|
||||
FinalizeCalls = 0;
|
||||
JS::PrepareZoneForGC(global1->zone());
|
||||
JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000);
|
||||
JS::StartIncrementalGC(cx, GC_NORMAL, JS::gcreason::API, 1000000);
|
||||
while (rt->gc.isIncrementalGCInProgress()) {
|
||||
JS::PrepareZoneForGC(global1->zone());
|
||||
JS::IncrementalGCSlice(rt, JS::gcreason::API, 1000000);
|
||||
JS::IncrementalGCSlice(cx, JS::gcreason::API, 1000000);
|
||||
}
|
||||
CHECK(!rt->gc.isIncrementalGCInProgress());
|
||||
CHECK(!rt->gc.isFullGc());
|
||||
@ -81,12 +81,12 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
JS::PrepareZoneForGC(global1->zone());
|
||||
JS::PrepareZoneForGC(global2->zone());
|
||||
JS::PrepareZoneForGC(global3->zone());
|
||||
JS::StartIncrementalGC(rt, GC_NORMAL, JS::gcreason::API, 1000000);
|
||||
JS::StartIncrementalGC(cx, GC_NORMAL, JS::gcreason::API, 1000000);
|
||||
while (rt->gc.isIncrementalGCInProgress()) {
|
||||
JS::PrepareZoneForGC(global1->zone());
|
||||
JS::PrepareZoneForGC(global2->zone());
|
||||
JS::PrepareZoneForGC(global3->zone());
|
||||
JS::IncrementalGCSlice(rt, JS::gcreason::API, 1000000);
|
||||
JS::IncrementalGCSlice(cx, JS::gcreason::API, 1000000);
|
||||
}
|
||||
CHECK(!rt->gc.isIncrementalGCInProgress());
|
||||
CHECK(!rt->gc.isFullGc());
|
||||
@ -100,7 +100,7 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
|
||||
FinalizeCalls = 0;
|
||||
JS_SetGCZeal(cx, 9, 1000000);
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(cx);
|
||||
js::SliceBudget budget(js::WorkBudget(1));
|
||||
rt->gc.startDebugGC(GC_NORMAL, budget);
|
||||
CHECK(rt->gc.state() == js::gc::MARK);
|
||||
|
@ -168,7 +168,7 @@ BEGIN_TEST(testIncrementalRoots)
|
||||
// We'd better be between iGC slices now. There's always a risk that
|
||||
// something will decide that we need to do a full GC (such as gczeal, but
|
||||
// that is turned off.)
|
||||
MOZ_ASSERT(JS::IsIncrementalGCInProgress(rt));
|
||||
MOZ_ASSERT(JS::IsIncrementalGCInProgress(cx));
|
||||
|
||||
// And assert that the mark bits are as we expect them to be.
|
||||
MOZ_ASSERT(vec[0]->asTenured().isMarked());
|
||||
|
@ -12,13 +12,13 @@
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
static void
|
||||
MinimizeHeap(JSRuntime* rt)
|
||||
MinimizeHeap(JSContext* cx)
|
||||
{
|
||||
// The second collection is to force us to wait for the background
|
||||
// sweeping that the first GC started to finish.
|
||||
JS_GC(JS_GetContext(rt));
|
||||
JS_GC(JS_GetContext(rt));
|
||||
js::gc::FinishGC(rt);
|
||||
JS_GC(cx);
|
||||
JS_GC(cx);
|
||||
js::gc::FinishGC(cx);
|
||||
}
|
||||
|
||||
BEGIN_TEST(testGCUID)
|
||||
@ -31,7 +31,7 @@ BEGIN_TEST(testGCUID)
|
||||
uint64_t tmp = 0;
|
||||
|
||||
// Ensure the heap is as minimal as it can get.
|
||||
MinimizeHeap(rt);
|
||||
MinimizeHeap(cx);
|
||||
|
||||
JS::RootedObject obj(cx, JS_NewPlainObject(cx));
|
||||
uintptr_t nurseryAddr = uintptr_t(obj.get());
|
||||
@ -53,7 +53,7 @@ BEGIN_TEST(testGCUID)
|
||||
CHECK(uid == tmp);
|
||||
|
||||
// Tenure the thing and check that the UID moved with it.
|
||||
MinimizeHeap(rt);
|
||||
MinimizeHeap(cx);
|
||||
uintptr_t tenuredAddr = uintptr_t(obj.get());
|
||||
CHECK(tenuredAddr != nurseryAddr);
|
||||
CHECK(!js::gc::IsInsideNursery(obj));
|
||||
@ -71,9 +71,9 @@ BEGIN_TEST(testGCUID)
|
||||
// Try to get another tenured object in the same location and check that
|
||||
// the uid was removed correctly.
|
||||
obj = nullptr;
|
||||
MinimizeHeap(rt);
|
||||
MinimizeHeap(cx);
|
||||
obj = JS_NewPlainObject(cx);
|
||||
MinimizeHeap(rt);
|
||||
MinimizeHeap(cx);
|
||||
CHECK(uintptr_t(obj.get()) == tenuredAddr);
|
||||
CHECK(!obj->zone()->hasUniqueId(obj));
|
||||
CHECK(obj->zone()->getUniqueId(obj, &tmp));
|
||||
@ -91,7 +91,7 @@ BEGIN_TEST(testGCUID)
|
||||
}
|
||||
|
||||
// Transfer our vector to tenured if it isn't there already.
|
||||
MinimizeHeap(rt);
|
||||
MinimizeHeap(cx);
|
||||
|
||||
// Tear holes in the heap by unrooting the even objects and collecting.
|
||||
JS::Rooted<ObjectVector> vec2(cx, ObjectVector(cx));
|
||||
@ -100,7 +100,7 @@ BEGIN_TEST(testGCUID)
|
||||
vec2.append(vec[i]);
|
||||
}
|
||||
vec.clear();
|
||||
MinimizeHeap(rt);
|
||||
MinimizeHeap(cx);
|
||||
|
||||
// Grab the last object in the vector as our object of interest.
|
||||
obj = vec2.back();
|
||||
@ -110,9 +110,9 @@ BEGIN_TEST(testGCUID)
|
||||
|
||||
// Force a compaction to move the object and check that the uid moved to
|
||||
// the new tenured heap location.
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::GCForReason(rt, GC_SHRINK, JS::gcreason::API);
|
||||
MinimizeHeap(rt);
|
||||
JS::PrepareForFullGC(cx);
|
||||
JS::GCForReason(cx, GC_SHRINK, JS::gcreason::API);
|
||||
MinimizeHeap(cx);
|
||||
CHECK(uintptr_t(obj.get()) != tenuredAddr);
|
||||
CHECK(obj->zone()->hasUniqueId(obj));
|
||||
CHECK(obj->zone()->getUniqueId(obj, &tmp));
|
||||
|
@ -28,7 +28,7 @@ unsigned
|
||||
countIonScripts(JSObject* global)
|
||||
{
|
||||
unsigned count = 0;
|
||||
js::IterateScripts(rt, global->compartment(), &count, ScriptCallback);
|
||||
js::IterateScripts(cx, global->compartment(), &count, ScriptCallback);
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -77,10 +77,10 @@ testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts)
|
||||
CHECK_EQUAL(value.toInt32(), 45);
|
||||
CHECK_EQUAL(countIonScripts(global), 1u);
|
||||
|
||||
GCForReason(rt, GC_NORMAL, gcreason::API);
|
||||
GCForReason(cx, GC_NORMAL, gcreason::API);
|
||||
CHECK_EQUAL(countIonScripts(global), remainingIonScripts);
|
||||
|
||||
GCForReason(rt, GC_SHRINK, gcreason::API);
|
||||
GCForReason(cx, GC_SHRINK, gcreason::API);
|
||||
CHECK_EQUAL(countIonScripts(global), 0u);
|
||||
|
||||
return true;
|
||||
|
@ -99,7 +99,7 @@ BEGIN_TEST(testWeakMap_keyDelegates)
|
||||
CHECK(newCCW(map, delegateRoot));
|
||||
js::SliceBudget budget(js::WorkBudget(1000000));
|
||||
rt->gc.startDebugGC(GC_NORMAL, budget);
|
||||
while (JS::IsIncrementalGCInProgress(rt))
|
||||
while (JS::IsIncrementalGCInProgress(cx))
|
||||
rt->gc.debugGCSlice(budget);
|
||||
#ifdef DEBUG
|
||||
CHECK(map->zone()->lastZoneGroupIndex() < delegateRoot->zone()->lastZoneGroupIndex());
|
||||
@ -115,7 +115,7 @@ BEGIN_TEST(testWeakMap_keyDelegates)
|
||||
CHECK(newCCW(map, delegateRoot));
|
||||
budget = js::SliceBudget(js::WorkBudget(100000));
|
||||
rt->gc.startDebugGC(GC_NORMAL, budget);
|
||||
while (JS::IsIncrementalGCInProgress(rt))
|
||||
while (JS::IsIncrementalGCInProgress(cx))
|
||||
rt->gc.debugGCSlice(budget);
|
||||
CHECK(checkSize(map, 1));
|
||||
|
||||
|
@ -437,8 +437,8 @@ class AutoLeaveZeal
|
||||
uint32_t dummy;
|
||||
JS_GetGCZealBits(cx_, &zealBits_, &frequency_, &dummy);
|
||||
JS_SetGCZeal(cx_, 0, 0);
|
||||
JS::PrepareForFullGC(JS_GetRuntime(cx_));
|
||||
JS::GCForReason(JS_GetRuntime(cx_), GC_SHRINK, JS::gcreason::DEBUG_GC);
|
||||
JS::PrepareForFullGC(cx_);
|
||||
JS::GCForReason(cx_, GC_SHRINK, JS::gcreason::DEBUG_GC);
|
||||
}
|
||||
~AutoLeaveZeal() {
|
||||
for (size_t i = 0; i < sizeof(zealBits_) * 8; i++) {
|
||||
|
@ -856,7 +856,7 @@ JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target)
|
||||
RootedObject newIdentity(cx);
|
||||
|
||||
// Don't allow a compacting GC to observe any intermediate state.
|
||||
AutoDisableCompactingGC nocgc(cx->runtime());
|
||||
AutoDisableCompactingGC nocgc(cx);
|
||||
|
||||
AutoDisableProxyCheck adpc(cx->runtime());
|
||||
|
||||
|
@ -1141,15 +1141,15 @@ js::SetActivityCallback(JSContext* cx, ActivityCallback cb, void* arg)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS::NotifyDidPaint(JSRuntime* rt)
|
||||
JS::NotifyDidPaint(JSContext* cx)
|
||||
{
|
||||
rt->gc.notifyDidPaint();
|
||||
cx->gc.notifyDidPaint();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS::PokeGC(JSRuntime* rt)
|
||||
JS::PokeGC(JSContext* cx)
|
||||
{
|
||||
rt->gc.poke();
|
||||
cx->gc.poke();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSCompartment*)
|
||||
@ -1160,6 +1160,14 @@ js::GetAnyCompartmentInZone(JS::Zone* zone)
|
||||
return comp.get();
|
||||
}
|
||||
|
||||
void
|
||||
JS::ObjectPtr::finalize(JSRuntime* rt)
|
||||
{
|
||||
if (IsIncrementalBarrierNeeded(rt->contextFromMainThread()))
|
||||
IncrementalObjectBarrier(value);
|
||||
value = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
JS::ObjectPtr::updateWeakPointerAfterGC()
|
||||
{
|
||||
|
@ -1478,7 +1478,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
|
||||
// Additionally, the lazy script cache is not used during incremental
|
||||
// GCs, to avoid resurrecting dead scripts after incremental sweeping
|
||||
// has started.
|
||||
if (canRelazify && !JS::IsIncrementalGCInProgress(cx->runtime())) {
|
||||
if (canRelazify && !JS::IsIncrementalGCInProgress(cx)) {
|
||||
LazyScriptCache::Lookup lookup(cx, lazy);
|
||||
cx->caches.lazyScriptCache.lookup(lookup, script.address());
|
||||
}
|
||||
|
119
js/src/jsgc.cpp
119
js/src/jsgc.cpp
@ -1742,12 +1742,12 @@ GCRuntime::isCompactingGCEnabled() const
|
||||
return compactingEnabled && compactingDisabledCount == 0;
|
||||
}
|
||||
|
||||
AutoDisableCompactingGC::AutoDisableCompactingGC(JSRuntime* rt)
|
||||
: gc(rt->gc)
|
||||
AutoDisableCompactingGC::AutoDisableCompactingGC(JSContext* cx)
|
||||
: gc(cx->gc)
|
||||
{
|
||||
gc.disableCompactingGC();
|
||||
if (gc.isIncrementalGCInProgress() && gc.isCompactingGc())
|
||||
FinishGC(rt);
|
||||
FinishGC(cx);
|
||||
}
|
||||
|
||||
AutoDisableCompactingGC::~AutoDisableCompactingGC()
|
||||
@ -2983,7 +2983,7 @@ GCRuntime::triggerGC(JS::gcreason::Reason reason)
|
||||
if (rt->isHeapCollecting())
|
||||
return false;
|
||||
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
requestMajorGC(reason);
|
||||
return true;
|
||||
}
|
||||
@ -3064,7 +3064,7 @@ GCRuntime::maybeGC(Zone* zone)
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (hasZealMode(ZealMode::Alloc) || hasZealMode(ZealMode::Poke)) {
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
gc(GC_NORMAL, JS::gcreason::DEBUG_GC);
|
||||
return true;
|
||||
}
|
||||
@ -3104,7 +3104,7 @@ GCRuntime::maybePeriodicFullGC()
|
||||
if (chunkAllocationSinceLastGC ||
|
||||
numArenasFreeCommitted > decommitThreshold)
|
||||
{
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
startGC(GC_SHRINK, JS::gcreason::PERIODIC_FULL_GC);
|
||||
} else {
|
||||
nextFullGCTime = now + GC_IDLE_FULL_SPAN;
|
||||
@ -6292,7 +6292,7 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
|
||||
|
||||
/* Need to re-schedule all zones for GC. */
|
||||
if (poked && cleanUpEverything)
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
|
||||
/*
|
||||
* This code makes an extra effort to collect compartments that we
|
||||
@ -6419,14 +6419,14 @@ GCRuntime::notifyDidPaint()
|
||||
verifyPreBarriers();
|
||||
|
||||
if (hasZealMode(ZealMode::FrameGC)) {
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
gc(GC_NORMAL, JS::gcreason::REFRESH_FRAME);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isIncrementalGCInProgress() && !interFrameGC && tunables.areRefreshFrameSlicesEnabled()) {
|
||||
JS::PrepareForIncrementalGC(rt);
|
||||
JS::PrepareForIncrementalGC(rt->contextFromMainThread());
|
||||
gcSlice(JS::gcreason::REFRESH_FRAME);
|
||||
}
|
||||
|
||||
@ -6448,7 +6448,7 @@ GCRuntime::startDebugGC(JSGCInvocationKind gckind, SliceBudget& budget)
|
||||
{
|
||||
MOZ_ASSERT(!isIncrementalGCInProgress());
|
||||
if (!ZonesSelected(rt))
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
invocationKind = gckind;
|
||||
collect(false, budget, JS::gcreason::DEBUG_GC);
|
||||
}
|
||||
@ -6458,7 +6458,7 @@ GCRuntime::debugGCSlice(SliceBudget& budget)
|
||||
{
|
||||
MOZ_ASSERT(isIncrementalGCInProgress());
|
||||
if (!ZonesSelected(rt))
|
||||
JS::PrepareForIncrementalGC(rt);
|
||||
JS::PrepareForIncrementalGC(rt->contextFromMainThread());
|
||||
collect(false, budget, JS::gcreason::DEBUG_GC);
|
||||
}
|
||||
|
||||
@ -6467,14 +6467,14 @@ void
|
||||
js::PrepareForDebugGC(JSRuntime* rt)
|
||||
{
|
||||
if (!ZonesSelected(rt))
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(rt->contextFromMainThread());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::ShrinkGCBuffers(JSRuntime* rt)
|
||||
JS::ShrinkGCBuffers(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!rt->isHeapBusy());
|
||||
rt->gc.shrinkBuffers();
|
||||
MOZ_ASSERT(!cx->isHeapBusy());
|
||||
cx->gc.shrinkBuffers();
|
||||
}
|
||||
|
||||
void
|
||||
@ -6604,20 +6604,21 @@ GCRuntime::gcIfRequested(JSContext* cx /* = nullptr */)
|
||||
return false;
|
||||
}
|
||||
|
||||
void js::gc::FinishGC(JSRuntime* rt)
|
||||
void
|
||||
js::gc::FinishGC(JSContext* cx)
|
||||
{
|
||||
if (JS::IsIncrementalGCInProgress(rt)) {
|
||||
JS::PrepareForIncrementalGC(rt);
|
||||
JS::FinishIncrementalGC(rt, JS::gcreason::API);
|
||||
if (JS::IsIncrementalGCInProgress(cx)) {
|
||||
JS::PrepareForIncrementalGC(cx);
|
||||
JS::FinishIncrementalGC(cx, JS::gcreason::API);
|
||||
}
|
||||
|
||||
rt->gc.nursery.waitBackgroundFreeEnd();
|
||||
cx->gc.nursery.waitBackgroundFreeEnd();
|
||||
}
|
||||
|
||||
AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime* rt, ZoneSelector selector)
|
||||
AutoPrepareForTracing::AutoPrepareForTracing(JSContext* cx, ZoneSelector selector)
|
||||
{
|
||||
js::gc::FinishGC(rt);
|
||||
session_.emplace(rt);
|
||||
js::gc::FinishGC(cx);
|
||||
session_.emplace(cx);
|
||||
}
|
||||
|
||||
JSCompartment*
|
||||
@ -6677,9 +6678,9 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
|
||||
MOZ_ASSERT(source->creationOptions().addonIdOrNull() ==
|
||||
target->creationOptions().addonIdOrNull());
|
||||
|
||||
JSRuntime* rt = source->runtimeFromMainThread();
|
||||
JSContext* cx = source->contextFromMainThread();
|
||||
|
||||
AutoPrepareForTracing prepare(rt, SkipAtoms);
|
||||
AutoPrepareForTracing prepare(cx, SkipAtoms);
|
||||
|
||||
// Cleanup tables and other state in the source compartment that will be
|
||||
// meaningless after merging into the target compartment.
|
||||
@ -6695,14 +6696,14 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
|
||||
|
||||
// Release any relocated arenas which we may be holding on to as they might
|
||||
// be in the source zone
|
||||
rt->gc.releaseHeldRelocatedArenas();
|
||||
cx->gc.releaseHeldRelocatedArenas();
|
||||
|
||||
// Fixup compartment pointers in source to refer to target, and make sure
|
||||
// type information generations are in sync.
|
||||
|
||||
// Get the static global lexical scope of the target compartment. Static
|
||||
// scopes need to be fixed up below.
|
||||
RootedObject targetStaticGlobalLexicalScope(rt);
|
||||
RootedObject targetStaticGlobalLexicalScope(cx);
|
||||
targetStaticGlobalLexicalScope = &target->maybeGlobal()->lexicalScope().staticBlock();
|
||||
|
||||
for (auto script = source->zone()->cellIter<JSScript>(); !script.done(); script.next()) {
|
||||
@ -6781,7 +6782,7 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
|
||||
MOZ_ASSERT(c.get() == source);
|
||||
|
||||
// Merge the allocator, stats and UIDs in source's zone into target's zone.
|
||||
target->zone()->arenas.adoptArenas(rt, &source->zone()->arenas);
|
||||
target->zone()->arenas.adoptArenas(cx, &source->zone()->arenas);
|
||||
target->zone()->usage.adopt(source->zone()->usage);
|
||||
target->zone()->adoptUniqueIds(source->zone());
|
||||
|
||||
@ -7195,28 +7196,28 @@ JS::PrepareZoneForGC(Zone* zone)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::PrepareForFullGC(JSRuntime* rt)
|
||||
JS::PrepareForFullGC(JSContext* cx)
|
||||
{
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
|
||||
for (ZonesIter zone(cx, WithAtoms); !zone.done(); zone.next())
|
||||
zone->scheduleGC();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::PrepareForIncrementalGC(JSRuntime* rt)
|
||||
JS::PrepareForIncrementalGC(JSContext* cx)
|
||||
{
|
||||
if (!JS::IsIncrementalGCInProgress(rt))
|
||||
if (!JS::IsIncrementalGCInProgress(cx))
|
||||
return;
|
||||
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
for (ZonesIter zone(cx, WithAtoms); !zone.done(); zone.next()) {
|
||||
if (zone->wasGCStarted())
|
||||
PrepareZoneForGC(zone);
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::IsGCScheduled(JSRuntime* rt)
|
||||
JS::IsGCScheduled(JSContext* cx)
|
||||
{
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
for (ZonesIter zone(cx, WithAtoms); !zone.done(); zone.next()) {
|
||||
if (zone->isGCScheduled())
|
||||
return true;
|
||||
}
|
||||
@ -7231,35 +7232,35 @@ JS::SkipZoneForGC(Zone* zone)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::GCForReason(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason)
|
||||
JS::GCForReason(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason)
|
||||
{
|
||||
MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK);
|
||||
rt->gc.gc(gckind, reason);
|
||||
cx->gc.gc(gckind, reason);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::StartIncrementalGC(JSRuntime* rt, JSGCInvocationKind gckind, gcreason::Reason reason, int64_t millis)
|
||||
JS::StartIncrementalGC(JSContext* cx, JSGCInvocationKind gckind, gcreason::Reason reason, int64_t millis)
|
||||
{
|
||||
MOZ_ASSERT(gckind == GC_NORMAL || gckind == GC_SHRINK);
|
||||
rt->gc.startGC(gckind, reason, millis);
|
||||
cx->gc.startGC(gckind, reason, millis);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::IncrementalGCSlice(JSRuntime* rt, gcreason::Reason reason, int64_t millis)
|
||||
JS::IncrementalGCSlice(JSContext* cx, gcreason::Reason reason, int64_t millis)
|
||||
{
|
||||
rt->gc.gcSlice(reason, millis);
|
||||
cx->gc.gcSlice(reason, millis);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::FinishIncrementalGC(JSRuntime* rt, gcreason::Reason reason)
|
||||
JS::FinishIncrementalGC(JSContext* cx, gcreason::Reason reason)
|
||||
{
|
||||
rt->gc.finishGC(reason);
|
||||
cx->gc.finishGC(reason);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::AbortIncrementalGC(JSRuntime* rt)
|
||||
JS::AbortIncrementalGC(JSContext* cx)
|
||||
{
|
||||
rt->gc.abortGC();
|
||||
cx->gc.abortGC();
|
||||
}
|
||||
|
||||
char16_t*
|
||||
@ -7314,39 +7315,39 @@ JS::GCDescription::formatJSON(JSRuntime* rt, uint64_t timestamp) const
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::GCSliceCallback)
|
||||
JS::SetGCSliceCallback(JSRuntime* rt, GCSliceCallback callback)
|
||||
JS::SetGCSliceCallback(JSContext* cx, GCSliceCallback callback)
|
||||
{
|
||||
return rt->gc.setSliceCallback(callback);
|
||||
return cx->gc.setSliceCallback(callback);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::GCNurseryCollectionCallback)
|
||||
JS::SetGCNurseryCollectionCallback(JSRuntime* rt, GCNurseryCollectionCallback callback)
|
||||
JS::SetGCNurseryCollectionCallback(JSContext* cx, GCNurseryCollectionCallback callback)
|
||||
{
|
||||
return rt->gc.setNurseryCollectionCallback(callback);
|
||||
return cx->gc.setNurseryCollectionCallback(callback);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::DisableIncrementalGC(JSRuntime* rt)
|
||||
JS::DisableIncrementalGC(JSContext* cx)
|
||||
{
|
||||
rt->gc.disallowIncrementalGC();
|
||||
cx->gc.disallowIncrementalGC();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::IsIncrementalGCEnabled(JSRuntime* rt)
|
||||
JS::IsIncrementalGCEnabled(JSContext* cx)
|
||||
{
|
||||
return rt->gc.isIncrementalGCEnabled();
|
||||
return cx->gc.isIncrementalGCEnabled();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::IsIncrementalGCInProgress(JSRuntime* rt)
|
||||
JS::IsIncrementalGCInProgress(JSContext* cx)
|
||||
{
|
||||
return rt->gc.isIncrementalGCInProgress() && !rt->gc.isVerifyPreBarriersEnabled();
|
||||
return cx->gc.isIncrementalGCInProgress() && !cx->gc.isVerifyPreBarriersEnabled();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::IsIncrementalBarrierNeeded(JSRuntime* rt)
|
||||
JS::IsIncrementalBarrierNeeded(JSContext* cx)
|
||||
{
|
||||
return rt->gc.state() == gc::MARK && !rt->isHeapBusy();
|
||||
return cx->gc.state() == gc::MARK && !cx->isHeapBusy();
|
||||
}
|
||||
|
||||
struct IncrementalReferenceBarrierFunctor {
|
||||
@ -7380,9 +7381,9 @@ JS::IncrementalObjectBarrier(JSObject* obj)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::WasIncrementalGC(JSRuntime* rt)
|
||||
JS::WasIncrementalGC(JSContext* cx)
|
||||
{
|
||||
return rt->gc.isIncrementalGc();
|
||||
return cx->gc.isIncrementalGc();
|
||||
}
|
||||
|
||||
JS::AutoDisableGenerationalGC::AutoDisableGenerationalGC(JSRuntime* rt)
|
||||
|
@ -992,7 +992,7 @@ typedef void (*IterateCellCallback)(JSRuntime* rt, void* data, void* thing,
|
||||
* on every in-use cell in the GC heap.
|
||||
*/
|
||||
extern void
|
||||
IterateZonesCompartmentsArenasCells(JSRuntime* rt, void* data,
|
||||
IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
@ -1003,7 +1003,7 @@ IterateZonesCompartmentsArenasCells(JSRuntime* rt, void* data,
|
||||
* single zone.
|
||||
*/
|
||||
extern void
|
||||
IterateZoneCompartmentsArenasCells(JSRuntime* rt, Zone* zone, void* data,
|
||||
IterateZoneCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
|
||||
IterateZoneCallback zoneCallback,
|
||||
JSIterateCompartmentCallback compartmentCallback,
|
||||
IterateArenaCallback arenaCallback,
|
||||
@ -1013,7 +1013,7 @@ IterateZoneCompartmentsArenasCells(JSRuntime* rt, Zone* zone, void* data,
|
||||
* Invoke chunkCallback on every in-use chunk.
|
||||
*/
|
||||
extern void
|
||||
IterateChunks(JSRuntime* rt, void* data, IterateChunkCallback chunkCallback);
|
||||
IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback);
|
||||
|
||||
typedef void (*IterateScriptCallback)(JSRuntime* rt, void* data, JSScript* script);
|
||||
|
||||
@ -1022,7 +1022,7 @@ typedef void (*IterateScriptCallback)(JSRuntime* rt, void* data, JSScript* scrip
|
||||
* the given compartment or for all compartments if it is null.
|
||||
*/
|
||||
extern void
|
||||
IterateScripts(JSRuntime* rt, JSCompartment* compartment,
|
||||
IterateScripts(JSContext* cx, JSCompartment* compartment,
|
||||
void* data, IterateScriptCallback scriptCallback);
|
||||
|
||||
extern void
|
||||
@ -1443,7 +1443,7 @@ struct MOZ_RAII AutoDisableProxyCheck
|
||||
|
||||
struct MOZ_RAII AutoDisableCompactingGC
|
||||
{
|
||||
explicit AutoDisableCompactingGC(JSRuntime* rt);
|
||||
explicit AutoDisableCompactingGC(JSContext* cx);
|
||||
~AutoDisableCompactingGC();
|
||||
|
||||
private:
|
||||
|
@ -2021,7 +2021,7 @@ GenerateLcovInfo(JSContext* cx, JSCompartment* comp, GenericPrinter& out)
|
||||
|
||||
// Collect the list of scripts which are part of the current compartment.
|
||||
{
|
||||
js::gc::AutoPrepareForTracing apft(rt, SkipAtoms);
|
||||
js::gc::AutoPrepareForTracing apft(cx, SkipAtoms);
|
||||
}
|
||||
Rooted<ScriptVector> topScripts(cx, ScriptVector(cx));
|
||||
for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
|
||||
|
@ -2495,8 +2495,8 @@ SaveSharedScriptData(ExclusiveContext* cx, Handle<JSScript*> script, SharedScrip
|
||||
* reachable. This is effectively a read barrier.
|
||||
*/
|
||||
if (cx->isJSContext()) {
|
||||
JSRuntime* rt = cx->asJSContext()->runtime();
|
||||
if (JS::IsIncrementalGCInProgress(rt) && rt->gc.isFullGc())
|
||||
JSContext* ncx = cx->asJSContext();
|
||||
if (JS::IsIncrementalGCInProgress(ncx) && ncx->gc.isFullGc())
|
||||
ssd->marked = true;
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,8 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>,
|
||||
if (!Base::init(len))
|
||||
return false;
|
||||
zone->gcWeakMapList.insertFront(this);
|
||||
marked = JS::IsIncrementalGCInProgress(zone->runtimeFromMainThread());
|
||||
JSRuntime* rt = zone->runtimeFromMainThread();
|
||||
marked = JS::IsIncrementalGCInProgress(rt->contextFromMainThread());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1218,7 +1218,7 @@ my_LargeAllocFailCallback(void* data)
|
||||
MOZ_ASSERT(!rt->isHeapBusy());
|
||||
MOZ_ASSERT(!rt->currentThreadHasExclusiveAccess());
|
||||
|
||||
JS::PrepareForFullGC(rt);
|
||||
JS::PrepareForFullGC(cx);
|
||||
AutoKeepAtoms keepAtoms(cx->perThreadData);
|
||||
rt->gc.gc(GC_NORMAL, JS::gcreason::SHARED_MEMORY_LIMIT);
|
||||
}
|
||||
@ -3917,7 +3917,7 @@ runOffThreadScript(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
JSRuntime* rt = cx->runtime();
|
||||
if (OffThreadParsingMustWaitForGC(rt))
|
||||
gc::FinishGC(rt);
|
||||
gc::FinishGC(cx);
|
||||
|
||||
void* token = offThreadState.waitUntilDone(cx, ScriptKind::Script);
|
||||
if (!token) {
|
||||
@ -4003,7 +4003,7 @@ FinishOffThreadModule(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
JSRuntime* rt = cx->runtime();
|
||||
if (OffThreadParsingMustWaitForGC(rt))
|
||||
gc::FinishGC(rt);
|
||||
gc::FinishGC(cx);
|
||||
|
||||
void* token = offThreadState.waitUntilDone(cx, ScriptKind::Module);
|
||||
if (!token) {
|
||||
@ -7030,7 +7030,7 @@ Shell(JSContext* cx, OptionParser* op, char** envp)
|
||||
|
||||
Maybe<AutoDisableCompactingGC> nocgc;
|
||||
if (op->getBoolOption("no-cgc"))
|
||||
nocgc.emplace(cx->runtime());
|
||||
nocgc.emplace(cx);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
|
@ -86,6 +86,24 @@ js::DebuggerEnvironment::owner() const
|
||||
return Debugger::fromJSObject(dbgobj);
|
||||
}
|
||||
|
||||
inline js::AbstractFramePtr
|
||||
js::DebuggerFrame::referent() const
|
||||
{
|
||||
AbstractFramePtr frame = AbstractFramePtr::FromRaw(getPrivate());
|
||||
if (frame.isScriptFrameIterData()) {
|
||||
ScriptFrameIter iter(*(ScriptFrameIter::Data*)(frame.raw()));
|
||||
frame = iter.abstractFramePtr();
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
inline js::Debugger*
|
||||
js::DebuggerFrame::owner() const
|
||||
{
|
||||
JSObject* dbgobj = &getReservedSlot(OWNER_SLOT).toObject();
|
||||
return Debugger::fromJSObject(dbgobj);
|
||||
}
|
||||
|
||||
inline js::Debugger*
|
||||
js::DebuggerObject::owner() const
|
||||
{
|
||||
|
@ -76,7 +76,7 @@ enum {
|
||||
JSSLOT_DEBUGFRAME_COUNT
|
||||
};
|
||||
|
||||
static const ClassOps DebuggerFrame_classOps = {
|
||||
const ClassOps DebuggerFrame::classOps_ = {
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* getProperty */
|
||||
@ -91,10 +91,10 @@ static const ClassOps DebuggerFrame_classOps = {
|
||||
nullptr, /* trace */
|
||||
};
|
||||
|
||||
static const Class DebuggerFrame_class = {
|
||||
const Class DebuggerFrame::class_ = {
|
||||
"Frame",
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGFRAME_COUNT),
|
||||
&DebuggerFrame_classOps
|
||||
&DebuggerFrame::classOps_
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -692,7 +692,7 @@ JS_STATIC_ASSERT(unsigned(JSSLOT_DEBUGFRAME_OWNER) == unsigned(DebuggerEnvironme
|
||||
/* static */ Debugger*
|
||||
Debugger::fromChildJSObject(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(obj->getClass() == &DebuggerFrame_class ||
|
||||
MOZ_ASSERT(obj->getClass() == &DebuggerFrame::class_ ||
|
||||
obj->getClass() == &DebuggerScript_class ||
|
||||
obj->getClass() == &DebuggerSource_class ||
|
||||
obj->getClass() == &DebuggerObject::class_ ||
|
||||
@ -715,45 +715,35 @@ Debugger::memory() const
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::getScriptFrameWithIter(JSContext* cx, AbstractFramePtr frame,
|
||||
Debugger::getScriptFrameWithIter(JSContext* cx, AbstractFramePtr referent,
|
||||
const ScriptFrameIter* maybeIter, MutableHandleValue vp)
|
||||
{
|
||||
MOZ_ASSERT_IF(maybeIter, maybeIter->abstractFramePtr() == frame);
|
||||
MOZ_ASSERT(!frame.script()->selfHosted());
|
||||
MOZ_ASSERT_IF(maybeIter, maybeIter->abstractFramePtr() == referent);
|
||||
MOZ_ASSERT(!referent.script()->selfHosted());
|
||||
|
||||
if (!frame.script()->ensureHasAnalyzedArgsUsage(cx))
|
||||
if (!referent.script()->ensureHasAnalyzedArgsUsage(cx))
|
||||
return false;
|
||||
|
||||
FrameMap::AddPtr p = frames.lookupForAdd(frame);
|
||||
FrameMap::AddPtr p = frames.lookupForAdd(referent);
|
||||
if (!p) {
|
||||
/* Create and populate the Debugger.Frame object. */
|
||||
RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject());
|
||||
RootedNativeObject frameobj(cx, NewNativeObjectWithGivenProto(cx, &DebuggerFrame_class,
|
||||
proto));
|
||||
if (!frameobj)
|
||||
RootedNativeObject debugger(cx, object);
|
||||
|
||||
RootedNativeObject frame(cx, DebuggerFrame::create(cx, proto, referent, maybeIter,
|
||||
debugger));
|
||||
if (!frame)
|
||||
return false;
|
||||
|
||||
// Eagerly copy ScriptFrameIter data if we've already walked the
|
||||
// stack.
|
||||
if (maybeIter) {
|
||||
AbstractFramePtr data = maybeIter->copyDataAsAbstractFramePtr();
|
||||
if (!data)
|
||||
return false;
|
||||
frameobj->setPrivate(data.raw());
|
||||
} else {
|
||||
frameobj->setPrivate(frame.raw());
|
||||
}
|
||||
|
||||
frameobj->setReservedSlot(JSSLOT_DEBUGFRAME_OWNER, ObjectValue(*object));
|
||||
|
||||
if (!ensureExecutionObservabilityOfFrame(cx, frame))
|
||||
if (!ensureExecutionObservabilityOfFrame(cx, referent))
|
||||
return false;
|
||||
|
||||
if (!frames.add(p, frame, frameobj)) {
|
||||
if (!frames.add(p, referent, frame)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
vp.setObject(*p->value());
|
||||
return true;
|
||||
}
|
||||
@ -4128,7 +4118,7 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery
|
||||
/* Search each compartment for debuggee scripts. */
|
||||
MOZ_ASSERT(vector.empty());
|
||||
oom = false;
|
||||
IterateScripts(cx->runtime(), singletonComp, this, considerScript);
|
||||
IterateScripts(cx, singletonComp, this, considerScript);
|
||||
if (oom) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -7014,6 +7004,69 @@ static const JSFunctionSpec DebuggerSource_methods[] = {
|
||||
|
||||
/*** Debugger.Frame ******************************************************************************/
|
||||
|
||||
/* static */ NativeObject*
|
||||
DebuggerFrame::initClass(JSContext* cx, HandleObject dbgCtor, HandleObject obj)
|
||||
{
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
|
||||
return InitClass(cx, dbgCtor, objProto, &class_, construct, 0, properties_,
|
||||
methods_, nullptr, nullptr);
|
||||
}
|
||||
|
||||
/* static */ DebuggerFrame*
|
||||
DebuggerFrame::create(JSContext* cx, HandleObject proto, AbstractFramePtr referent,
|
||||
const ScriptFrameIter* maybeIter, HandleNativeObject debugger)
|
||||
{
|
||||
JSObject* obj = NewObjectWithGivenProto(cx, &DebuggerFrame::class_, proto, TenuredObject);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
DebuggerFrame& frame = obj->as<DebuggerFrame>();
|
||||
|
||||
// Eagerly copy ScriptFrameIter data if we've already walked the stack.
|
||||
if (maybeIter) {
|
||||
AbstractFramePtr data = maybeIter->copyDataAsAbstractFramePtr();
|
||||
if (!data)
|
||||
return nullptr;
|
||||
frame.setPrivate(data.raw());
|
||||
} else {
|
||||
frame.setPrivate(referent.raw());
|
||||
}
|
||||
|
||||
frame.setReservedSlot(JSSLOT_DEBUGFRAME_OWNER, ObjectValue(*debugger));
|
||||
|
||||
return &frame;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerFrame::getCallee(JSContext* cx, Handle<DebuggerFrame*> frame,
|
||||
MutableHandle<DebuggerObject*> result)
|
||||
{
|
||||
AbstractFramePtr referent = frame->referent();
|
||||
if (!referent.isFunctionFrame()) {
|
||||
result.set(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
Debugger* dbg = frame->owner();
|
||||
|
||||
RootedObject callee(cx, referent.callee());
|
||||
return dbg->wrapDebuggeeObject(cx, callee, result);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerFrame::getIsConstructing(JSContext* cx, Handle<DebuggerFrame*> frame, bool& result)
|
||||
{
|
||||
Maybe<ScriptFrameIter> maybeIter;
|
||||
if (!DebuggerFrame::getScriptFrameIter(cx, frame, maybeIter))
|
||||
return false;
|
||||
ScriptFrameIter& iter = *maybeIter;
|
||||
|
||||
result = iter.isFunctionFrame() && iter.isConstructing();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateFrameIterPc(FrameIter& iter)
|
||||
{
|
||||
@ -7051,6 +7104,55 @@ UpdateFrameIterPc(FrameIter& iter)
|
||||
iter.updatePcQuadratic();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerFrame::getEnvironment(JSContext* cx, Handle<DebuggerFrame*> frame,
|
||||
MutableHandle<DebuggerEnvironment*> result)
|
||||
{
|
||||
Debugger* dbg = frame->owner();
|
||||
|
||||
Maybe<ScriptFrameIter> maybeIter;
|
||||
if (!DebuggerFrame::getScriptFrameIter(cx, frame, maybeIter))
|
||||
return false;
|
||||
ScriptFrameIter& iter = *maybeIter;
|
||||
|
||||
Rooted<Env*> env(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, iter.abstractFramePtr().scopeChain());
|
||||
UpdateFrameIterPc(iter);
|
||||
env = GetDebugScopeForFrame(cx, iter.abstractFramePtr(), iter.pc());
|
||||
if (!env)
|
||||
return false;
|
||||
}
|
||||
|
||||
return dbg->wrapEnvironment(cx, env, result);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerFrame::isGenerator() const
|
||||
{
|
||||
return referent().script()->isGenerator();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerFrame::getScriptFrameIter(JSContext* cx, Handle<DebuggerFrame*> frame,
|
||||
Maybe<ScriptFrameIter>& result)
|
||||
{
|
||||
AbstractFramePtr referent = AbstractFramePtr::FromRaw(frame->getPrivate());
|
||||
if (referent.isScriptFrameIterData()) {
|
||||
result.emplace(*reinterpret_cast<ScriptFrameIter::Data*>(referent.raw()));
|
||||
} else {
|
||||
result.emplace(cx, ScriptFrameIter::IGNORE_DEBUGGER_EVAL_PREV_LINK);
|
||||
ScriptFrameIter& iter = *result;
|
||||
while (!iter.hasUsableAbstractFramePtr() || iter.abstractFramePtr() != referent)
|
||||
++iter;
|
||||
AbstractFramePtr data = iter.copyDataAsAbstractFramePtr();
|
||||
if (!data)
|
||||
return false;
|
||||
frame->setPrivate(data.raw());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
DebuggerFrame_freeScriptFrameIterData(FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
@ -7075,22 +7177,22 @@ DebuggerFrame_finalize(FreeOp* fop, JSObject* obj)
|
||||
DebuggerFrame_freeScriptFrameIterData(fop, obj);
|
||||
}
|
||||
|
||||
static NativeObject*
|
||||
CheckThisFrame(JSContext* cx, const CallArgs& args, const char* fnname, bool checkLive)
|
||||
/* static */ DebuggerFrame*
|
||||
DebuggerFrame::checkThis(JSContext* cx, const CallArgs& args, const char* fnname, bool checkLive)
|
||||
{
|
||||
JSObject* thisobj = NonNullObject(cx, args.thisv());
|
||||
if (!thisobj)
|
||||
return nullptr;
|
||||
if (thisobj->getClass() != &DebuggerFrame_class) {
|
||||
if (thisobj->getClass() != &DebuggerFrame::class_) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
|
||||
"Debugger.Frame", fnname, thisobj->getClass()->name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NativeObject* nthisobj = &thisobj->as<NativeObject>();
|
||||
DebuggerFrame* nthisobj = &thisobj->as<DebuggerFrame>();
|
||||
|
||||
/*
|
||||
* Forbid Debugger.Frame.prototype, which is of class DebuggerFrame_class
|
||||
* Forbid Debugger.Frame.prototype, which is of class DebuggerFrame::class_
|
||||
* but isn't really a working Debugger.Frame object. The prototype object
|
||||
* is distinguished by having a nullptr private value. Also, forbid popped
|
||||
* frames.
|
||||
@ -7127,10 +7229,16 @@ CheckThisFrame(JSContext* cx, const CallArgs& args, const char* fnname, bool che
|
||||
* Methods that need a ScriptFrameIterator should use THIS_FRAME_ITER.
|
||||
*/
|
||||
|
||||
#define THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj) \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
RootedNativeObject thisobj(cx, CheckThisFrame(cx, args, fnname, true)); \
|
||||
if (!thisobj) \
|
||||
#define THIS_DEBUGGER_FRAME(cx, argc, vp, fnname, args, frame) \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
Rooted<DebuggerFrame*> frame(cx, DebuggerFrame::checkThis(cx, args, fnname, true)); \
|
||||
if (!frame) \
|
||||
return false;
|
||||
|
||||
#define THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj) \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
RootedNativeObject thisobj(cx, DebuggerFrame::checkThis(cx, args, fnname, true)); \
|
||||
if (!thisobj) \
|
||||
return false
|
||||
|
||||
#define THIS_FRAME(cx, argc, vp, fnname, args, thisobj, frame) \
|
||||
@ -7214,47 +7322,51 @@ DebuggerFrame_getImplementation(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerFrame_getEnvironment(JSContext* cx, unsigned argc, Value* vp)
|
||||
/* static */ bool
|
||||
DebuggerFrame::environmentGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_FRAME_OWNER_ITER(cx, argc, vp, "get environment", args, thisobj, _, iter, dbg);
|
||||
THIS_DEBUGGER_FRAME(cx, argc, vp, "get environment", args, frame);
|
||||
|
||||
Rooted<Env*> env(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, iter.abstractFramePtr().scopeChain());
|
||||
UpdateFrameIterPc(iter);
|
||||
env = GetDebugScopeForFrame(cx, iter.abstractFramePtr(), iter.pc());
|
||||
if (!env)
|
||||
return false;
|
||||
}
|
||||
|
||||
return dbg->wrapEnvironment(cx, env, args.rval());
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerFrame_getCallee(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_FRAME(cx, argc, vp, "get callee", args, thisobj, frame);
|
||||
RootedValue calleev(cx, frame.isFunctionFrame() ? frame.calleev() : NullValue());
|
||||
if (!Debugger::fromChildJSObject(thisobj)->wrapDebuggeeValue(cx, &calleev))
|
||||
Rooted<DebuggerEnvironment*> result(cx);
|
||||
if (!DebuggerFrame::getEnvironment(cx, frame, &result))
|
||||
return false;
|
||||
args.rval().set(calleev);
|
||||
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerFrame_getGenerator(JSContext* cx, unsigned argc, Value* vp)
|
||||
/* static */ bool
|
||||
DebuggerFrame::calleeGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_FRAME(cx, argc, vp, "get generator", args, thisobj, frame);
|
||||
args.rval().setBoolean(frame.script()->isGenerator());
|
||||
THIS_DEBUGGER_FRAME(cx, argc, vp, "get callee", args, frame);
|
||||
|
||||
Rooted<DebuggerObject*> result(cx);
|
||||
if (!DebuggerFrame::getCallee(cx, frame, &result))
|
||||
return false;
|
||||
|
||||
args.rval().setObjectOrNull(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerFrame_getConstructing(JSContext* cx, unsigned argc, Value* vp)
|
||||
/* static */ bool
|
||||
DebuggerFrame::generatorGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_FRAME_ITER(cx, argc, vp, "get constructing", args, thisobj, _, iter);
|
||||
args.rval().setBoolean(iter.isFunctionFrame() && iter.isConstructing());
|
||||
THIS_DEBUGGER_FRAME(cx, argc, vp, "get callee", args, frame);
|
||||
|
||||
args.rval().setBoolean(frame->isGenerator());
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerFrame::constructingGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGGER_FRAME(cx, argc, vp, "get callee", args, frame);
|
||||
|
||||
bool result;
|
||||
if (!DebuggerFrame::getIsConstructing(cx, frame, result))
|
||||
return false;
|
||||
|
||||
args.rval().setBoolean(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -7458,7 +7570,7 @@ static bool
|
||||
DebuggerFrame_getLive(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
NativeObject* thisobj = CheckThisFrame(cx, args, "get live", false);
|
||||
NativeObject* thisobj = DebuggerFrame::checkThis(cx, args, "get live", false);
|
||||
if (!thisobj)
|
||||
return false;
|
||||
bool hasFrame = !!thisobj->getPrivate();
|
||||
@ -7758,20 +7870,20 @@ DebuggerFrame_evalWithBindings(JSContext* cx, unsigned argc, Value* vp)
|
||||
return DebuggerGenericEval(cx, chars, bindings, options, args.rval(), dbg, nullptr, &iter);
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerFrame_construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
/* static */ bool
|
||||
DebuggerFrame::construct(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
|
||||
"Debugger.Frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
static const JSPropertySpec DebuggerFrame_properties[] = {
|
||||
const JSPropertySpec DebuggerFrame::properties_[] = {
|
||||
JS_PSG("arguments", DebuggerFrame_getArguments, 0),
|
||||
JS_PSG("callee", DebuggerFrame_getCallee, 0),
|
||||
JS_PSG("constructing", DebuggerFrame_getConstructing, 0),
|
||||
JS_PSG("environment", DebuggerFrame_getEnvironment, 0),
|
||||
JS_PSG("generator", DebuggerFrame_getGenerator, 0),
|
||||
JS_PSG("callee", DebuggerFrame::calleeGetter, 0),
|
||||
JS_PSG("constructing", DebuggerFrame::constructingGetter, 0),
|
||||
JS_PSG("environment", DebuggerFrame::environmentGetter, 0),
|
||||
JS_PSG("generator", DebuggerFrame::generatorGetter, 0),
|
||||
JS_PSG("live", DebuggerFrame_getLive, 0),
|
||||
JS_PSG("offset", DebuggerFrame_getOffset, 0),
|
||||
JS_PSG("older", DebuggerFrame_getOlder, 0),
|
||||
@ -7784,7 +7896,7 @@ static const JSPropertySpec DebuggerFrame_properties[] = {
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
static const JSFunctionSpec DebuggerFrame_methods[] = {
|
||||
const JSFunctionSpec DebuggerFrame::methods_[] = {
|
||||
JS_FN("eval", DebuggerFrame_eval, 1, 0),
|
||||
JS_FN("evalWithBindings", DebuggerFrame_evalWithBindings, 1, 0),
|
||||
JS_FS_END
|
||||
@ -10201,10 +10313,7 @@ JS_DefineDebuggerObject(JSContext* cx, HandleObject obj)
|
||||
if (!debugProto)
|
||||
return false;
|
||||
|
||||
frameProto = InitClass(cx, debugCtor, objProto, &DebuggerFrame_class,
|
||||
DebuggerFrame_construct, 0,
|
||||
DebuggerFrame_properties, DebuggerFrame_methods,
|
||||
nullptr, nullptr);
|
||||
frameProto = DebuggerFrame::initClass(cx, debugCtor, obj);
|
||||
if (!frameProto)
|
||||
return false;
|
||||
|
||||
|
@ -1130,6 +1130,52 @@ class DebuggerEnvironment : public NativeObject
|
||||
static MOZ_MUST_USE bool setVariableMethod(JSContext* cx, unsigned argc, Value* vp);
|
||||
};
|
||||
|
||||
class DebuggerFrame : public NativeObject
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
OWNER_SLOT
|
||||
};
|
||||
|
||||
static const unsigned RESERVED_SLOTS = 1;
|
||||
|
||||
static const Class class_;
|
||||
|
||||
static NativeObject* initClass(JSContext* cx, HandleObject dbgCtor, HandleObject objProto);
|
||||
static DebuggerFrame* create(JSContext* cx, HandleObject proto, AbstractFramePtr referent,
|
||||
const ScriptFrameIter* maybeIter, HandleNativeObject debugger);
|
||||
static DebuggerFrame* checkThis(JSContext* cx, const CallArgs& args, const char* fnname,
|
||||
bool checkLive);
|
||||
|
||||
static MOZ_MUST_USE bool getCallee(JSContext* cx, Handle<DebuggerFrame*> frame,
|
||||
MutableHandle<DebuggerObject*> result);
|
||||
static MOZ_MUST_USE bool getIsConstructing(JSContext* cx, Handle<DebuggerFrame*> frame,
|
||||
bool& result);
|
||||
static MOZ_MUST_USE bool getEnvironment(JSContext* cx, Handle<DebuggerFrame*> frame,
|
||||
MutableHandle<DebuggerEnvironment*> result);
|
||||
|
||||
bool isGenerator() const;
|
||||
|
||||
private:
|
||||
static const ClassOps classOps_;
|
||||
|
||||
static const JSPropertySpec properties_[];
|
||||
static const JSFunctionSpec methods_[];
|
||||
|
||||
static MOZ_MUST_USE bool getScriptFrameIter(JSContext* cx, Handle<DebuggerFrame*> frame,
|
||||
mozilla::Maybe<ScriptFrameIter>& result);
|
||||
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static MOZ_MUST_USE bool calleeGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool constructingGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool environmentGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool generatorGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
AbstractFramePtr referent() const;
|
||||
Debugger* owner() const;
|
||||
};
|
||||
|
||||
class DebuggerObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
|
@ -1157,7 +1157,7 @@ GlobalHelperThreadState::finishParseTask(JSContext* maybecx, JSRuntime* rt, Pars
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mergeParseTaskCompartment(rt, parseTask, global, cx->compartment());
|
||||
mergeParseTaskCompartment(cx, parseTask, global, cx->compartment());
|
||||
|
||||
if (!parseTask->finish(cx))
|
||||
return nullptr;
|
||||
@ -1229,7 +1229,7 @@ GlobalObject::getStarGeneratorFunctionPrototype()
|
||||
}
|
||||
|
||||
void
|
||||
GlobalHelperThreadState::mergeParseTaskCompartment(JSRuntime* rt, ParseTask* parseTask,
|
||||
GlobalHelperThreadState::mergeParseTaskCompartment(JSContext* cx, ParseTask* parseTask,
|
||||
Handle<GlobalObject*> global,
|
||||
JSCompartment* dest)
|
||||
{
|
||||
@ -1237,10 +1237,10 @@ GlobalHelperThreadState::mergeParseTaskCompartment(JSRuntime* rt, ParseTask* par
|
||||
// finished merging the contents of the parse task's compartment into the
|
||||
// destination compartment. Finish any ongoing incremental GC first and
|
||||
// assert that no allocation can occur.
|
||||
gc::FinishGC(rt);
|
||||
JS::AutoAssertNoAlloc noAlloc(rt);
|
||||
gc::FinishGC(cx);
|
||||
JS::AutoAssertNoAlloc noAlloc(cx);
|
||||
|
||||
LeaveParseTaskZone(rt, parseTask);
|
||||
LeaveParseTaskZone(cx, parseTask);
|
||||
|
||||
{
|
||||
// Generator functions don't have Function.prototype as prototype but a
|
||||
|
@ -226,7 +226,7 @@ class GlobalHelperThreadState
|
||||
}
|
||||
|
||||
JSScript* finishParseTask(JSContext* maybecx, JSRuntime* rt, ParseTaskKind kind, void* token);
|
||||
void mergeParseTaskCompartment(JSRuntime* rt, ParseTask* parseTask,
|
||||
void mergeParseTaskCompartment(JSContext* cx, ParseTask* parseTask,
|
||||
Handle<GlobalObject*> global,
|
||||
JSCompartment* dest);
|
||||
|
||||
|
@ -768,9 +768,10 @@ FindNotableScriptSources(JS::RuntimeSizes& runtime)
|
||||
}
|
||||
|
||||
static bool
|
||||
CollectRuntimeStatsHelper(JSRuntime* rt, RuntimeStats* rtStats, ObjectPrivateVisitor* opv,
|
||||
CollectRuntimeStatsHelper(JSContext* cx, RuntimeStats* rtStats, ObjectPrivateVisitor* opv,
|
||||
bool anonymize, IterateCellCallback statsCellCallback)
|
||||
{
|
||||
JSRuntime* rt = cx;
|
||||
if (!rtStats->compartmentStatsVector.reserve(rt->numCompartments))
|
||||
return false;
|
||||
|
||||
@ -783,14 +784,14 @@ CollectRuntimeStatsHelper(JSRuntime* rt, RuntimeStats* rtStats, ObjectPrivateVis
|
||||
rtStats->gcHeapUnusedChunks =
|
||||
size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize;
|
||||
|
||||
IterateChunks(rt, &rtStats->gcHeapDecommittedArenas,
|
||||
IterateChunks(cx, &rtStats->gcHeapDecommittedArenas,
|
||||
DecommittedArenasChunkCallback);
|
||||
|
||||
// Take the per-compartment measurements.
|
||||
StatsClosure closure(rtStats, opv, anonymize);
|
||||
if (!closure.init())
|
||||
return false;
|
||||
IterateZonesCompartmentsArenasCells(rt, &closure,
|
||||
IterateZonesCompartmentsArenasCells(cx, &closure,
|
||||
StatsZoneCallback,
|
||||
StatsCompartmentCallback,
|
||||
StatsArenaCallback,
|
||||
@ -865,10 +866,10 @@ CollectRuntimeStatsHelper(JSRuntime* rt, RuntimeStats* rtStats, ObjectPrivateVis
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv,
|
||||
JS::CollectRuntimeStats(JSContext* cx, RuntimeStats *rtStats, ObjectPrivateVisitor *opv,
|
||||
bool anonymize)
|
||||
{
|
||||
return CollectRuntimeStatsHelper(rt, rtStats, opv, anonymize, StatsCellCallback<FineGrained>);
|
||||
return CollectRuntimeStatsHelper(cx, rtStats, opv, anonymize, StatsCellCallback<FineGrained>);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(size_t)
|
||||
@ -918,7 +919,7 @@ class SimpleJSRuntimeStats : public JS::RuntimeStats
|
||||
};
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
AddSizeOfTab(JSRuntime* rt, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectPrivateVisitor* opv,
|
||||
AddSizeOfTab(JSContext* cx, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectPrivateVisitor* opv,
|
||||
TabSizes* sizes)
|
||||
{
|
||||
SimpleJSRuntimeStats rtStats(mallocSizeOf);
|
||||
@ -936,7 +937,7 @@ AddSizeOfTab(JSRuntime* rt, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectP
|
||||
StatsClosure closure(&rtStats, opv, /* anonymize = */ false);
|
||||
if (!closure.init())
|
||||
return false;
|
||||
IterateZoneCompartmentsArenasCells(rt, zone, &closure,
|
||||
IterateZoneCompartmentsArenasCells(cx, zone, &closure,
|
||||
StatsZoneCallback,
|
||||
StatsCompartmentCallback,
|
||||
StatsArenaCallback,
|
||||
@ -958,13 +959,13 @@ AddSizeOfTab(JSRuntime* rt, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectP
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
AddServoSizeOf(JSRuntime *rt, MallocSizeOf mallocSizeOf, ObjectPrivateVisitor *opv,
|
||||
AddServoSizeOf(JSContext* cx, MallocSizeOf mallocSizeOf, ObjectPrivateVisitor *opv,
|
||||
ServoSizes *sizes)
|
||||
{
|
||||
SimpleJSRuntimeStats rtStats(mallocSizeOf);
|
||||
|
||||
// No need to anonymize because the results will be aggregated.
|
||||
if (!CollectRuntimeStatsHelper(rt, &rtStats, opv, /* anonymize = */ false,
|
||||
if (!CollectRuntimeStatsHelper(cx, &rtStats, opv, /* anonymize = */ false,
|
||||
StatsCellCallback<CoarseGrained>))
|
||||
return false;
|
||||
|
||||
|
@ -385,8 +385,9 @@ JSRuntime::destroyRuntime()
|
||||
* Finish any in-progress GCs first. This ensures the parseWaitingOnGC
|
||||
* list is empty in CancelOffThreadParses.
|
||||
*/
|
||||
if (JS::IsIncrementalGCInProgress(this))
|
||||
FinishGC(this);
|
||||
JSContext* cx = contextFromMainThread();
|
||||
if (JS::IsIncrementalGCInProgress(cx))
|
||||
FinishGC(cx);
|
||||
|
||||
/* Free source hook early, as its destructor may want to delete roots. */
|
||||
sourceHook = nullptr;
|
||||
@ -432,7 +433,7 @@ JSRuntime::destroyRuntime()
|
||||
/* Set the profiler sampler buffer generation to invalid. */
|
||||
profilerSampleBufferGen_ = UINT32_MAX;
|
||||
|
||||
JS::PrepareForFullGC(this);
|
||||
JS::PrepareForFullGC(contextFromMainThread());
|
||||
gc.gc(GC_NORMAL, JS::gcreason::DESTROY_RUNTIME);
|
||||
}
|
||||
|
||||
|
@ -2570,9 +2570,9 @@ nsXPCComponents_Utils::GetWeakReference(HandleValue object, JSContext* cx,
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceGC()
|
||||
{
|
||||
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
||||
PrepareForFullGC(rt);
|
||||
GCForReason(rt, GC_NORMAL, gcreason::COMPONENT_UTILS);
|
||||
JSContext* cx = nsXPConnect::GetRuntimeInstance()->Context();
|
||||
PrepareForFullGC(cx);
|
||||
GCForReason(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2614,9 +2614,9 @@ nsXPCComponents_Utils::ClearMaxCCTime()
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceShrinkingGC()
|
||||
{
|
||||
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
||||
PrepareForFullGC(rt);
|
||||
GCForReason(rt, GC_SHRINK, gcreason::COMPONENT_UTILS);
|
||||
JSContext* cx = nsXPConnect::GetRuntimeInstance()->Context();
|
||||
PrepareForFullGC(cx);
|
||||
GCForReason(cx, GC_SHRINK, gcreason::COMPONENT_UTILS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1655,7 +1655,7 @@ XPCJSRuntime::~XPCJSRuntime()
|
||||
// to destroy it later we will crash.
|
||||
SetPendingException(nullptr);
|
||||
|
||||
JS::SetGCSliceCallback(Runtime(), mPrevGCSliceCallback);
|
||||
JS::SetGCSliceCallback(Context(), mPrevGCSliceCallback);
|
||||
|
||||
xpc_DelocalizeRuntime(Runtime());
|
||||
|
||||
@ -2952,7 +2952,7 @@ JSReporter::CollectReports(WindowPaths* windowPaths,
|
||||
XPCJSRuntimeStats rtStats(windowPaths, topWindowPaths, getLocations,
|
||||
anonymize);
|
||||
OrphanReporter orphanReporter(XPCConvert::GetISupportsFromJSObject);
|
||||
if (!JS::CollectRuntimeStats(xpcrt->Runtime(), &rtStats, &orphanReporter,
|
||||
if (!JS::CollectRuntimeStats(xpcrt->Context(), &rtStats, &orphanReporter,
|
||||
anonymize))
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -3135,12 +3135,12 @@ static nsresult
|
||||
JSSizeOfTab(JSObject* objArg, size_t* jsObjectsSize, size_t* jsStringsSize,
|
||||
size_t* jsPrivateSize, size_t* jsOtherSize)
|
||||
{
|
||||
JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->Runtime();
|
||||
JS::RootedObject obj(rt, objArg);
|
||||
JSContext* cx = nsXPConnect::GetRuntimeInstance()->Context();
|
||||
JS::RootedObject obj(cx, objArg);
|
||||
|
||||
TabSizes sizes;
|
||||
OrphanReporter orphanReporter(XPCConvert::GetISupportsFromJSObject);
|
||||
NS_ENSURE_TRUE(JS::AddSizeOfTab(rt, obj, moz_malloc_size_of,
|
||||
NS_ENSURE_TRUE(JS::AddSizeOfTab(cx, obj, moz_malloc_size_of,
|
||||
&orphanReporter, &sizes),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
@ -3555,7 +3555,7 @@ XPCJSRuntime::Initialize()
|
||||
JS_SetDestroyCompartmentCallback(cx, CompartmentDestroyedCallback);
|
||||
JS_SetSizeOfIncludingThisCompartmentCallback(cx, CompartmentSizeOfIncludingThisCallback);
|
||||
JS_SetCompartmentNameCallback(cx, CompartmentNameCallback);
|
||||
mPrevGCSliceCallback = JS::SetGCSliceCallback(runtime, GCSliceCallback);
|
||||
mPrevGCSliceCallback = JS::SetGCSliceCallback(cx, GCSliceCallback);
|
||||
JS_AddFinalizeCallback(cx, FinalizeCallback, nullptr);
|
||||
JS_AddWeakPointerZoneGroupCallback(cx, WeakPointerZoneGroupCallback, this);
|
||||
JS_AddWeakPointerCompartmentCallback(cx, WeakPointerCompartmentCallback, this);
|
||||
@ -3845,7 +3845,7 @@ void
|
||||
XPCRootSetElem::RemoveFromRootSet()
|
||||
{
|
||||
nsXPConnect* xpc = nsXPConnect::XPConnect();
|
||||
JS::PokeGC(xpc->GetRuntime()->Runtime());
|
||||
JS::PokeGC(xpc->GetRuntime()->Context());
|
||||
|
||||
MOZ_ASSERT(mSelfp, "Must be linked");
|
||||
|
||||
|
@ -625,8 +625,8 @@ XPCWrappedNative::UpdateScriptableInfo(XPCNativeScriptableInfo* si)
|
||||
MOZ_ASSERT(mScriptableInfo, "UpdateScriptableInfo expects an existing scriptable info");
|
||||
|
||||
// Write barrier for incremental GC.
|
||||
JSRuntime* rt = GetRuntime()->Runtime();
|
||||
if (IsIncrementalBarrierNeeded(rt))
|
||||
JSContext* cx = GetRuntime()->Context();
|
||||
if (IsIncrementalBarrierNeeded(cx))
|
||||
mScriptableInfo->Mark();
|
||||
|
||||
mScriptableInfo = si;
|
||||
@ -640,8 +640,8 @@ XPCWrappedNative::SetProto(XPCWrappedNativeProto* p)
|
||||
MOZ_ASSERT(HasProto());
|
||||
|
||||
// Write barrier for incremental GC.
|
||||
JSRuntime* rt = GetRuntime()->Runtime();
|
||||
GetProto()->WriteBarrierPre(rt);
|
||||
JSContext* cx = GetRuntime()->Context();
|
||||
GetProto()->WriteBarrierPre(cx);
|
||||
|
||||
mMaybeProto = p;
|
||||
}
|
||||
|
@ -1083,7 +1083,7 @@ SetLocationForGlobal(JSObject* global, nsIURI* locationURI)
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::NotifyDidPaint()
|
||||
{
|
||||
JS::NotifyDidPaint(GetRuntime()->Runtime());
|
||||
JS::NotifyDidPaint(GetRuntime()->Context());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1735,10 +1735,10 @@ public:
|
||||
TraceInside(trc);
|
||||
}
|
||||
|
||||
void WriteBarrierPre(JSRuntime* rt)
|
||||
void WriteBarrierPre(JSContext* cx)
|
||||
{
|
||||
if (JS::IsIncrementalBarrierNeeded(rt) && mJSProtoObject)
|
||||
mJSProtoObject.writeBarrierPre(rt);
|
||||
if (JS::IsIncrementalBarrierNeeded(cx) && mJSProtoObject)
|
||||
mJSProtoObject.writeBarrierPre(cx);
|
||||
}
|
||||
|
||||
// NOP. This is just here to make the AutoMarkingPtr code compile.
|
||||
|
@ -67,14 +67,12 @@ EvictTouchPoint(RefPtr<dom::Touch>& aTouch,
|
||||
event.mTouches.AppendElement(aTouch);
|
||||
nsEventStatus status;
|
||||
widget->DispatchEvent(&event, status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!node || !aLimitToDocument || node->OwnerDoc() == aLimitToDocument) {
|
||||
// We couldn't dispatch touchend. Remove the touch from gCaptureTouchList explicitly.
|
||||
TouchManager::gCaptureTouchList->Remove(aTouch->Identifier());
|
||||
}
|
||||
}
|
||||
|
@ -5621,6 +5621,13 @@ ScrollFrameHelper::GetBorderRadii(const nsSize& aFrameSize,
|
||||
return true;
|
||||
}
|
||||
|
||||
static nscoord
|
||||
SnapCoord(nscoord aCoord, double aRes, nscoord aAppUnitsPerPixel)
|
||||
{
|
||||
double snappedToLayerPixels = NS_round((aRes*aCoord)/aAppUnitsPerPixel);
|
||||
return NSToCoordRoundWithClamp(snappedToLayerPixels*aAppUnitsPerPixel/aRes);
|
||||
}
|
||||
|
||||
nsRect
|
||||
ScrollFrameHelper::GetScrolledRect() const
|
||||
{
|
||||
@ -5634,30 +5641,82 @@ ScrollFrameHelper::GetScrolledRect() const
|
||||
if (result.height < mScrollPort.height) {
|
||||
NS_WARNING("Scrolled rect smaller than scrollport?");
|
||||
}
|
||||
|
||||
// Expand / contract the result by up to half a layer pixel so that scrolling
|
||||
// to the right / bottom edge does not change the layer pixel alignment of
|
||||
// the scrolled contents.
|
||||
// For that, we first convert the scroll port and the scrolled rect to rects
|
||||
// relative to the reference frame, since that's the space where painting does
|
||||
// snapping.
|
||||
nsSize scrollPortSize = GetScrollPositionClampingScrollPortSize();
|
||||
nsIFrame* referenceFrame = nsLayoutUtils::GetReferenceFrame(mOuter);
|
||||
nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(referenceFrame);
|
||||
nsRect scrollPort(mScrollPort.TopLeft() + toReferenceFrame, scrollPortSize);
|
||||
nsRect scrolledRect = result + scrollPort.TopLeft();
|
||||
|
||||
if (scrollPort.Overflows() || scrolledRect.Overflows()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Now, snap the bottom right corner of both of these rects.
|
||||
// We snap to layer pixels, so we need to respect the layer's scale.
|
||||
nscoord appUnitsPerDevPixel = mScrolledFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
gfxSize scale = FrameLayerBuilder::GetPaintedLayerScaleForFrame(mScrolledFrame);
|
||||
if (scale.IsEmpty()) {
|
||||
scale = gfxSize(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Compute bounds for the scroll position, and computed the snapped scrolled
|
||||
// rect from the scroll position bounds.
|
||||
nscoord snappedScrolledAreaBottom = SnapCoord(scrolledRect.YMost(), scale.height, appUnitsPerDevPixel);
|
||||
nscoord snappedScrollPortBottom = SnapCoord(scrollPort.YMost(), scale.height, appUnitsPerDevPixel);
|
||||
nscoord maximumScrollOffsetY = snappedScrolledAreaBottom - snappedScrollPortBottom;
|
||||
result.SetBottomEdge(scrollPort.height + maximumScrollOffsetY);
|
||||
|
||||
if (GetScrolledFrameDir() == NS_STYLE_DIRECTION_LTR) {
|
||||
nscoord snappedScrolledAreaRight = SnapCoord(scrolledRect.XMost(), scale.width, appUnitsPerDevPixel);
|
||||
nscoord snappedScrollPortRight = SnapCoord(scrollPort.XMost(), scale.width, appUnitsPerDevPixel);
|
||||
nscoord maximumScrollOffsetX = snappedScrolledAreaRight - snappedScrollPortRight;
|
||||
result.SetRightEdge(scrollPort.width + maximumScrollOffsetX);
|
||||
} else {
|
||||
// In RTL, the scrolled area's right edge is at scrollPort.XMost(),
|
||||
// and the scrolled area's x position is zero or negative. We want
|
||||
// the right edge to stay flush with the scroll port, so we snap the
|
||||
// left edge.
|
||||
nscoord snappedScrolledAreaLeft = SnapCoord(scrolledRect.x, scale.width, appUnitsPerDevPixel);
|
||||
nscoord snappedScrollPortLeft = SnapCoord(scrollPort.x, scale.width, appUnitsPerDevPixel);
|
||||
nscoord minimumScrollOffsetX = snappedScrolledAreaLeft - snappedScrollPortLeft;
|
||||
result.SetLeftEdge(minimumScrollOffsetX);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsRect
|
||||
ScrollFrameHelper::GetScrolledRectInternal(const nsRect& aScrolledFrameOverflowArea,
|
||||
const nsSize& aScrollPortSize) const
|
||||
{
|
||||
uint8_t frameDir = IsLTR() ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
|
||||
|
||||
uint8_t
|
||||
ScrollFrameHelper::GetScrolledFrameDir() const
|
||||
{
|
||||
// If the scrolled frame has unicode-bidi: plaintext, the paragraph
|
||||
// direction set by the text content overrides the direction of the frame
|
||||
if (mScrolledFrame->StyleTextReset()->mUnicodeBidi &
|
||||
NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
|
||||
nsIFrame* childFrame = mScrolledFrame->PrincipalChildList().FirstChild();
|
||||
if (childFrame) {
|
||||
frameDir =
|
||||
(nsBidiPresUtils::ParagraphDirection(childFrame) == NSBIDI_LTR)
|
||||
return (nsBidiPresUtils::ParagraphDirection(childFrame) == NSBIDI_LTR)
|
||||
? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
|
||||
}
|
||||
}
|
||||
|
||||
return IsLTR() ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
nsRect
|
||||
ScrollFrameHelper::GetScrolledRectInternal(const nsRect& aScrolledFrameOverflowArea,
|
||||
const nsSize& aScrollPortSize) const
|
||||
{
|
||||
return nsLayoutUtils::GetScrolledRect(mScrolledFrame,
|
||||
aScrolledFrameOverflowArea,
|
||||
aScrollPortSize, frameDir);
|
||||
aScrollPortSize, GetScrolledFrameDir());
|
||||
}
|
||||
|
||||
nsMargin
|
||||
|
@ -626,6 +626,7 @@ protected:
|
||||
AsyncScrollEventType mAsyncScrollEvent;
|
||||
bool HasPluginFrames();
|
||||
bool HasPerspective() const;
|
||||
uint8_t GetScrolledFrameDir() const;
|
||||
|
||||
static void EnsureFrameVisPrefsCached();
|
||||
static bool sFrameVisPrefsCached;
|
||||
|
@ -9,7 +9,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="outer" style="overflow:auto; height:200px; border:2px dotted black;" onscroll="doneScroll()">
|
||||
<div id="outer" style="overflow:auto; height:200px; border:2px dotted black; transform: translateY(1px)" onscroll="doneScroll()">
|
||||
<div id="d" style="overflow:auto; height:102px;" onscroll="doneScroll()">
|
||||
<div id="inner" style="height:100.1px; border:1px solid black; background:yellow;">Hello</div>
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@
|
||||
position: absolute;
|
||||
left: 200px;
|
||||
top: 100px;
|
||||
font: 14px/1.1em "Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;
|
||||
font: 14px/1.3em "Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" reftest-async-scroll>
|
||||
<meta charset="utf-8">
|
||||
<title>Make sure the scrolled layer is not invalidated when you scroll all the way to the bottom</title>
|
||||
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.scrollbox {
|
||||
margin: 50px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.scrolled-contents {
|
||||
height: 150.2px;
|
||||
padding-top: 150px;
|
||||
}
|
||||
|
||||
.reftest-no-paint {
|
||||
margin: 0 20px;
|
||||
border: 1px solid blue;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="scrollbox"
|
||||
reftest-displayport-x="0" reftest-displayport-y="0"
|
||||
reftest-displayport-w="200" reftest-displayport-h="200"
|
||||
reftest-async-scroll-x="0" reftest-async-scroll-y="0">
|
||||
<div class="scrolled-contents">
|
||||
<div class="reftest-no-paint">
|
||||
<!-- This element has the magic "reftest-no-paint" class which
|
||||
constitutes the actual test here. -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var scrollbox = document.querySelector(".scrollbox");
|
||||
scrollbox.scrollTop = 2;
|
||||
scrollbox.scrollTop = 1;
|
||||
scrollbox.scrollTop = 0;
|
||||
|
||||
function doTest() {
|
||||
scrollbox.scrollTop = 999;
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
document.addEventListener("MozReftestInvalidate", doTest);
|
||||
|
||||
</script>
|
74
layout/reftests/scrolling/fractional-scroll-area.html
Normal file
74
layout/reftests/scrolling/fractional-scroll-area.html
Normal file
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>Fractional scroll area position / size</title>
|
||||
|
||||
<style>
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#scrollbox {
|
||||
width: 200px;
|
||||
overflow: hidden;
|
||||
background: red;
|
||||
}
|
||||
|
||||
#scrolled-content {
|
||||
background: lime;
|
||||
box-sizing: border-box;
|
||||
border: solid black;
|
||||
border-width: 1px 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div id="scrollbox">
|
||||
<div id="scrolled-content"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
function getFloatQueryParams(defaultValues) {
|
||||
let result = Object.assign({}, defaultValues);
|
||||
for (let chunk of location.search.substr(1).split("&")) {
|
||||
let parts = chunk.split("=");
|
||||
result[parts[0]] = parseFloat(parts[1]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let params = getFloatQueryParams({
|
||||
top: 0,
|
||||
outerBottom: 100,
|
||||
innerBottom: 100,
|
||||
borderTop: 0,
|
||||
borderBottom: 0,
|
||||
scrollBefore: 0,
|
||||
scrollAfter: undefined,
|
||||
offsetAfter: undefined,
|
||||
});
|
||||
|
||||
let scrollArea = document.getElementById("scrollbox");
|
||||
let scrolledContent = document.getElementById("scrolled-content");
|
||||
|
||||
scrollArea.style.marginTop = params.top + "px";
|
||||
scrollArea.style.height = (params.outerBottom - params.top) + "px";
|
||||
scrolledContent.style.height = (params.innerBottom - params.top) + "px";
|
||||
|
||||
scrollArea.scrollTop = 1;
|
||||
scrollArea.scrollTop = 2;
|
||||
scrollArea.scrollTop = params.scrollBefore;
|
||||
|
||||
window.addEventListener("MozReftestInvalidate", function () {
|
||||
if (params.scrollAfter !== undefined) {
|
||||
scrollArea.scrollTop = params.scrollAfter;
|
||||
}
|
||||
if (params.offsetAfter !== undefined) {
|
||||
document.body.style.marginTop = params.offsetAfter + "px";
|
||||
}
|
||||
document.documentElement.className = "";
|
||||
});
|
||||
|
||||
</script>
|
@ -36,3 +36,52 @@ skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,
|
||||
== frame-scrolling-attr-1.html frame-scrolling-attr-ref.html
|
||||
fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2420) == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html
|
||||
== move-item.html move-item-ref.html # bug 1125750
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
|
||||
!= fractional-scroll-area-invalidation.html about:blank
|
||||
|
@ -22,7 +22,7 @@ skip-if(B2G||Mulet) HTTP(..) == table-cell.html table-cell-ref.html # Initial mu
|
||||
skip-if(Mulet) fuzzy-if(gtkWidget,10,32) HTTP(..) == two-value-syntax.html two-value-syntax-ref.html # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables
|
||||
skip-if(B2G||Mulet) HTTP(..) == single-value.html single-value-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
skip-if(B2G||Mulet) fuzzy-if(gtkWidget,10,2) HTTP(..) == atomic-under-marker.html atomic-under-marker-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fuzzy(1,702) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
fuzzy(1,2616) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
|
||||
HTTP(..) == combobox-zoom.html combobox-zoom-ref.html
|
||||
|
||||
# The vertical-text pref setting can be removed after bug 1138384 lands
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsString.h"
|
||||
#include "nsStyleStruct.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include "StyleStructContext.h"
|
||||
|
||||
#include "mozilla/EventStates.h"
|
||||
@ -163,6 +164,125 @@ Gecko_GetElementId(RawGeckoElement* aElement)
|
||||
return attr ? attr->GetAtomValue() : nullptr;
|
||||
}
|
||||
|
||||
template<class MatchFn>
|
||||
bool
|
||||
DoMatch(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName, MatchFn aMatch)
|
||||
{
|
||||
if (aNS) {
|
||||
int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS);
|
||||
NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
|
||||
const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
|
||||
return value && aMatch(value);
|
||||
}
|
||||
// No namespace means any namespace - we have to check them all. :-(
|
||||
const nsAttrName* attrName;
|
||||
for (uint32_t i = 0; (attrName = aElement->GetAttrNameAt(i)); ++i) {
|
||||
if (attrName->LocalName() != aName) {
|
||||
continue;
|
||||
}
|
||||
const nsAttrValue* value =
|
||||
aElement->GetParsedAttr(attrName->LocalName(), attrName->NamespaceID());
|
||||
if (aMatch(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Work around our overly-restrictive static analysis. This can be removed once
|
||||
// bug 1281935 lands.
|
||||
template<typename T>
|
||||
struct FakeRef {
|
||||
MOZ_IMPLICIT FakeRef(T* aPtr) : mPtr(aPtr) {}
|
||||
operator T*() const { return mPtr; }
|
||||
T* mPtr;
|
||||
};
|
||||
|
||||
bool
|
||||
Gecko_HasAttr(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName)
|
||||
{
|
||||
auto match = [](const nsAttrValue* aValue) { return true; };
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_AttrEquals(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName,
|
||||
nsIAtom* aStr_, bool aIgnoreCase)
|
||||
{
|
||||
FakeRef<nsIAtom> aStr(aStr_);
|
||||
auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
|
||||
return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
|
||||
};
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_AttrDashEquals(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName,
|
||||
nsIAtom* aStr_)
|
||||
{
|
||||
FakeRef<nsIAtom> aStr(aStr_);
|
||||
auto match = [aStr](const nsAttrValue* aValue) {
|
||||
nsAutoString str;
|
||||
aValue->ToString(str);
|
||||
const nsDefaultStringComparator c;
|
||||
return nsStyleUtil::DashMatchCompare(str, nsDependentAtomString(aStr), c);
|
||||
};
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_AttrIncludes(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName,
|
||||
nsIAtom* aStr_)
|
||||
{
|
||||
FakeRef<nsIAtom> aStr(aStr_);
|
||||
auto match = [aStr](const nsAttrValue* aValue) {
|
||||
nsAutoString str;
|
||||
aValue->ToString(str);
|
||||
const nsDefaultStringComparator c;
|
||||
return nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr), c);
|
||||
};
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_AttrHasSubstring(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName,
|
||||
nsIAtom* aStr_)
|
||||
{
|
||||
FakeRef<nsIAtom> aStr(aStr_);
|
||||
auto match = [aStr](const nsAttrValue* aValue) {
|
||||
nsAutoString str;
|
||||
aValue->ToString(str);
|
||||
return FindInReadable(str, nsDependentAtomString(aStr));
|
||||
};
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_AttrHasPrefix(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName,
|
||||
nsIAtom* aStr_)
|
||||
{
|
||||
FakeRef<nsIAtom> aStr(aStr_);
|
||||
auto match = [aStr](const nsAttrValue* aValue) {
|
||||
nsAutoString str;
|
||||
aValue->ToString(str);
|
||||
return StringBeginsWith(str, nsDependentAtomString(aStr));
|
||||
};
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_AttrHasSuffix(RawGeckoElement* aElement, nsIAtom* aNS, nsIAtom* aName,
|
||||
nsIAtom* aStr_)
|
||||
{
|
||||
FakeRef<nsIAtom> aStr(aStr_);
|
||||
auto match = [aStr](const nsAttrValue* aValue) {
|
||||
nsAutoString str;
|
||||
aValue->ToString(str);
|
||||
return StringEndsWith(str, nsDependentAtomString(aStr));
|
||||
};
|
||||
return DoMatch(aElement, aNS, aName, match);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Gecko_ClassOrClassList(RawGeckoElement* aElement,
|
||||
nsIAtom** aClass, nsIAtom*** aClassList)
|
||||
|
@ -101,6 +101,16 @@ nsIAtom* Gecko_LocalName(RawGeckoElement* element);
|
||||
nsIAtom* Gecko_Namespace(RawGeckoElement* element);
|
||||
nsIAtom* Gecko_GetElementId(RawGeckoElement* element);
|
||||
|
||||
// Attributes.
|
||||
bool Gecko_HasAttr(RawGeckoElement* element, nsIAtom* ns, nsIAtom* name);
|
||||
bool Gecko_AttrEquals(RawGeckoElement* element, nsIAtom* ns, nsIAtom* name, nsIAtom* str, bool ignoreCase);
|
||||
bool Gecko_AttrDashEquals(RawGeckoElement* element, nsIAtom* ns, nsIAtom* name, nsIAtom* str);
|
||||
bool Gecko_AttrIncludes(RawGeckoElement* element, nsIAtom* ns, nsIAtom* name, nsIAtom* str);
|
||||
bool Gecko_AttrHasSubstring(RawGeckoElement* element, nsIAtom* ns, nsIAtom* name, nsIAtom* str);
|
||||
bool Gecko_AttrHasPrefix(RawGeckoElement* element, nsIAtom* ns, nsIAtom* name, nsIAtom* str);
|
||||
bool Gecko_AttrHasSuffix(RawGeckoElement* element, nsIAtom* ns, nsIAtom* name, nsIAtom* str);
|
||||
|
||||
|
||||
// Gets the class or class list (if any) of the Element.
|
||||
//
|
||||
// The calling convention here is rather hairy, and is optimized for getting
|
||||
|
@ -1376,35 +1376,6 @@ enum class SelectorMatchesFlags : uint8_t {
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SelectorMatchesFlags)
|
||||
|
||||
static bool ValueIncludes(const nsSubstring& aValueList,
|
||||
const nsSubstring& aValue,
|
||||
const nsStringComparator& aComparator)
|
||||
{
|
||||
const char16_t *p = aValueList.BeginReading(),
|
||||
*p_end = aValueList.EndReading();
|
||||
|
||||
while (p < p_end) {
|
||||
// skip leading space
|
||||
while (p != p_end && nsContentUtils::IsHTMLWhitespace(*p))
|
||||
++p;
|
||||
|
||||
const char16_t *val_start = p;
|
||||
|
||||
// look for space or end
|
||||
while (p != p_end && !nsContentUtils::IsHTMLWhitespace(*p))
|
||||
++p;
|
||||
|
||||
const char16_t *val_end = p;
|
||||
|
||||
if (val_start < val_end &&
|
||||
aValue.Equals(Substring(val_start, val_end), aComparator))
|
||||
return true;
|
||||
|
||||
++p; // we know the next character is not whitespace
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return whether the selector matches conditions for the :active and
|
||||
// :hover quirk.
|
||||
static inline bool ActiveHoverQuirkMatches(nsCSSSelector* aSelector,
|
||||
@ -1472,7 +1443,7 @@ static bool AttrMatchesValue(const nsAttrSelector* aAttrSelector,
|
||||
case NS_ATTR_FUNC_EQUALS:
|
||||
return aValue.Equals(aAttrSelector->mValue, comparator);
|
||||
case NS_ATTR_FUNC_INCLUDES:
|
||||
return ValueIncludes(aValue, aAttrSelector->mValue, comparator);
|
||||
return nsStyleUtil::ValueIncludes(aValue, aAttrSelector->mValue, comparator);
|
||||
case NS_ATTR_FUNC_DASHMATCH:
|
||||
return nsStyleUtil::DashMatchCompare(aValue, aAttrSelector->mValue, comparator);
|
||||
case NS_ATTR_FUNC_ENDSMATCH:
|
||||
|
@ -2775,17 +2775,12 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable
|
||||
|
||||
nsChangeHint CalcDifference(const nsStyleTable& aNewData) const;
|
||||
static nsChangeHint MaxDifference() {
|
||||
return nsChangeHint_ReconstructFrame |
|
||||
nsChangeHint_NeedReflow |
|
||||
nsChangeHint_ReflowChangesSizeOrPosition |
|
||||
nsChangeHint_ClearAncestorIntrinsics;
|
||||
return nsChangeHint_ReconstructFrame;
|
||||
}
|
||||
static nsChangeHint DifferenceAlwaysHandledForDescendants() {
|
||||
// CalcDifference never returns the reflow hints that are sometimes
|
||||
// handled for descendants as hints not handled for descendants.
|
||||
return nsChangeHint_NeedReflow |
|
||||
nsChangeHint_ReflowChangesSizeOrPosition |
|
||||
nsChangeHint_ClearAncestorIntrinsics;
|
||||
return nsChangeHint(0);
|
||||
}
|
||||
|
||||
uint8_t mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
|
||||
@ -3096,8 +3091,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
|
||||
return nsChangeHint_ReconstructFrame |
|
||||
nsChangeHint_NeedReflow |
|
||||
nsChangeHint_NeedDirtyReflow |
|
||||
nsChangeHint_ReflowChangesSizeOrPosition |
|
||||
nsChangeHint_ClearAncestorIntrinsics |
|
||||
NS_STYLE_HINT_VISUAL |
|
||||
nsChangeHint_UpdateCursor |
|
||||
nsChangeHint_NeutralChange;
|
||||
@ -3105,9 +3098,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
|
||||
static nsChangeHint DifferenceAlwaysHandledForDescendants() {
|
||||
// CalcDifference never returns the reflow hints that are sometimes
|
||||
// handled for descendants as hints not handled for descendants.
|
||||
return nsChangeHint_NeedReflow |
|
||||
nsChangeHint_ReflowChangesSizeOrPosition |
|
||||
nsChangeHint_ClearAncestorIntrinsics;
|
||||
return nsChangeHint_NeedReflow;
|
||||
}
|
||||
|
||||
uint8_t mUserInput; // [inherited]
|
||||
|
@ -50,6 +50,36 @@ bool nsStyleUtil::DashMatchCompare(const nsAString& aAttributeValue,
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
nsStyleUtil::ValueIncludes(const nsSubstring& aValueList,
|
||||
const nsSubstring& aValue,
|
||||
const nsStringComparator& aComparator)
|
||||
{
|
||||
const char16_t *p = aValueList.BeginReading(),
|
||||
*p_end = aValueList.EndReading();
|
||||
|
||||
while (p < p_end) {
|
||||
// skip leading space
|
||||
while (p != p_end && nsContentUtils::IsHTMLWhitespace(*p))
|
||||
++p;
|
||||
|
||||
const char16_t *val_start = p;
|
||||
|
||||
// look for space or end
|
||||
while (p != p_end && !nsContentUtils::IsHTMLWhitespace(*p))
|
||||
++p;
|
||||
|
||||
const char16_t *val_end = p;
|
||||
|
||||
if (val_start < val_end &&
|
||||
aValue.Equals(Substring(val_start, val_end), aComparator))
|
||||
return true;
|
||||
|
||||
++p; // we know the next character is not whitespace
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void nsStyleUtil::AppendEscapedCSSString(const nsAString& aString,
|
||||
nsAString& aReturn,
|
||||
char16_t quoteChar)
|
||||
|
@ -31,6 +31,10 @@ public:
|
||||
const nsAString& aSelectorValue,
|
||||
const nsStringComparator& aComparator);
|
||||
|
||||
static bool ValueIncludes(const nsSubstring& aValueList,
|
||||
const nsSubstring& aValue,
|
||||
const nsStringComparator& aComparator);
|
||||
|
||||
// Append a quoted (with 'quoteChar') and escaped version of aString
|
||||
// to aResult. 'quoteChar' must be ' or ".
|
||||
static void AppendEscapedCSSString(const nsAString& aString,
|
||||
|
@ -1447,6 +1447,10 @@ HttpChannelChild::ConnectParent(uint32_t registrarId)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (tabChild && tabChild->IsDestroyed()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// The socket transport in the chrome process now holds a logical ref to us
|
||||
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
|
||||
AddIPDLReference();
|
||||
@ -1965,15 +1969,21 @@ HttpChannelChild::ContinueAsyncOpen()
|
||||
mChannelId.ToProvidedString(chid);
|
||||
openArgs.channelId().AssignASCII(chid);
|
||||
|
||||
if (tabChild && tabChild->IsDestroyed()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// The socket transport in the chrome process now holds a logical ref to us
|
||||
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
|
||||
AddIPDLReference();
|
||||
|
||||
PBrowserOrId browser = static_cast<ContentChild*>(gNeckoChild->Manager())
|
||||
->GetBrowserOrId(tabChild);
|
||||
gNeckoChild->SendPHttpChannelConstructor(this, browser,
|
||||
IPC::SerializedLoadContext(this),
|
||||
openArgs);
|
||||
if (!gNeckoChild->SendPHttpChannelConstructor(this, browser,
|
||||
IPC::SerializedLoadContext(this),
|
||||
openArgs)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (optionalFDs.type() ==
|
||||
OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
|
||||
|
@ -1,7 +1,9 @@
|
||||
---
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: "0 seconds"
|
||||
deadline:
|
||||
relative-datestamp: "24 hours"
|
||||
metadata:
|
||||
name: 'Docker Image Build: {{image_name}}'
|
||||
description: 'Build the docker image {{image_name}} for use by dependent tasks'
|
||||
@ -43,7 +45,8 @@ task:
|
||||
'{{artifact_path}}':
|
||||
type: 'file'
|
||||
path: '/artifacts/image.tar'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
extra:
|
||||
treeherderEnv:
|
||||
- staging
|
||||
|
@ -28,6 +28,8 @@ flags:
|
||||
- linux64-valgrind
|
||||
- macosx64
|
||||
- macosx64-st-an
|
||||
- win32
|
||||
- win64
|
||||
|
||||
tests:
|
||||
- cppunit
|
||||
|
@ -215,6 +215,22 @@ builds:
|
||||
file_patterns:
|
||||
- js/public/**
|
||||
- js/src/**
|
||||
win32:
|
||||
platforms:
|
||||
- win32
|
||||
types:
|
||||
opt:
|
||||
task: tasks/builds/opt_win32.yml
|
||||
debug:
|
||||
task: tasks/builds/dbg_win32.yml
|
||||
win64:
|
||||
platforms:
|
||||
- win64
|
||||
types:
|
||||
opt:
|
||||
task: tasks/builds/opt_win64.yml
|
||||
debug:
|
||||
task: tasks/builds/dbg_win64.yml
|
||||
|
||||
tests:
|
||||
cppunit:
|
||||
|
@ -4,8 +4,10 @@
|
||||
taskId: {{build_slugid}}
|
||||
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: "0 seconds"
|
||||
deadline:
|
||||
relative-datestamp: "24 hours"
|
||||
metadata:
|
||||
source: '{{source}}'
|
||||
owner: mozilla-taskcluster-maintenance@mozilla.com
|
||||
|
@ -50,7 +50,8 @@ task:
|
||||
'public/android/checkstyle/checkstyle.xml':
|
||||
type: file
|
||||
path: '/home/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/reports/checkstyle/checkstyle.xml'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
|
||||
extra:
|
||||
treeherderEnv:
|
||||
|
@ -50,15 +50,18 @@ task:
|
||||
'public/android/lint/lint-results-automationDebug.html':
|
||||
type: file
|
||||
path: '/home/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/outputs/lint-results-automationDebug.html'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
'public/android/lint/lint-results-automationDebug.xml':
|
||||
type: file
|
||||
path: '/home/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/outputs/lint-results-automationDebug.xml'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
'public/android/lint/lint-results-automationDebug_files':
|
||||
type: directory
|
||||
path: '/home/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/outputs/lint-results-automationDebug_files'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
|
||||
extra:
|
||||
treeherderEnv:
|
||||
|
@ -50,7 +50,8 @@ task:
|
||||
'public/android/unittest':
|
||||
type: directory
|
||||
path: '/home/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/reports/tests'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
|
||||
extra:
|
||||
treeherderEnv:
|
||||
|
@ -34,7 +34,8 @@ task:
|
||||
'public/clang.tar.xz':
|
||||
type: file
|
||||
path: '/home/worker/workspace/artifacts/clang.tar.xz'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
|
||||
extra:
|
||||
treeherderEnv:
|
||||
|
@ -27,7 +27,8 @@ task:
|
||||
'public/gcc.tar.xz':
|
||||
type: file
|
||||
path: '/home/worker/workspace/artifacts/gcc.tar.xz'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: "1 year"
|
||||
|
||||
extra:
|
||||
treeherderEnv:
|
||||
|
@ -23,4 +23,5 @@ task:
|
||||
'public/build':
|
||||
type: directory
|
||||
path: '/home/worker/artifacts/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
|
@ -20,8 +20,10 @@ task:
|
||||
'public/logs/':
|
||||
type: directory
|
||||
path: '/home/worker/workspace/build/upload/logs/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
'public/test_info/':
|
||||
type: directory
|
||||
path: '/home/worker/workspace/build/blobber_upload_dir/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
|
@ -6,8 +6,10 @@
|
||||
taskId: {{build_slugid}}
|
||||
docker-image: desktop-build
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
source: '{{source}}'
|
||||
owner: mozilla-taskcluster-maintenance@mozilla.com
|
||||
@ -40,7 +42,8 @@ task:
|
||||
'public/logs/':
|
||||
type: directory
|
||||
path: '/home/worker/workspace/build/upload/logs/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
command:
|
||||
- bash
|
||||
- /home/worker/bin/build.sh
|
||||
|
@ -4,8 +4,10 @@
|
||||
taskId: '{{image_slugid}}'
|
||||
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
name: 'Docker Artifact Image Builder'
|
||||
description: 'Builder for docker images as artifacts'
|
||||
@ -40,7 +42,8 @@ task:
|
||||
'{{artifact_path}}':
|
||||
type: 'file'
|
||||
path: '/artifacts/image.tar'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
extra:
|
||||
treeherderEnv:
|
||||
- staging
|
||||
|
@ -4,8 +4,10 @@
|
||||
taskId: {{build_slugid}}
|
||||
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
source: '{{source}}'
|
||||
owner: mozilla-taskcluster-maintenance@mozilla.com
|
||||
@ -34,7 +36,8 @@ task:
|
||||
'public/build':
|
||||
type: directory
|
||||
path: '/home/worker/workspace/build/upload/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
|
||||
|
||||
env:
|
||||
|
@ -4,8 +4,10 @@
|
||||
taskId: {{build_slugid}}
|
||||
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
source: http://todo.com/soon
|
||||
owner: mozilla-taskcluster-maintenance@mozilla.com
|
||||
|
@ -4,8 +4,10 @@
|
||||
taskId: {{build_slugid}}
|
||||
docker-image: phone-builder
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
source: '{{source}}'
|
||||
owner: mozilla-taskcluster-maintenance@mozilla.com
|
||||
@ -44,11 +46,13 @@ task:
|
||||
'private/build':
|
||||
type: directory
|
||||
path: '/home/worker/artifacts/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
'public/build':
|
||||
type: directory
|
||||
path: '/home/worker/artifacts-public/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
|
||||
|
||||
env:
|
||||
|
@ -3,8 +3,10 @@
|
||||
taskId: {{build_slugid}}
|
||||
docker-image: builder
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
source: '{{source}}'
|
||||
owner: apoirot@mozilla.com
|
||||
@ -45,7 +47,8 @@ task:
|
||||
'public/build':
|
||||
type: directory
|
||||
path: '/home/worker/artifacts/'
|
||||
expires: '{{#from_now}}1 year{{/from_now}}'
|
||||
expires:
|
||||
relative-datestamp: '1 year'
|
||||
|
||||
env:
|
||||
GECKO_BASE_REPOSITORY: '{{base_repository}}'
|
||||
|
@ -3,8 +3,10 @@
|
||||
taskId: {{taskId}}
|
||||
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
source: '{{source}}'
|
||||
owner: amiyaguchi@mozilla.com
|
||||
|
@ -1,7 +1,9 @@
|
||||
# This task is the base for most tests in gecko.
|
||||
task:
|
||||
created: '{{now}}'
|
||||
deadline: '{{#from_now}}24 hours{{/from_now}}'
|
||||
created:
|
||||
relative-datestamp: '0 seconds'
|
||||
deadline:
|
||||
relative-datestamp: '24 hours'
|
||||
metadata:
|
||||
source: '{{source}}'
|
||||
owner: mozilla-taskcluster-maintenance@mozilla.com
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user