Merge m-c to fx-team, a=merge

This commit is contained in:
Wes Kocher 2016-07-07 17:36:54 -07:00
commit aac6bd4fa7
118 changed files with 1932 additions and 1013 deletions

View File

@ -4351,6 +4351,7 @@
case "Browser:WindowCreated": {
let tab = this.getTabForBrowser(browser);
if (tab && data.userContextId) {
ContextualIdentityService.telemetry(data.userContextId);
tab.setUserContextId(data.userContextId);
}

View File

@ -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);
},
}

View File

@ -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

View File

@ -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.
*

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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:

View File

@ -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

View File

@ -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,

View File

@ -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:

View File

@ -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.
}

View File

@ -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,

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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))) {

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -132,7 +132,6 @@ private:
Atomic<uint32_t> mInputIncoming;
Atomic<bool> mIsShutDown;
const bool mUseSoftwareImages;
const bool mIs106;
// Protects mReorderQueue.
Monitor mMonitor;

View File

@ -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(

View File

@ -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>

View File

@ -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;

View File

@ -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));
}
}

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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);
}

View File

@ -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++;
}
}

View File

@ -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)

View File

@ -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(); }
};

View File

@ -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()) {

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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());

View File

@ -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));

View File

@ -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;

View File

@ -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));

View File

@ -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++) {

View File

@ -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());

View File

@ -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()
{

View File

@ -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());
}

View File

@ -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)

View File

@ -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:

View File

@ -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()) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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
{

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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");

View File

@ -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;
}

View File

@ -1083,7 +1083,7 @@ SetLocationForGlobal(JSObject* global, nsIURI* locationURI)
NS_IMETHODIMP
nsXPConnect::NotifyDidPaint()
{
JS::NotifyDidPaint(GetRuntime()->Runtime());
JS::NotifyDidPaint(GetRuntime()->Context());
return NS_OK;
}

View File

@ -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.

View File

@ -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());
}
}

View File

@ -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

View File

@ -626,6 +626,7 @@ protected:
AsyncScrollEventType mAsyncScrollEvent;
bool HasPluginFrames();
bool HasPerspective() const;
uint8_t GetScrolledFrameDir() const;
static void EnsureFrameVisPrefsCached();
static bool sFrameVisPrefsCached;

View File

@ -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>

View File

@ -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>

View File

@ -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>

View 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>

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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:

View File

@ -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]

View File

@ -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)

View File

@ -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,

View File

@ -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) {

View File

@ -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

View File

@ -28,6 +28,8 @@ flags:
- linux64-valgrind
- macosx64
- macosx64-st-an
- win32
- win64
tests:
- cppunit

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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'

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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}}'

View File

@ -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

View File

@ -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