mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- 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:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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, ¶m,
|
||||
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, ¶m,
|
||||
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, ¶m,
|
||||
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();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ using namespace JS;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXPConnect,
|
||||
nsIXPConnect,
|
||||
nsISupportsWeakReference,
|
||||
nsIThreadObserver)
|
||||
|
||||
nsXPConnect* nsXPConnect::gSelf = nullptr;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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,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");
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user