import changes from `dev' branch of rmottola/Arctic-Fox:

- missing crashreporter section (4831c9622)
- Bug 866681, part 1 - Track if any slice of CC was manually triggered. r=smaug (358239be3)
- Bug 866681, part 2 - Make ContentUnbinder use DeferredFinalize. r=smaug (3155b68fa)
- Bug 1177627 - Back out most of 7fcf6bf43eda for causing Gaia unit test crashes. r=smaug (6ddb7866c)
-  Bug 1158257 - Gecko should always provide SpiderMonkey with a debuggerMallocSizeOf; r=mccr8 (f18a9c4ec)
- add (unused) crashreporter (9f35b04ee)
- Bug 1175513 - Make some private nsXPCWrappedJSClass const or static; r=bholley (39e560872)
- Bug 1175513 - Factor out nsXPCWrappedJSClass::CleanupOutparams; r=bholley (93f602ab6)
- Bug 1175513 - Improve code style in nsXPCWrappedJSClass::CleanupOutparams; r=bholley (cd874ea37)
- Bug 1178969 - nsXPConnect doesn't need to implement nsSupportsWeakReference. r=bholley (e76ebddc9)
- Bug 1182409 - Add 'allowWaivers' sandbox option. r=gabor (71befc1c9)
- Bug 1184400, part 1 - Make XPCJSRuntime::SuspectWrappedNative into a method on XPCWrappedNative. r=bholley (4d102ee6a)
- Bug 1184400, part 2 - XPCWrappedNative::Suspect() should suspect the JS reflector object even if it doesn't own it. r=bholley (c8339179c)
- Bug 1184400, part 3 - Use HasExternalReference in XPCWrappedNative::Traverse. r=bholley (3020bd602)
- Bug 1186213 - Add an API to deep-freeze the result of Cu.cloneInto. r=gkrizsanits (3b1b03b07)
- Bug 1185144 - nsConsoleService::LogMessageWithMode() should release the retired message on the main thread. r=froydnj (e615f5eb2)
- Bug 1171716 - Part 1: Add NS_ReleaseOnMainThread. r=froydnj (dd13528db)
- Bug 1171716 - Part 3: Use NS_ReleaseOnMainThread in WebSocketChannel dtor. r=froydnj (0818574a6)
- Bug 1171716 - Part 4: Use NS_ReleaseOnMainThread in JarChannel dtor. r=froydnj (06c85f670)
- Bug 1171716 - Part 5: Use NS_ReleaseOnMainThread in HttpBaseChannel dtor. r=froydnj (e599c1b8e)
- Bug 1185527 - Split out a refcountless base class for nsScriptError. r=gabor (325087790)
- Bug 1157908 - Give Gecko thread Looper low priority; r=snorp (713dd5bb1)
- Bug 968923 - part 5a - add use counters for SVGSVGElement and CSS properties for testing purposes; r=bz (9ed578c11)
- Bug 968923 - part 3d - record use counter information from the CSS parser; r=dbaron (ea188ea15)
- Bug 968923 - fix bogus assert in nsSVGElement.cpp; r=heycam (moz hg rev a0744d2060df)
This commit is contained in:
2021-07-18 22:25:24 +08:00
parent 619c191e44
commit 9d8e58858d
40 changed files with 533 additions and 251 deletions
-3
View File
@@ -1273,13 +1273,10 @@ public:
nsAutoScriptBlocker scriptBlocker;
uint32_t len = mSubtreeRoots.Length();
if (len) {
PRTime start = PR_Now();
for (uint32_t i = 0; i < len; ++i) {
UnbindSubtree(mSubtreeRoots[i]);
}
mSubtreeRoots.Clear();
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_CONTENT_UNBIND,
uint32_t(PR_Now() - start) / PR_USEC_PER_MSEC);
}
nsCycleCollector_dispatchDeferredDeletion();
if (this == sContentUnbinder) {
+14 -3
View File
@@ -18,12 +18,18 @@
//
// method <IDL interface name>.<IDL operation name>
// attribute <IDL interface name>.<IDL attribute name>
// property <CSS property name>
// property <CSS property method name>
//
// The |CSS property method name| should be identical to the |method|
// argument to CSS_PROP and related macros. The method name is
// identical to the name of the property, except that all hyphens are
// removed and CamelCase naming is used. See nsCSSPropList.h for
// further details.
//
// To actually cause use counters to be incremented, DOM methods
// and attributes must have a [UseCounter] extended attribute in
// the Web IDL file, and CSS properties must be declared with
// the CSS_PROPERTY_HAS_USE_COUNTER flag in nsCSSPropList.h.
// the Web IDL file. CSS properties require no special treatment
// beyond being listed below.
//
// You might reasonably ask why we have this file and we require
// annotating things with [UseCounter] in the relevant WebIDL file as
@@ -31,3 +37,8 @@
// dependencies were correct would have been rather difficult, and
// annotating the WebIDL files does nothing for identifying CSS
// property usage, which we would also like to track.
method SVGSVGElement.getElementById
attribute SVGSVGElement.currentScale
property Fill
property FillOpacity
+5 -4
View File
@@ -45,7 +45,7 @@ def generate_list(f, counters):
print('USE_COUNTER_DOM_ATTRIBUTE(%s, %s)' % (counter['interface_name'], counter['attribute_name']), file=f)
elif counter['type'] == 'property':
prop = counter['property_name']
print('USE_COUNTER_CSS_PROPERTY(%s, %s)' % (prop, prop.replace('-', '_')), file=f)
print('USE_COUNTER_CSS_PROPERTY(%s, %s)' % (prop, prop), file=f)
print_optional_macro_undeclare('USE_COUNTER_DOM_METHOD')
print_optional_macro_undeclare('USE_COUNTER_DOM_ATTRIBUTE')
@@ -55,19 +55,20 @@ def generate_property_map(f, counters):
print(AUTOGENERATED_WARNING_COMMENT, file=f)
print('''
enum {
// XXX is this the right define?
#define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) privatename_
#define CSS_PROP_LIST_INCLUDE_LOGICAL
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \\
kwtable_, stylestruct_, stylestructoffset_, animtype_) \\
USE_COUNTER_FOR_CSS_PROPERTY_##id_ = eUseCounter_UNKNOWN,
USE_COUNTER_FOR_CSS_PROPERTY_##method_ = eUseCounter_UNKNOWN,
#include "nsCSSPropList.h"
#undef CSS_PROP
#undef CSS_PROP_LIST_INCLUDE_LOGICAL
#undef CSS_PROP_PUBLIC_OR_PRIVATE
};
''', file=f)
for counter in counters:
if counter['type'] == 'property':
prop = counter['property_name'].replace('-', '_')
prop = counter['property_name']
print('#define USE_COUNTER_FOR_CSS_PROPERTY_%s eUseCounter_property_%s' % (prop, prop), file=f)
def use_counter_list(output_header, conf_filename):
+1 -1
View File
@@ -41,7 +41,7 @@ def read_conf(conf_filename):
'interface_name': interface_name,
'attribute_name': attribute_name }
continue
m = re.match(r'property ([a-z0-9-]+)$', line)
m = re.match(r'property ([A-Za-z0-9]+)$', line)
if m:
property_name = m.group(1)
yield { 'type': 'property',
+19 -1
View File
@@ -1187,9 +1187,27 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
nsCSSProps::eEnabledForAllContent);
if (propertyID != eCSSProperty_UNKNOWN) {
bool changed; // outparam for ParseProperty. (ignored)
bool changed = false; // outparam for ParseProperty.
mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
mElement->NodePrincipal(), mDecl, &changed, false, true);
if (changed) {
// The normal reporting of use counters by the nsCSSParser won't happen
// since it doesn't have a sheet.
if (nsCSSProps::IsShorthand(propertyID)) {
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, propertyID,
nsCSSProps::eEnabledForAllContent) {
UseCounter useCounter = nsCSSProps::UseCounterFor(*subprop);
if (useCounter != eUseCounter_UNKNOWN) {
mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
}
}
} else {
UseCounter useCounter = nsCSSProps::UseCounterFor(propertyID);
if (useCounter != eUseCounter_UNKNOWN) {
mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
}
}
}
return;
}
MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,
+2
View File
@@ -33,6 +33,7 @@ interface SVGSVGElement : SVGGraphicsElement {
readonly attribute float screenPixelToMillimeterY;
readonly attribute boolean useCurrentView;
// readonly attribute SVGViewSpec currentView;
[UseCounter]
attribute float currentScale;
readonly attribute SVGPoint currentTranslate;
@@ -70,6 +71,7 @@ interface SVGSVGElement : SVGGraphicsElement {
SVGTransform createSVGTransform();
[NewObject]
SVGTransform createSVGTransformFromMatrix(SVGMatrix matrix);
[UseCounter]
Element? getElementById(DOMString elementId);
};
-13
View File
@@ -23,10 +23,6 @@
#include "nsXULAppAPI.h"
#include "prthread.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
@@ -111,15 +107,6 @@ MessagePump::Run(MessagePump::Delegate* aDelegate)
// equal priority, we sensitively rely on processing exactly one
// Task per DoWorkRunnable XPCOM event.
#ifdef MOZ_WIDGET_ANDROID
// This processes messages in the Android Looper. Note that we only
// get here if the normal Gecko event loop has been awoken above.
// Bug 750713
if (MOZ_LIKELY(AndroidBridge::HasEnv())) {
did_work |= mozilla::widget::GeckoAppShell::PumpMessageLoop();
}
#endif
did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
if (did_work && delayed_work_time_.is_null()
+11 -1
View File
@@ -271,7 +271,17 @@ StackScopedClone(JSContext* cx, StackScopedCloneOptions& options,
}
// Now recreate the clones in the target compartment.
return buffer.read(cx, val, &gStackScopedCloneCallbacks, &data);
if (!buffer.read(cx, val, &gStackScopedCloneCallbacks, &data))
return false;
// Deep-freeze if requested.
if (options.deepFreeze && val.isObject()) {
RootedObject obj(cx, &val.toObject());
if (!JS_DeepFreezeObject(cx, obj))
return false;
}
return true;
}
// Note - This function mirrors the logic of CheckPassToChrome in
+5 -3
View File
@@ -1029,8 +1029,9 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
if (!sandbox)
return NS_ERROR_FAILURE;
CompartmentPrivate::Get(sandbox)->writeToGlobalPrototype =
options.writeToGlobalPrototype;
CompartmentPrivate* priv = CompartmentPrivate::Get(sandbox);
priv->allowWaivers = options.allowWaivers;
priv->writeToGlobalPrototype = options.writeToGlobalPrototype;
// Set up the wantXrays flag, which indicates whether xrays are desired even
// for same-origin access.
@@ -1041,7 +1042,7 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
// Arguably we should just flip the default for chrome and still honor the
// flag, but such a change would break code in subtle ways for minimal
// benefit. So we just switch it off here.
CompartmentPrivate::Get(sandbox)->wantXrays =
priv->wantXrays =
AccessCheck::isChrome(sandbox) ? false : options.wantXrays;
{
@@ -1480,6 +1481,7 @@ SandboxOptions::Parse()
{
bool ok = ParseObject("sandboxPrototype", &proto) &&
ParseBoolean("wantXrays", &wantXrays) &&
ParseBoolean("allowWaivers", &allowWaivers) &&
ParseBoolean("wantComponents", &wantComponents) &&
ParseBoolean("wantExportHelpers", &wantExportHelpers) &&
ParseString("sandboxName", sandboxName) &&
-18
View File
@@ -563,24 +563,6 @@ void XPCJSRuntime::TraceAdditionalNativeGrayRoots(JSTracer* trc)
static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc);
}
// static
void
XPCJSRuntime::SuspectWrappedNative(XPCWrappedNative* wrapper,
nsCycleCollectionNoteRootCallback& cb)
{
if (!wrapper->IsValid() || wrapper->IsWrapperExpired())
return;
MOZ_ASSERT(NS_IsMainThread(),
"Suspecting wrapped natives from non-main thread");
// Only record objects that might be part of a cycle as roots, unless
// the callback wants all traces (a debug feature).
JSObject* obj = wrapper->GetFlatJSObjectPreserveColor();
if (JS::ObjectIsMarkedGray(obj) || cb.WantAllTraces())
cb.NoteJSRoot(obj);
}
void
XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback& cb)
{
+56 -77
View File
@@ -607,7 +607,7 @@ nsXPCWrappedJSClass::GetArraySizeFromParam(JSContext* cx,
uint16_t methodIndex,
uint8_t paramIndex,
nsXPTCMiniVariant* nativeParams,
uint32_t* result)
uint32_t* result) const
{
uint8_t argnum;
nsresult rv;
@@ -638,7 +638,7 @@ nsXPCWrappedJSClass::GetInterfaceTypeFromParam(JSContext* cx,
uint16_t methodIndex,
const nsXPTType& type,
nsXPTCMiniVariant* nativeParams,
nsID* result)
nsID* result) const
{
uint8_t type_tag = type.TagPart();
@@ -676,7 +676,7 @@ nsXPCWrappedJSClass::GetInterfaceTypeFromParam(JSContext* cx,
return false;
}
void
/* static */ void
nsXPCWrappedJSClass::CleanupPointerArray(const nsXPTType& datum_type,
uint32_t array_count,
void** arrayp)
@@ -696,7 +696,7 @@ nsXPCWrappedJSClass::CleanupPointerArray(const nsXPTType& datum_type,
}
}
void
/* static */ void
nsXPCWrappedJSClass::CleanupPointerTypeObject(const nsXPTType& type,
void** pp)
{
@@ -710,6 +710,56 @@ nsXPCWrappedJSClass::CleanupPointerTypeObject(const nsXPTType& type,
}
}
void
nsXPCWrappedJSClass::CleanupOutparams(JSContext* cx, uint16_t methodIndex,
const nsXPTMethodInfo* info, nsXPTCMiniVariant* nativeParams,
bool inOutOnly, uint8_t n) const
{
// clean up any 'out' params handed in
for (uint8_t i = 0; i < n; i++) {
const nsXPTParamInfo& param = info->params[i];
if (!param.IsOut())
continue;
const nsXPTType& type = param.GetType();
if (!type.deprecated_IsPointer())
continue;
void* p = nativeParams[i].val.p;
if (!p)
continue;
// The inOutOnly flag was introduced when consolidating two very
// similar code paths in CallMethod in bug 1175513. I don't know
// if and why the difference is necessary.
if (!inOutOnly || param.IsIn()) {
if (type.IsArray()) {
void** pp = *static_cast<void***>(p);
if (pp) {
// we need to get the array length and iterate the items
uint32_t array_count;
nsXPTType datum_type;
if (NS_SUCCEEDED(mInfo->GetTypeForParam(methodIndex, &param,
1, &datum_type)) &&
datum_type.deprecated_IsPointer() &&
GetArraySizeFromParam(cx, info, param, methodIndex,
i, nativeParams, &array_count) &&
array_count) {
CleanupPointerArray(datum_type, array_count, pp);
}
// always release the array if it is inout
free(pp);
}
} else {
CleanupPointerTypeObject(type, static_cast<void**>(p));
}
}
*static_cast<void**>(p) = nullptr;
}
}
nsresult
nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
const char * aPropertyName,
@@ -1148,45 +1198,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
pre_call_clean_up:
// clean up any 'out' params handed in
for (i = 0; i < paramCount; i++) {
const nsXPTParamInfo& param = info->params[i];
if (!param.IsOut())
continue;
const nsXPTType& type = param.GetType();
if (!type.deprecated_IsPointer())
continue;
void* p;
if (!(p = nativeParams[i].val.p))
continue;
if (param.IsIn()) {
if (type.IsArray()) {
void** pp;
if (nullptr != (pp = *((void***)p))) {
// we need to get the array length and iterate the items
uint32_t array_count;
nsXPTType datum_type;
if (NS_SUCCEEDED(mInfo->GetTypeForParam(methodIndex, &param,
1, &datum_type)) &&
datum_type.deprecated_IsPointer() &&
GetArraySizeFromParam(cx, info, param, methodIndex,
i, nativeParams, &array_count) &&
array_count) {
CleanupPointerArray(datum_type, array_count, pp);
}
// always release the array if it is inout
free(pp);
}
} else
CleanupPointerTypeObject(type, (void**)p);
}
*((void**)p) = nullptr;
}
CleanupOutparams(cx, methodIndex, info, nativeParams, /* inOutOnly = */ true, paramCount);
// Make sure "this" doesn't get deleted during this call.
nsCOMPtr<nsIXPCWrappedJSClass> kungFuDeathGrip(this);
@@ -1392,40 +1404,7 @@ pre_call_clean_up:
if (i != paramCount) {
// We didn't manage all the result conversions!
// We have to cleanup any junk that *did* get converted.
for (uint8_t k = 0; k < i; k++) {
const nsXPTParamInfo& param = info->params[k];
if (!param.IsOut())
continue;
const nsXPTType& type = param.GetType();
if (!type.deprecated_IsPointer())
continue;
void* p;
if (!(p = nativeParams[k].val.p))
continue;
if (type.IsArray()) {
void** pp;
if (nullptr != (pp = *((void***)p))) {
// we need to get the array length and iterate the items
uint32_t array_count;
nsXPTType datum_type;
if (NS_SUCCEEDED(mInfo->GetTypeForParam(methodIndex, &param,
1, &datum_type)) &&
datum_type.deprecated_IsPointer() &&
GetArraySizeFromParam(cx, info, param, methodIndex,
k, nativeParams, &array_count) &&
array_count) {
CleanupPointerArray(datum_type, array_count, pp);
}
free(pp);
}
} else
CleanupPointerTypeObject(type, (void**)p);
*((void**)p) = nullptr;
}
CleanupOutparams(cx, methodIndex, info, nativeParams, /* inOutOnly = */ false, i);
} else {
// set to whatever the JS code might have set as the result
retval = xpcc->GetPendingResult();
+21 -1
View File
@@ -17,6 +17,7 @@
#include "XrayWrapper.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionNoteRootCallback.h"
#include <stdint.h>
#include "mozilla/DeferredFinalize.h"
@@ -67,7 +68,7 @@ NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Traverse
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(XPCWrappedNative, tmp->mRefCnt.get())
}
if (tmp->mRefCnt.get() > 1) {
if (tmp->HasExternalReference()) {
// If our refcount is > 1, our reference to the flat JS object is
// considered "strong", and we're going to traverse it.
@@ -93,6 +94,25 @@ NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Traverse
return NS_OK;
}
void
XPCWrappedNative::Suspect(nsCycleCollectionNoteRootCallback& cb)
{
if (!IsValid() || IsWrapperExpired())
return;
MOZ_ASSERT(NS_IsMainThread(),
"Suspecting wrapped natives from non-main thread");
// Only record objects that might be part of a cycle as roots, unless
// the callback wants all traces (a debug feature). Do this even if
// the XPCWN doesn't own the JS reflector object in case the reflector
// keeps alive other C++ things. This is safe because if the reflector
// had died the reference from the XPCWN to it would have been cleared.
JSObject* obj = GetFlatJSObjectPreserveColor();
if (JS::ObjectIsMarkedGray(obj) || cb.WantAllTraces())
cb.NoteJSRoot(obj);
}
void
XPCWrappedNative::NoteTearoffs(nsCycleCollectionTraversalCallback& cb)
{
+1 -4
View File
@@ -503,10 +503,7 @@ XPCWrappedNativeScope::SuspectAllWrappers(XPCJSRuntime* rt,
{
for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) {
for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) {
auto entry = static_cast<Native2WrappedNativeMap::Entry*>(i.Get());
XPCWrappedNative* wrapper = entry->value;
if (wrapper->HasExternalReference())
XPCJSRuntime::SuspectWrappedNative(wrapper, cb);
static_cast<Native2WrappedNativeMap::Entry*>(i.Get())->value->Suspect(cb);
}
if (cur->mDOMExpandoSet) {
+4 -6
View File
@@ -33,16 +33,14 @@ UnwrapNW(JSContext* cx, unsigned argc, Value* vp)
}
JS::RootedValue v(cx, args[0]);
if (!v.isObject() || !js::IsWrapper(&v.toObject())) {
if (!v.isObject() || !js::IsCrossCompartmentWrapper(&v.toObject()) ||
!WrapperFactory::AllowWaiver(&v.toObject())) {
args.rval().set(v);
return true;
}
if (AccessCheck::wrapperSubsumes(&v.toObject())) {
bool ok = xpc::WrapperFactory::WaiveXrayAndWrap(cx, &v);
NS_ENSURE_TRUE(ok, false);
}
bool ok = xpc::WrapperFactory::WaiveXrayAndWrap(cx, &v);
NS_ENSURE_TRUE(ok, false);
args.rval().set(v);
return true;
}
+36 -36
View File
@@ -18,9 +18,7 @@
#include "nsILoadContext.h"
#include "nsIDocShell.h"
NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
nsScriptError::nsScriptError()
nsScriptErrorBase::nsScriptErrorBase()
: mMessage(),
mSourceName(),
mLineNumber(0),
@@ -36,10 +34,10 @@ nsScriptError::nsScriptError()
{
}
nsScriptError::~nsScriptError() {}
nsScriptErrorBase::~nsScriptErrorBase() {}
void
nsScriptError::InitializeOnMainThread()
nsScriptErrorBase::InitializeOnMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mInitializedOnMainThread);
@@ -70,7 +68,7 @@ nsScriptError::InitializeOnMainThread()
// nsIConsoleMessage methods
NS_IMETHODIMP
nsScriptError::GetMessageMoz(char16_t** result) {
nsScriptErrorBase::GetMessageMoz(char16_t** result) {
nsresult rv;
nsAutoCString message;
@@ -87,7 +85,7 @@ nsScriptError::GetMessageMoz(char16_t** result) {
NS_IMETHODIMP
nsScriptError::GetLogLevel(uint32_t* aLogLevel)
nsScriptErrorBase::GetLogLevel(uint32_t* aLogLevel)
{
if (mFlags & (uint32_t)nsIScriptError::infoFlag) {
*aLogLevel = nsIConsoleMessage::info;
@@ -101,66 +99,66 @@ nsScriptError::GetLogLevel(uint32_t* aLogLevel)
// nsIScriptError methods
NS_IMETHODIMP
nsScriptError::GetErrorMessage(nsAString& aResult) {
nsScriptErrorBase::GetErrorMessage(nsAString& aResult) {
aResult.Assign(mMessage);
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetSourceName(nsAString& aResult) {
nsScriptErrorBase::GetSourceName(nsAString& aResult) {
aResult.Assign(mSourceName);
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetSourceLine(nsAString& aResult) {
nsScriptErrorBase::GetSourceLine(nsAString& aResult) {
aResult.Assign(mSourceLine);
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetLineNumber(uint32_t* result) {
nsScriptErrorBase::GetLineNumber(uint32_t* result) {
*result = mLineNumber;
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetColumnNumber(uint32_t* result) {
nsScriptErrorBase::GetColumnNumber(uint32_t* result) {
*result = mColumnNumber;
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetFlags(uint32_t* result) {
nsScriptErrorBase::GetFlags(uint32_t* result) {
*result = mFlags;
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetCategory(char** result) {
nsScriptErrorBase::GetCategory(char** result) {
*result = ToNewCString(mCategory);
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetStack(JS::MutableHandleValue aStack) {
nsScriptErrorBase::GetStack(JS::MutableHandleValue aStack) {
aStack.setUndefined();
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::SetStack(JS::HandleValue aStack) {
nsScriptErrorBase::SetStack(JS::HandleValue aStack) {
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::Init(const nsAString& message,
const nsAString& sourceName,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const char* category)
nsScriptErrorBase::Init(const nsAString& message,
const nsAString& sourceName,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const char* category)
{
return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
columnNumber, flags,
@@ -170,14 +168,14 @@ nsScriptError::Init(const nsAString& message,
}
NS_IMETHODIMP
nsScriptError::InitWithWindowID(const nsAString& message,
const nsAString& sourceName,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const nsACString& category,
uint64_t aInnerWindowID)
nsScriptErrorBase::InitWithWindowID(const nsAString& message,
const nsAString& sourceName,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const nsACString& category,
uint64_t aInnerWindowID)
{
mMessage.Assign(message);
mSourceName.Assign(sourceName);
@@ -197,7 +195,7 @@ nsScriptError::InitWithWindowID(const nsAString& message,
}
NS_IMETHODIMP
nsScriptError::ToString(nsACString& /*UTF8*/ aResult)
nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
{
static const char format0[] =
"[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
@@ -258,7 +256,7 @@ nsScriptError::ToString(nsACString& /*UTF8*/ aResult)
}
NS_IMETHODIMP
nsScriptError::GetOuterWindowID(uint64_t* aOuterWindowID)
nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID)
{
NS_WARN_IF_FALSE(NS_IsMainThread() || mInitializedOnMainThread,
"This can't be safely determined off the main thread, "
@@ -273,21 +271,21 @@ nsScriptError::GetOuterWindowID(uint64_t* aOuterWindowID)
}
NS_IMETHODIMP
nsScriptError::GetInnerWindowID(uint64_t* aInnerWindowID)
nsScriptErrorBase::GetInnerWindowID(uint64_t* aInnerWindowID)
{
*aInnerWindowID = mInnerWindowID;
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetTimeStamp(int64_t* aTimeStamp)
nsScriptErrorBase::GetTimeStamp(int64_t* aTimeStamp)
{
*aTimeStamp = mTimeStamp;
return NS_OK;
}
NS_IMETHODIMP
nsScriptError::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow)
nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow)
{
NS_WARN_IF_FALSE(NS_IsMainThread() || mInitializedOnMainThread,
"This can't be safely determined off the main thread, "
@@ -300,3 +298,5 @@ nsScriptError::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow)
*aIsFromPrivateWindow = mIsFromPrivateWindow;
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
+3 -3
View File
@@ -6,7 +6,7 @@
/*
* nsScriptErrorWithStack implementation.
* a main-thread-only, cycle-collected subclass of nsScriptError
* a main-thread-only, cycle-collected subclass of nsScriptErrorBase
* that can store a SavedFrame stack trace object.
*/
@@ -40,9 +40,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptErrorWithStack)
NS_INTERFACE_MAP_END
nsScriptErrorWithStack::nsScriptErrorWithStack(JS::HandleObject aStack)
: nsScriptError(),
mStack(aStack)
: mStack(aStack)
{
MOZ_ASSERT(NS_IsMainThread(), "You can't use this class on workers.");
mozilla::HoldJSObjects(this);
}
-1
View File
@@ -39,7 +39,6 @@ using namespace JS;
NS_IMPL_ISUPPORTS(nsXPConnect,
nsIXPConnect,
nsISupportsWeakReference,
nsIThreadObserver)
nsXPConnect* nsXPConnect::gSelf = nullptr;
+43 -19
View File
@@ -247,8 +247,7 @@ static inline bool IS_WN_REFLECTOR(JSObject* obj)
// to this rule are noted explicitly.
class nsXPConnect final : public nsIXPConnect,
public nsIThreadObserver,
public nsSupportsWeakReference
public nsIThreadObserver
{
public:
// all the interface method declarations...
@@ -587,9 +586,6 @@ public:
inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
static void SuspectWrappedNative(XPCWrappedNative* wrapper,
nsCycleCollectionNoteRootCallback& cb);
void DebugDump(int16_t depth);
void SystemIsBeingShutDown();
@@ -2252,6 +2248,7 @@ public:
bool HasExternalReference() const {return mRefCnt > 1;}
void Suspect(nsCycleCollectionNoteRootCallback& cb);
void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
// Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
@@ -2398,7 +2395,7 @@ private:
uint16_t methodIndex,
uint8_t paramIndex,
nsXPTCMiniVariant* params,
uint32_t* result);
uint32_t* result) const;
bool GetInterfaceTypeFromParam(JSContext* cx,
const XPTMethodDescriptor* method,
@@ -2406,14 +2403,17 @@ private:
uint16_t methodIndex,
const nsXPTType& type,
nsXPTCMiniVariant* params,
nsID* result);
nsID* result) const;
void CleanupPointerArray(const nsXPTType& datum_type,
uint32_t array_count,
void** arrayp);
static void CleanupPointerArray(const nsXPTType& datum_type,
uint32_t array_count,
void** arrayp);
void CleanupPointerTypeObject(const nsXPTType& type,
void** pp);
static void CleanupPointerTypeObject(const nsXPTType& type,
void** pp);
void CleanupOutparams(JSContext* cx, uint16_t methodIndex, const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams, bool inOutOnly, uint8_t n) const;
private:
XPCJSRuntime* mRuntime;
@@ -2993,18 +2993,17 @@ xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
// Definition of nsScriptError, defined here because we lack a place to put
// XPCOM objects associated with the JavaScript engine.
class nsScriptError : public nsIScriptError {
class nsScriptErrorBase : public nsIScriptError {
public:
nsScriptError();
nsScriptErrorBase();
// TODO - do something reasonable on getting null from these babies.
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICONSOLEMESSAGE
NS_DECL_NSISCRIPTERROR
protected:
virtual ~nsScriptError();
virtual ~nsScriptErrorBase();
void
InitializeOnMainThread();
@@ -3026,7 +3025,16 @@ protected:
bool mIsFromPrivateWindow;
};
class nsScriptErrorWithStack : public nsScriptError {
class nsScriptError final : public nsScriptErrorBase {
public:
nsScriptError() {}
NS_DECL_THREADSAFE_ISUPPORTS
private:
virtual ~nsScriptError() {}
};
class nsScriptErrorWithStack : public nsScriptErrorBase {
public:
explicit nsScriptErrorWithStack(JS::HandleObject);
@@ -3470,6 +3478,7 @@ public:
JSObject* options = nullptr)
: OptionsBase(cx, options)
, wantXrays(true)
, allowWaivers(true)
, wantComponents(true)
, wantExportHelpers(false)
, proto(cx)
@@ -3485,6 +3494,7 @@ public:
virtual bool Parse();
bool wantXrays;
bool allowWaivers;
bool wantComponents;
bool wantExportHelpers;
JS::RootedObject proto;
@@ -3569,11 +3579,13 @@ public:
: OptionsBase(cx, options)
, wrapReflectors(false)
, cloneFunctions(false)
, deepFreeze(false)
{ }
virtual bool Parse() {
return ParseBoolean("wrapReflectors", &wrapReflectors) &&
ParseBoolean("cloneFunctions", &cloneFunctions);
ParseBoolean("cloneFunctions", &cloneFunctions) &&
ParseBoolean("deepFreeze", &deepFreeze);
}
// When a reflector is encountered, wrap it rather than aborting the clone.
@@ -3582,6 +3594,9 @@ public:
// When a function is encountered, clone it (exportFunction-style) rather than
// aborting the clone.
bool cloneFunctions;
// If true, the resulting object is deep-frozen after being cloned.
bool deepFreeze;
};
JSObject*
@@ -3681,6 +3696,7 @@ public:
explicit CompartmentPrivate(JSCompartment* c)
: wantXrays(false)
, allowWaivers(true)
, writeToGlobalPrototype(false)
, skipWriteToGlobalPrototype(false)
, universalXPConnectEnabled(false)
@@ -3708,9 +3724,17 @@ public:
return Get(compartment);
}
// Controls whether this compartment gets Xrays to same-origin. This behavior
// is deprecated, but is still the default for sandboxes for compatibity
// reasons.
bool wantXrays;
// Controls whether this compartment is allowed to waive Xrays to content
// that it subsumes. This should generally be true, except in cases where we
// want to prevent code from depending on Xray Waivers (which might make it
// more portable to other browser architectures).
bool allowWaivers;
// This flag is intended for a very specific use, internal to Gecko. It may
// go away or change behavior at any time. It should not be added to any
// documentation and it should not be used without consulting the XPConnect
@@ -0,0 +1,30 @@
const Cu = Components.utils;
function checkWaivers(from, allowed) {
var sb = new Cu.Sandbox('http://example.com');
from.test = sb.eval('var o = {prop: 2, f: function() {return 42;}}; o');
// Make sure that |from| has Xrays to sb.
do_check_eq(from.eval('test.prop'), 2);
do_check_eq(from.eval('test.f'), undefined);
// Make sure that waivability works as expected.
do_check_eq(from.eval('!!test.wrappedJSObject'), allowed);
do_check_eq(from.eval('XPCNativeWrapper.unwrap(test) !== test'), allowed);
// Make a sandbox with the same principal as |from|, but without any waiver
// restrictions, and make sure that the waiver does not transfer.
var friend = new Cu.Sandbox(Cu.getObjectPrincipal(from));
friend.test = from.test;
friend.eval('var waived = test.wrappedJSObject;');
do_check_true(friend.eval('waived.f()'), 42);
friend.from = from;
friend.eval('from.waived = waived');
do_check_eq(from.eval('!!waived.f'), allowed);
}
function run_test() {
checkWaivers(new Cu.Sandbox('http://example.com'), true);
checkWaivers(new Cu.Sandbox('http://example.com', {allowWaivers: false}), false);
checkWaivers(new Cu.Sandbox(['http://example.com']), true);
checkWaivers(new Cu.Sandbox(['http://example.com'], {allowWaivers: false}), false);
}
@@ -0,0 +1,33 @@
const Cu = Components.utils;
function checkThrows(f, rgxp) { try { f(); do_check_false(); } catch (e) { do_check_true(rgxp.test(e)); } }
var o = { foo: 42, bar : { tick: 'tock' } };
function checkClone(clone, frozen) {
var waived = Cu.waiveXrays(clone);
function touchFoo() { "use strict"; waived.foo = 12; do_check_eq(waived.foo, 12); }
function touchBar() { "use strict"; waived.bar.tick = 'tack'; do_check_eq(waived.bar.tick, 'tack'); }
function addProp() { "use strict"; waived.newProp = 100; do_check_eq(waived.newProp, 100); }
if (!frozen) {
touchFoo();
touchBar();
addProp();
} else {
checkThrows(touchFoo, /read-only/);
checkThrows(touchBar, /read-only/);
checkThrows(addProp, /extensible/);
}
var desc = Object.getOwnPropertyDescriptor(waived, 'foo');
do_check_eq(desc.writable, !frozen);
do_check_eq(desc.configurable, !frozen);
desc = Object.getOwnPropertyDescriptor(waived.bar, 'tick');
do_check_eq(desc.writable, !frozen);
do_check_eq(desc.configurable, !frozen);
}
function run_test() {
var sb = new Cu.Sandbox(null);
checkClone(Cu.waiveXrays(Cu.cloneInto(o, sb)), false);
checkClone(Cu.cloneInto(o, sb, { deepFreeze: true }), true);
}
+2
View File
@@ -18,6 +18,7 @@ support-files =
recursive_importB.jsm
syntax_error.jsm
[test_allowWaivers.js]
[test_bogus_files.js]
[test_bug408412.js]
[test_bug451678.js]
@@ -61,6 +62,7 @@ support-files =
[test_bug1170311.js]
[test_bug_442086.js]
[test_callFunctionWithAsyncStack.js]
[test_deepFreezeClone.js]
[test_file.js]
[test_blob.js]
[test_blob2.js]
+19 -3
View File
@@ -106,6 +106,20 @@ WrapperFactory::WaiveXray(JSContext* cx, JSObject* objArg)
return CreateXrayWaiver(cx, obj);
}
/* static */ bool
WrapperFactory::AllowWaiver(JSCompartment* target, JSCompartment* origin)
{
return CompartmentPrivate::Get(target)->allowWaivers &&
AccessCheck::subsumes(target, origin);
}
/* static */ bool
WrapperFactory::AllowWaiver(JSObject* wrapper) {
MOZ_ASSERT(js::IsCrossCompartmentWrapper(wrapper));
return AllowWaiver(js::GetObjectCompartment(wrapper),
js::GetObjectCompartment(js::UncheckedUnwrap(wrapper)));
}
inline bool
ShouldWaiveXray(JSContext* cx, JSObject* originalObj)
{
@@ -468,8 +482,10 @@ WrapperFactory::Rewrap(JSContext* cx, HandleObject existing, HandleObject obj)
bool wantXrays = !sameOrigin || sameOriginXrays;
// If Xrays are warranted, the caller may waive them for non-security
// wrappers.
bool waiveXrays = wantXrays && !securityWrapper && HasWaiveXrayFlag(obj);
// wrappers (unless explicitly forbidden from doing so).
bool waiveXrays = wantXrays && !securityWrapper &&
CompartmentPrivate::Get(target)->allowWaivers &&
HasWaiveXrayFlag(obj);
// We have slightly different behavior for the case when the object
// being wrapped is in an XBL scope.
@@ -542,7 +558,7 @@ WrapperFactory::WaiveXrayAndWrap(JSContext* cx, MutableHandleObject argObj)
// to things in |obj|'s compartment.
JSCompartment* target = js::GetContextCompartment(cx);
JSCompartment* origin = js::GetObjectCompartment(obj);
obj = AccessCheck::subsumes(target, origin) ? WaiveXray(cx, obj) : obj;
obj = AllowWaiver(target, origin) ? WaiveXray(cx, obj) : obj;
if (!obj)
return false;
+7
View File
@@ -37,6 +37,13 @@ class WrapperFactory {
static JSObject* CreateXrayWaiver(JSContext* cx, JS::HandleObject obj);
static JSObject* WaiveXray(JSContext* cx, JSObject* obj);
// Computes whether we should allow the creation of an Xray waiver from
// |target| to |origin|.
static bool AllowWaiver(JSCompartment* target, JSCompartment* origin);
// Convenience method for the above, operating on a wrapper.
static bool AllowWaiver(JSObject* wrapper);
// Prepare a given object for wrapping in a new compartment.
static JSObject* PrepareForWrapping(JSContext* cx,
JS::HandleObject scope,
+2 -2
View File
@@ -1318,7 +1318,7 @@ wrappedJSObject_getter(JSContext* cx, unsigned argc, Value* vp)
}
RootedObject wrapper(cx, &args.thisv().toObject());
if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper) ||
!AccessCheck::wrapperSubsumes(wrapper)) {
!WrapperFactory::AllowWaiver(wrapper)) {
JS_ReportError(cx, "Unexpected object");
return false;
}
@@ -1381,7 +1381,7 @@ XrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
// Handle .wrappedJSObject for subsuming callers. This should move once we
// sort out own-ness for the holder.
if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_WRAPPED_JSOBJECT) &&
AccessCheck::wrapperSubsumes(wrapper))
WrapperFactory::AllowWaiver(wrapper))
{
if (!JS_AlreadyHasOwnPropertyById(cx, holder, id, &found))
return false;
+15 -4
View File
@@ -614,12 +614,14 @@ nsCSSExpandedDataBlock::TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
bool aIsImportant,
bool aOverrideImportant,
bool aMustCallValueAppended,
css::Declaration* aDeclaration)
css::Declaration* aDeclaration,
nsIDocument* aSheetDocument)
{
if (!nsCSSProps::IsShorthand(aPropID)) {
return DoTransferFromBlock(aFromBlock, aPropID,
aIsImportant, aOverrideImportant,
aMustCallValueAppended, aDeclaration);
aMustCallValueAppended, aDeclaration,
aSheetDocument);
}
// We can pass eIgnoreEnabledState (here, and in ClearProperty above) rather
@@ -631,7 +633,8 @@ nsCSSExpandedDataBlock::TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID, aEnabledState) {
changed |= DoTransferFromBlock(aFromBlock, *p,
aIsImportant, aOverrideImportant,
aMustCallValueAppended, aDeclaration);
aMustCallValueAppended, aDeclaration,
aSheetDocument);
}
return changed;
}
@@ -642,7 +645,8 @@ nsCSSExpandedDataBlock::DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
bool aIsImportant,
bool aOverrideImportant,
bool aMustCallValueAppended,
css::Declaration* aDeclaration)
css::Declaration* aDeclaration,
nsIDocument* aSheetDocument)
{
bool changed = false;
MOZ_ASSERT(aFromBlock.HasPropertyBit(aPropID), "oops");
@@ -670,6 +674,13 @@ nsCSSExpandedDataBlock::DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
aDeclaration->ValueAppended(aPropID);
}
if (aSheetDocument) {
UseCounter useCounter = nsCSSProps::UseCounterFor(aPropID);
if (useCounter != eUseCounter_UNKNOWN) {
aSheetDocument->SetDocumentAndPageUseCounter(useCounter);
}
}
SetPropertyBit(aPropID);
aFromBlock.ClearPropertyBit(aPropID);
+7 -2
View File
@@ -19,6 +19,7 @@
struct nsRuleData;
class nsCSSExpandedDataBlock;
class nsIDocument;
namespace mozilla {
namespace css {
@@ -249,6 +250,8 @@ public:
* Returns true if something changed, false otherwise. Calls
* |ValueAppended| on |aDeclaration| if the property was not
* previously set, or in any case if |aMustCallValueAppended| is true.
* Calls |SetDocumentAndPageUseCounter| on |aSheetDocument| if it is
* non-null and |aPropID| has a use counter.
*/
bool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
nsCSSProperty aPropID,
@@ -256,7 +259,8 @@ public:
bool aIsImportant,
bool aOverrideImportant,
bool aMustCallValueAppended,
mozilla::css::Declaration* aDeclaration);
mozilla::css::Declaration* aDeclaration,
nsIDocument* aSheetDocument);
/**
* Copies the values for aPropID into the specified aRuleData object.
@@ -290,7 +294,8 @@ private:
bool aIsImportant,
bool aOverrideImportant,
bool aMustCallValueAppended,
mozilla::css::Declaration* aDeclaration);
mozilla::css::Declaration* aDeclaration,
nsIDocument* aSheetDocument);
#ifdef DEBUG
void DoAssertInitialState();
+14 -2
View File
@@ -111,6 +111,8 @@ public:
nsresult SetStyleSheet(CSSStyleSheet* aSheet);
nsIDocument* GetDocument();
nsresult SetQuirkMode(bool aQuirkMode);
nsresult SetChildLoader(mozilla::css::Loader* aChildLoader);
@@ -1341,6 +1343,15 @@ CSSParserImpl::SetStyleSheet(CSSStyleSheet* aSheet)
return NS_OK;
}
nsIDocument*
CSSParserImpl::GetDocument()
{
if (!mSheet) {
return nullptr;
}
return mSheet->GetDocument();
}
nsresult
CSSParserImpl::SetQuirkMode(bool aQuirkMode)
{
@@ -1693,7 +1704,8 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID,
aDeclaration->ExpandTo(&mData);
*aChanged = mData.TransferFromBlock(mTempData, aPropID,
PropertyEnabledState(), aIsImportant,
true, false, aDeclaration);
true, false, aDeclaration,
GetDocument());
aDeclaration->CompressFrom(&mData);
}
CLEAR_ERROR();
@@ -6906,7 +6918,7 @@ CSSParserImpl::ParseDeclaration(css::Declaration* aDeclaration,
PropertyEnabledState(),
status == ePriority_Important,
false, aMustCallValueAppended,
aDeclaration);
aDeclaration, GetDocument());
}
return true;
+15
View File
@@ -2989,6 +2989,21 @@ nsCSSProps::gPropertyEnabled[eCSSProperty_COUNT_with_aliases] = {
#undef CSS_PROP_ALIAS
};
#include "../../dom/base/PropertyUseCounterMap.inc"
/* static */ const UseCounter
nsCSSProps::gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands] = {
#define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) privatename_
#define CSS_PROP_LIST_INCLUDE_LOGICAL
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \
kwtable_, stylestruct_, stylestructoffset_, animtype_) \
static_cast<UseCounter>(USE_COUNTER_FOR_CSS_PROPERTY_##method_),
#include "nsCSSPropList.h"
#undef CSS_PROP
#undef CSS_PROP_LIST_INCLUDE_LOGICAL
#undef CSS_PROP_PUBLIC_OR_PRIVATE
};
// Check that all logical property flags are used appropriately.
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \
kwtable_, stylestruct_, stylestructoffset_, animtype_) \
+15
View File
@@ -15,6 +15,7 @@
#include "nsCSSProperty.h"
#include "nsStyleStructFwd.h"
#include "nsCSSKeywords.h"
#include "mozilla/UseCounter.h"
// Length of the "--" prefix on custom names (such as custom property names,
// and, in the future, custom media query names).
@@ -516,6 +517,20 @@ public:
return gPropertyEnabled[aProperty];
}
private:
// A table for the use counter associated with each CSS property. If a
// property does not have a use counter defined in UseCounters.conf, then
// its associated entry is |eUseCounter_UNKNOWN|.
static const mozilla::UseCounter gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands];
public:
static mozilla::UseCounter UseCounterFor(nsCSSProperty aProperty) {
MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
"out of range");
return gPropertyUseCounter[aProperty];
}
static bool IsEnabled(nsCSSProperty aProperty, EnabledState aEnabled)
{
if (IsEnabled(aProperty)) {
+1 -8
View File
@@ -213,14 +213,7 @@ nsJARChannel::nsJARChannel()
nsJARChannel::~nsJARChannel()
{
if (mLoadInfo) {
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
nsILoadInfo *forgetableLoadInfo;
mLoadInfo.forget(&forgetableLoadInfo);
NS_ProxyRelease(mainThread, forgetableLoadInfo, false);
}
NS_ReleaseOnMainThread(mLoadInfo);
// release owning reference to the jar handler
nsJARProtocolHandler *handler = gJarHandler;
+1 -8
View File
@@ -105,14 +105,7 @@ HttpBaseChannel::~HttpBaseChannel()
{
LOG(("Destroying HttpBaseChannel @%x\n", this));
if (mLoadInfo) {
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
nsILoadInfo *forgetableLoadInfo;
mLoadInfo.forget(&forgetableLoadInfo);
NS_ProxyRelease(mainThread, forgetableLoadInfo, false);
}
NS_ReleaseOnMainThread(mLoadInfo);
// Make sure we don't leak
CleanRedirectCacheChainIfNecessary();
@@ -1185,33 +1185,13 @@ WebSocketChannel::~WebSocketChannel()
while ((mCurrentOut = (OutboundMessage *) mOutgoingMessages.PopFront()))
delete mCurrentOut;
nsCOMPtr<nsIThread> mainThread;
nsIURI *forgettable;
NS_GetMainThread(getter_AddRefs(mainThread));
if (mURI) {
mURI.forget(&forgettable);
NS_ProxyRelease(mainThread, forgettable, false);
}
if (mOriginalURI) {
mOriginalURI.forget(&forgettable);
NS_ProxyRelease(mainThread, forgettable, false);
}
NS_ReleaseOnMainThread(mURI);
NS_ReleaseOnMainThread(mOriginalURI);
mListenerMT = nullptr;
if (mLoadGroup) {
nsILoadGroup *forgettableGroup;
mLoadGroup.forget(&forgettableGroup);
NS_ProxyRelease(mainThread, forgettableGroup, false);
}
if (mLoadInfo) {
nsILoadInfo *forgetableLoadInfo;
mLoadInfo.forget(&forgetableLoadInfo);
NS_ProxyRelease(mainThread, forgetableLoadInfo, false);
}
NS_ReleaseOnMainThread(mLoadGroup);
NS_ReleaseOnMainThread(mLoadInfo);
}
NS_IMETHODIMP
+7
View File
@@ -64,12 +64,17 @@
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/ScriptSettings.h"
#include "jsprf.h"
#include "js/Debug.h"
#include "nsCycleCollectionNoteRootCallback.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCycleCollector.h"
#include "nsDOMJSUtils.h"
#include "nsJSUtils.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "nsIException.h"
#include "nsThreadUtils.h"
#include "xpcpublic.h"
@@ -424,6 +429,8 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSRuntime* aParentRuntime,
};
SetDOMCallbacks(mJSRuntime, &DOMcallbacks);
JS::dbg::SetDebuggerMallocSizeOf(mJSRuntime, moz_malloc_size_of);
nsCycleCollector_registerJSRuntime(this);
}
+4 -2
View File
@@ -102,6 +102,7 @@ struct CycleCollectorResults
{
mForcedGC = false;
mMergedZones = false;
mAnyManual = false;
mVisitedRefCounted = 0;
mVisitedGCed = 0;
mFreedRefCounted = 0;
@@ -114,6 +115,7 @@ struct CycleCollectorResults
bool mForcedGC;
bool mMergedZones;
bool mAnyManual; // true if any slice of the CC was manually triggered, or at shutdown.
uint32_t mVisitedRefCounted;
uint32_t mVisitedGCed;
uint32_t mFreedRefCounted;
@@ -206,6 +208,7 @@ private:
virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
void TraceNativeGrayRoots(JSTracer* aTracer);
public:
enum DeferredFinalizeType {
FinalizeIncrementally,
FinalizeNow,
@@ -213,7 +216,6 @@ private:
void FinalizeDeferredThings(DeferredFinalizeType aType);
public:
// Two conditions, JSOutOfMemory and JSLargeAllocationFailure, are noted in
// crash reports. Here are the values that can appear in the reports:
enum class OOMState : uint32_t {
@@ -221,7 +223,7 @@ public:
OK,
// We are currently reporting the given condition.
//
//
// Suppose a crash report contains "JSLargeAllocationFailure:
// Reporting". This means we crashed while executing memory-pressure
// observers, trying to shake loose some memory. The large allocation in
+14 -1
View File
@@ -20,6 +20,7 @@
#include "nsIClassInfoImpl.h"
#include "nsIConsoleListener.h"
#include "nsPrintfCString.h"
#include "nsProxyRelease.h"
#include "nsIScriptError.h"
#include "mozilla/Preferences.h"
@@ -67,6 +68,8 @@ nsConsoleService::nsConsoleService()
NS_IMETHODIMP
nsConsoleService::ClearMessagesForWindowID(const uint64_t innerID)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Remove the messages related to this window
for (uint32_t i = 0; i < mBufferSize && mMessages[i]; i++) {
// Only messages implementing nsIScriptError interface exposes the inner window ID
@@ -104,6 +107,8 @@ nsConsoleService::ClearMessagesForWindowID(const uint64_t innerID)
nsConsoleService::~nsConsoleService()
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
uint32_t i = 0;
while (i < mBufferSize && mMessages[i]) {
NS_RELEASE(mMessages[i]);
@@ -200,6 +205,7 @@ nsConsoleService::LogMessage(nsIConsoleMessage* aMessage)
return LogMessageWithMode(aMessage, OutputToLog);
}
// This can be called off the main thread.
nsresult
nsConsoleService::LogMessageWithMode(nsIConsoleMessage* aMessage,
nsConsoleService::OutputMode aOutputMode)
@@ -313,7 +319,10 @@ nsConsoleService::LogMessageWithMode(nsIConsoleMessage* aMessage,
}
if (retiredMessage) {
NS_RELEASE(retiredMessage);
// Release |retiredMessage| on the main thread in case it is an instance of
// a mainthread-only class like nsScriptErrorWithStack and we're off the
// main thread.
NS_ReleaseOnMainThread(retiredMessage);
}
if (r) {
@@ -353,6 +362,8 @@ NS_IMETHODIMP
nsConsoleService::GetMessageArray(uint32_t* aCount,
nsIConsoleMessage*** aMessages)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
nsIConsoleMessage** messageArray;
/*
@@ -449,6 +460,8 @@ nsConsoleService::UnregisterListener(nsIConsoleListener* aListener)
NS_IMETHODIMP
nsConsoleService::Reset()
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
/*
* Make sure nobody trips into the buffer while it's being reset
*/
+8
View File
@@ -3551,6 +3551,9 @@ nsCycleCollector::CleanupAfterCollection()
#endif
if (mJSRuntime) {
mJSRuntime->FinalizeDeferredThings(mResults.mAnyManual
? CycleCollectedJSRuntime::FinalizeNow
: CycleCollectedJSRuntime::FinalizeIncrementally);
mJSRuntime->EndCycleCollectionCallback(mResults);
timeLog.Checkpoint("CleanupAfterCollection::EndCycleCollectionCallback()");
}
@@ -3613,6 +3616,10 @@ nsCycleCollector::Collect(ccType aCCType,
timeLog.Checkpoint("Collect::FreeSnowWhite");
}
if (aCCType != SliceCC) {
mResults.mAnyManual = true;
}
++mResults.mNumSlices;
bool continueSlice = aBudget.isUnlimited() || !aPreferShorterSlices;
@@ -3810,6 +3817,7 @@ nsCycleCollector::BeginCollection(ccType aCCType,
// Set up the data structures for building the graph.
mGraph.Init();
mResults.Init();
mResults.mAnyManual = (aCCType != SliceCC);
bool mergeZones = ShouldMergeZones(aCCType);
mResults.mMergedZones = mergeZones;
+57 -1
View File
@@ -57,7 +57,7 @@ NS_ProxyRelease(nsIEventTarget* aTarget, nsRefPtr<T>& aDoomed,
* the doomed object; the object to be released on the target thread.
* @param aAlwaysProxy
* normally, if NS_ProxyRelease is called on the target thread, then the
* doomed object will released directly. however, if this parameter is
* doomed object will be released directly. However, if this parameter is
* true, then an event will always be posted to the target thread for
* asynchronous release.
*/
@@ -65,6 +65,62 @@ nsresult
NS_ProxyRelease(nsIEventTarget* aTarget, nsISupports* aDoomed,
bool aAlwaysProxy = false);
/**
* Ensure that a nsCOMPtr is released on the main thread.
*
* @see NS_ReleaseOnMainThread( nsISupports*, bool)
*/
template<class T>
inline NS_HIDDEN_(nsresult)
NS_ReleaseOnMainThread(nsCOMPtr<T>& aDoomed,
bool aAlwaysProxy = false)
{
T* raw = nullptr;
aDoomed.swap(raw);
return NS_ReleaseOnMainThread(raw, aAlwaysProxy);
}
/**
* Ensure that a nsRefPtr is released on the main thread.
*
* @see NS_ReleaseOnMainThread(nsISupports*, bool)
*/
template<class T>
inline NS_HIDDEN_(nsresult)
NS_ReleaseOnMainThread(nsRefPtr<T>& aDoomed,
bool aAlwaysProxy = false)
{
T* raw = nullptr;
aDoomed.swap(raw);
return NS_ReleaseOnMainThread(raw, aAlwaysProxy);
}
/**
* Ensures that the delete of a nsISupports object occurs on the main thread.
*
* @param aDoomed
* the doomed object; the object to be released on the main thread.
* @param aAlwaysProxy
* normally, if NS_ReleaseOnMainThread is called on the main thread,
* then the doomed object will be released directly. However, if this
* parameter is true, then an event will always be posted to the main
* thread for asynchronous release.
*/
inline nsresult
NS_ReleaseOnMainThread(nsISupports* aDoomed,
bool aAlwaysProxy = false)
{
// NS_ProxyRelease treats a null event target as "the current thread". So a
// handle on the main thread is only necessary when we're not already on the
// main thread or the release must happen asynchronously.
nsCOMPtr<nsIThread> mainThread;
if (!NS_IsMainThread() || aAlwaysProxy) {
NS_GetMainThread(getter_AddRefs(mainThread));
}
return NS_ProxyRelease(mainThread, aDoomed, aAlwaysProxy);
}
/**
* Class to safely handle main-thread-only pointers off the main thread.
*
@@ -0,0 +1,34 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is just a sanity test that Gecko is giving SpiderMonkey a MallocSizeOf
// function for new JSRuntimes. There is more extensive testing around the
// expected byte sizes within SpiderMonkey's jit-tests, we just want to make
// sure that Gecko is providing SpiderMonkey with the callback it needs.
const Cu = Components.utils;
const { byteSize } = Cu.getJSTestingFunctions();
function run_test()
{
const objects = [
{},
{ w: 1, x: 2, y: 3, z:4, a: 5 },
[],
Array(10).fill(null),
new RegExp("(2|two) problems", "g"),
new Date(),
new Uint8Array(64),
Promise.resolve(1),
function f() {},
Object
];
for (let obj of objects) {
do_print(uneval(obj));
ok(byteSize(obj), "We should get some (non-zero) byte size");
}
}
+1
View File
@@ -27,6 +27,7 @@ fail-if = os == "android"
# Bug 676998: test fails consistently on Android
fail-if = os == "android"
[test_bug725015.js]
[test_debugger_malloc_size_of.js]
[test_compmgr_warnings.js]
# Bug 676998: test fails consistently on Android
fail-if = os == "android"
+22
View File
@@ -769,6 +769,28 @@ nsThread::ProcessNextEvent(bool aMayWait, bool* aResult)
}
}
#ifdef MOZ_CRASHREPORTER
if (MAIN_THREAD == mIsMainThread && !ShuttingDown()) {
// Keep an eye on memory usage (cheap, ~7ms) somewhat frequently,
// but save memory reports (expensive, ~75ms) less frequently.
const size_t LOW_MEMORY_CHECK_SECONDS = 30;
const size_t LOW_MEMORY_SAVE_SECONDS = 3 * 60;
static TimeStamp nextCheck = TimeStamp::NowLoRes()
+ TimeDuration::FromSeconds(LOW_MEMORY_CHECK_SECONDS);
TimeStamp now = TimeStamp::NowLoRes();
if (now >= nextCheck) {
if (SaveMemoryReportNearOOM()) {
nextCheck = now + TimeDuration::FromSeconds(LOW_MEMORY_SAVE_SECONDS);
} else {
nextCheck = now + TimeDuration::FromSeconds(LOW_MEMORY_CHECK_SECONDS);
}
}
}
#endif
bool notifyMainThreadObserver =
(MAIN_THREAD == mIsMainThread) && sMainThreadObserver;
if (notifyMainThreadObserver) {