mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Merge inbound to m-c a=merge
This commit is contained in:
commit
530c4a09f9
@ -157,7 +157,7 @@ struct EventNameMapping
|
||||
{
|
||||
// This holds pointers to nsGkAtoms members, and is therefore safe as a
|
||||
// non-owning reference.
|
||||
nsIAtom* MOZ_OWNING_REF mAtom;
|
||||
nsIAtom* MOZ_NON_OWNING_REF mAtom;
|
||||
uint32_t mId;
|
||||
int32_t mType;
|
||||
mozilla::EventClassID mEventClassID;
|
||||
|
@ -120,27 +120,19 @@ nsStyleLinkElement::SetLineNumber(uint32_t aLineNumber)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsStyleLinkElement::IsImportEnabled(nsIPrincipal* aPrincipal)
|
||||
nsStyleLinkElement::IsImportEnabled()
|
||||
{
|
||||
static bool sAdded = false;
|
||||
static bool sWebComponentsEnabled;
|
||||
static bool sImportsEnabled;
|
||||
if (!sAdded) {
|
||||
// This part runs only once because of the static flag.
|
||||
Preferences::AddBoolVarCache(&sWebComponentsEnabled,
|
||||
"dom.webcomponents.enabled",
|
||||
Preferences::AddBoolVarCache(&sImportsEnabled,
|
||||
"dom.htmlimports.enabled",
|
||||
false);
|
||||
sAdded = true;
|
||||
}
|
||||
|
||||
if (sWebComponentsEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the web components pref is not enabled, check
|
||||
// if we are in a certified app because imports is enabled
|
||||
// for certified apps.
|
||||
return aPrincipal &&
|
||||
aPrincipal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED;
|
||||
return sImportsEnabled;
|
||||
}
|
||||
|
||||
static uint32_t ToLinkMask(const nsAString& aLink, nsIPrincipal* aPrincipal)
|
||||
@ -155,8 +147,8 @@ static uint32_t ToLinkMask(const nsAString& aLink, nsIPrincipal* aPrincipal)
|
||||
return nsStyleLinkElement::eNEXT;
|
||||
else if (aLink.EqualsLiteral("alternate"))
|
||||
return nsStyleLinkElement::eALTERNATE;
|
||||
else if (aLink.EqualsLiteral("import") && aPrincipal &&
|
||||
nsStyleLinkElement::IsImportEnabled(aPrincipal))
|
||||
else if (aLink.EqualsLiteral("import") &&
|
||||
nsStyleLinkElement::IsImportEnabled())
|
||||
return nsStyleLinkElement::eHTMLIMPORT;
|
||||
else
|
||||
return 0;
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
static uint32_t ParseLinkTypes(const nsAString& aTypes,
|
||||
nsIPrincipal* aPrincipal);
|
||||
|
||||
static bool IsImportEnabled(nsIPrincipal* aPrincipal);
|
||||
static bool IsImportEnabled();
|
||||
|
||||
void UpdateStyleSheetInternal()
|
||||
{
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
@ -1577,6 +1578,15 @@ WrapNativeParent(JSContext* cx, const T& p)
|
||||
return WrapNativeParent(cx, GetParentPointer(p), GetWrapperCache(p), GetUseXBLScope(p));
|
||||
}
|
||||
|
||||
// Specialization for the case of nsIGlobalObject, since in that case
|
||||
// we can just get the JSObject* directly.
|
||||
template<>
|
||||
inline JSObject*
|
||||
WrapNativeParent(JSContext* cx, nsIGlobalObject* const& p)
|
||||
{
|
||||
return p ? p->GetGlobalJSObject() : JS::CurrentGlobalOrNull(cx);
|
||||
}
|
||||
|
||||
template<typename T, bool WrapperCached=NativeHasMember<T>::GetParentObject>
|
||||
struct GetParentObject
|
||||
{
|
||||
|
@ -16,8 +16,9 @@ DataContainerEvent::DataContainerEvent(EventTarget* aOwner,
|
||||
WidgetEvent* aEvent)
|
||||
: Event(aOwner, aPresContext, aEvent)
|
||||
{
|
||||
if (mOwner) {
|
||||
if (nsIDocument* doc = mOwner->GetExtantDoc()) {
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mOwner);
|
||||
if (win) {
|
||||
if (nsIDocument* doc = win->GetExtantDoc()) {
|
||||
doc->WarnOnceAbout(nsIDocument::eDataContainerEvent);
|
||||
}
|
||||
}
|
||||
|
@ -1026,7 +1026,11 @@ Event::TimeStamp() const
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
nsPerformance* perf = mOwner->GetPerformance();
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mOwner);
|
||||
if (NS_WARN_IF(!win)) {
|
||||
return 0.0;
|
||||
}
|
||||
nsPerformance* perf = win->GetPerformance();
|
||||
if (NS_WARN_IF(!perf)) {
|
||||
return 0.0;
|
||||
}
|
||||
@ -1049,8 +1053,9 @@ Event::TimeStamp() const
|
||||
bool
|
||||
Event::GetPreventDefault() const
|
||||
{
|
||||
if (mOwner) {
|
||||
if (nsIDocument* doc = mOwner->GetExtantDoc()) {
|
||||
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mOwner));
|
||||
if (win) {
|
||||
if (nsIDocument* doc = win->GetExtantDoc()) {
|
||||
doc->WarnOnceAbout(nsIDocument::eGetPreventDefault);
|
||||
}
|
||||
}
|
||||
@ -1130,23 +1135,23 @@ Event::SetOwner(mozilla::dom::EventTarget* aOwner)
|
||||
|
||||
nsCOMPtr<nsINode> n = do_QueryInterface(aOwner);
|
||||
if (n) {
|
||||
mOwner = do_QueryInterface(n->OwnerDoc()->GetScopeObject());
|
||||
mOwner = n->OwnerDoc()->GetScopeObject();
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aOwner);
|
||||
if (w) {
|
||||
if (w->IsOuterWindow()) {
|
||||
mOwner = w->GetCurrentInnerWindow();
|
||||
mOwner = do_QueryInterface(w->GetCurrentInnerWindow());
|
||||
} else {
|
||||
mOwner.swap(w);
|
||||
mOwner = do_QueryInterface(w);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<DOMEventTargetHelper> eth = do_QueryInterface(aOwner);
|
||||
if (eth) {
|
||||
mOwner = eth->GetOwner();
|
||||
mOwner = eth->GetParentObject();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "Units.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIDOMEventTarget;
|
||||
@ -63,15 +64,6 @@ private:
|
||||
WidgetEvent* aEvent);
|
||||
|
||||
public:
|
||||
void GetParentObject(nsIScriptGlobalObject** aParentObject)
|
||||
{
|
||||
if (mOwner) {
|
||||
CallQueryInterface(mOwner, aParentObject);
|
||||
} else {
|
||||
*aParentObject = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static Event* FromSupports(nsISupports* aSupports)
|
||||
{
|
||||
nsIDOMEvent* event =
|
||||
@ -93,7 +85,7 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Event)
|
||||
|
||||
nsISupports* GetParentObject()
|
||||
nsIGlobalObject* GetParentObject()
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
@ -274,7 +266,7 @@ protected:
|
||||
mozilla::WidgetEvent* mEvent;
|
||||
nsRefPtr<nsPresContext> mPresContext;
|
||||
nsCOMPtr<EventTarget> mExplicitOriginalTarget;
|
||||
nsCOMPtr<nsPIDOMWindow> mOwner; // nsPIDOMWindow for now.
|
||||
nsCOMPtr<nsIGlobalObject> mOwner;
|
||||
bool mEventIsInternal;
|
||||
bool mPrivateDataDuplicated;
|
||||
bool mIsMainThreadEvent;
|
||||
|
@ -275,7 +275,7 @@ HTMLLinkElement::UpdateImport()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nsStyleLinkElement::IsImportEnabled(NodePrincipal())) {
|
||||
if (!nsStyleLinkElement::IsImportEnabled()) {
|
||||
// For now imports are hidden behind a pref...
|
||||
return;
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "nsIEffectiveTLDService.h"
|
||||
#include "nsIIDNService.h"
|
||||
#include "nsCRT.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "nsIWindowsRegKey.h"
|
||||
@ -37,6 +36,7 @@
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
class PluginAsyncSurrogate;
|
||||
class PluginTag;
|
||||
} // namespace mozilla
|
||||
} // namespace plugins
|
||||
|
||||
|
@ -2228,6 +2228,7 @@ XMLHttpRequest::Abort(ErrorResult& aRv)
|
||||
|
||||
if (mCanceled) {
|
||||
aRv.ThrowUncatchableException();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mProxy) {
|
||||
|
@ -1,10 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# Due to bug 796023, we can't have -DUNICODE and -D_UNICODE; defining those
|
||||
# macros changes the type of LOGFONT to LOGFONTW instead of LOGFONTA. This
|
||||
# changes the symbol names of exported C++ functions that use LOGFONT.
|
||||
DEFINES := $(filter-out -DUNICODE -D_UNICODE,$(DEFINES))
|
@ -170,3 +170,10 @@ CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
|
||||
CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
# Due to bug 796023, we can't have -DUNICODE and -D_UNICODE; defining those
|
||||
# macros changes the type of LOGFONT to LOGFONTW instead of LOGFONTA. This
|
||||
# changes the symbol names of exported C++ functions that use LOGFONT.
|
||||
del DEFINES['UNICODE']
|
||||
del DEFINES['_UNICODE']
|
||||
|
@ -1,7 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES := $(filter-out -DUNICODE,$(DEFINES))
|
@ -157,3 +157,6 @@ CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
|
||||
CFLAGS += CONFIG['TK_CFLAGS']
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
del DEFINES['UNICODE']
|
||||
|
@ -244,7 +244,7 @@ already_AddRefed<nsIDOMWindowUtils>
|
||||
APZCCallbackHelper::GetDOMWindowUtils(const nsIContent* aContent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils;
|
||||
nsIDocument* doc = aContent->GetCurrentDoc();
|
||||
nsIDocument* doc = aContent->GetComposedDoc();
|
||||
if (doc) {
|
||||
utils = GetDOMWindowUtils(doc);
|
||||
}
|
||||
|
@ -4,7 +4,5 @@
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES := $(filter-out -DUNICODE,$(DEFINES))
|
||||
|
||||
DeprecatedPremultiplyTables.h: $(srcdir)/genTables.py
|
||||
$(PYTHON) $(srcdir)/genTables.py
|
||||
|
@ -1067,6 +1067,11 @@ gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry* aFontEntry,
|
||||
NS_ASSERTION(aFontEntry->mFamilyName.Length() != 0,
|
||||
"caching a font associated with no family yet");
|
||||
|
||||
// if caching is disabled, simply return
|
||||
if (Preferences::GetBool("gfx.downloadable_fonts.disable_cache")) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfxUserFontData* data = aFontEntry->mUserFontData;
|
||||
if (data->mIsBuffer) {
|
||||
#ifdef DEBUG_USERFONT_CACHE
|
||||
@ -1143,7 +1148,8 @@ gfxUserFontSet::UserFontCache::GetFont(nsIURI* aSrcURI,
|
||||
gfxUserFontEntry* aUserFontEntry,
|
||||
bool aPrivate)
|
||||
{
|
||||
if (!sUserFonts) {
|
||||
if (!sUserFonts ||
|
||||
Preferences::GetBool("gfx.downloadable_fonts.disable_cache")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1973,13 +1973,6 @@ public:
|
||||
mSoftwareVsyncRate = TimeDuration::FromMilliseconds(rate);
|
||||
}
|
||||
|
||||
virtual ~D3DVsyncDisplay()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DisableVsync();
|
||||
delete mVsyncThread;
|
||||
}
|
||||
|
||||
virtual void EnableVsync() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -2082,6 +2075,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~D3DVsyncDisplay()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DisableVsync();
|
||||
delete mVsyncThread;
|
||||
}
|
||||
|
||||
bool IsInVsyncThread()
|
||||
{
|
||||
return mVsyncThread->thread_id() == PlatformThread::CurrentId();
|
||||
|
@ -302,3 +302,6 @@ DEFINES['GRAPHITE2_STATIC'] = True
|
||||
|
||||
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
|
||||
DEFINES['OTS_DLL'] = True
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
del DEFINES['UNICODE']
|
||||
|
@ -22,6 +22,8 @@ ${INCLUDES}
|
||||
|
||||
using namespace std;
|
||||
|
||||
using base::Thread;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
@ -20,6 +20,9 @@ struct RunnableMethodTraits<mozilla::_ipdltest2::TestOpensOpenedChild>
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
using base::ProcessHandle;
|
||||
using base::Thread;
|
||||
|
||||
namespace mozilla {
|
||||
// NB: this is generally bad style, but I am lazy.
|
||||
using namespace _ipdltest;
|
||||
|
@ -311,6 +311,7 @@ selfhosting_srcs := \
|
||||
$(srcdir)/builtin/Map.js \
|
||||
$(srcdir)/builtin/Number.js \
|
||||
$(srcdir)/builtin/Object.js \
|
||||
$(srcdir)/builtin/RegExp.js \
|
||||
$(srcdir)/builtin/String.js \
|
||||
$(srcdir)/builtin/Set.js \
|
||||
$(srcdir)/builtin/TypedArray.js \
|
||||
|
@ -689,7 +689,10 @@ js::obj_create(JSContext *cx, unsigned argc, Value *vp)
|
||||
/* 15.2.3.5 step 4. */
|
||||
if (args.hasDefined(1)) {
|
||||
if (args[1].isPrimitive()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, args[1], NullPtr());
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -328,67 +328,6 @@ regexp_toString(JSContext *cx, unsigned argc, Value *vp)
|
||||
return CallNonGenericMethod<IsRegExp, regexp_toString_impl>(cx, args);
|
||||
}
|
||||
|
||||
/* ES6 draft rev29 21.2.5.3 RegExp.prototype.flags */
|
||||
bool
|
||||
regexp_flags(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
/* Steps 1-2. */
|
||||
if (!args.thisv().isObject()) {
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, args.thisv(), NullPtr());
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
|
||||
bytes, "not an object");
|
||||
js_free(bytes);
|
||||
return false;
|
||||
}
|
||||
RootedObject thisObj(cx, &args.thisv().toObject());
|
||||
|
||||
/* Step 3. */
|
||||
StringBuffer sb(cx);
|
||||
|
||||
/* Steps 4-6. */
|
||||
RootedValue global(cx);
|
||||
if (!GetProperty(cx, thisObj, thisObj, cx->names().global, &global))
|
||||
return false;
|
||||
if (ToBoolean(global) && !sb.append('g'))
|
||||
return false;
|
||||
|
||||
/* Steps 7-9. */
|
||||
RootedValue ignoreCase(cx);
|
||||
if (!GetProperty(cx, thisObj, thisObj, cx->names().ignoreCase, &ignoreCase))
|
||||
return false;
|
||||
if (ToBoolean(ignoreCase) && !sb.append('i'))
|
||||
return false;
|
||||
|
||||
/* Steps 10-12. */
|
||||
RootedValue multiline(cx);
|
||||
if (!GetProperty(cx, thisObj, thisObj, cx->names().multiline, &multiline))
|
||||
return false;
|
||||
if (ToBoolean(multiline) && !sb.append('m'))
|
||||
return false;
|
||||
|
||||
/* Steps 13-15. */
|
||||
RootedValue unicode(cx);
|
||||
if (!GetProperty(cx, thisObj, thisObj, cx->names().unicode, &unicode))
|
||||
return false;
|
||||
if (ToBoolean(unicode) && !sb.append('u'))
|
||||
return false;
|
||||
|
||||
/* Steps 16-18. */
|
||||
RootedValue sticky(cx);
|
||||
if (!GetProperty(cx, thisObj, thisObj, cx->names().sticky, &sticky))
|
||||
return false;
|
||||
if (ToBoolean(sticky) && !sb.append('y'))
|
||||
return false;
|
||||
|
||||
/* Step 19. */
|
||||
args.rval().setString(sb.finishString());
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ES6 draft rev32 21.2.5.4. */
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
regexp_global_impl(JSContext *cx, CallArgs args)
|
||||
@ -499,7 +438,7 @@ regexp_sticky(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
}
|
||||
|
||||
static const JSPropertySpec regexp_properties[] = {
|
||||
JS_PSG("flags", regexp_flags, 0),
|
||||
JS_SELF_HOSTED_GET("flags", "RegExpFlagsGetter", 0),
|
||||
JS_PSG("global", regexp_global, 0),
|
||||
JS_PSG("ignoreCase", regexp_ignoreCase, 0),
|
||||
JS_PSG("multiline", regexp_multiline, 0),
|
||||
|
38
js/src/builtin/RegExp.js
Normal file
38
js/src/builtin/RegExp.js
Normal file
@ -0,0 +1,38 @@
|
||||
/* 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/. */
|
||||
|
||||
// ES6 draft rev34 (2015/02/20) 21.2.5.3 get RegExp.prototype.flags
|
||||
function RegExpFlagsGetter() {
|
||||
// Steps 1-2.
|
||||
var R = this;
|
||||
if (!IsObject(R))
|
||||
ThrowError(JSMSG_NOT_NONNULL_OBJECT, R === null ? "null" : typeof R);
|
||||
|
||||
// Step 3.
|
||||
var result = "";
|
||||
|
||||
// Steps 4-6.
|
||||
if (R.global)
|
||||
result += "g";
|
||||
|
||||
// Steps 7-9.
|
||||
if (R.ignoreCase)
|
||||
result += "i";
|
||||
|
||||
// Steps 10-12.
|
||||
if (R.multiline)
|
||||
result += "m";
|
||||
|
||||
// Steps 13-15.
|
||||
// TODO: Uncomment these steps when bug 1135377 is fixed.
|
||||
// if (R.unicode)
|
||||
// result += "u";
|
||||
|
||||
// Steps 16-18.
|
||||
if (R.sticky)
|
||||
result += "y";
|
||||
|
||||
// Step 19.
|
||||
return result;
|
||||
}
|
@ -16,7 +16,7 @@ function WeakSet_add(value) {
|
||||
|
||||
// Step 5.
|
||||
if (!IsObject(value))
|
||||
ThrowError(JSMSG_NOT_NONNULL_OBJECT);
|
||||
ThrowError(JSMSG_NOT_NONNULL_OBJECT, DecompileArg(0, value));
|
||||
|
||||
// Steps 7-8.
|
||||
callFunction(std_WeakMap_set, entries, value, true);
|
||||
|
@ -123,7 +123,10 @@ WeakSetObject::construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
||||
if (isOriginalAdder) {
|
||||
if (keyVal.isPrimitive()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, NullPtr());
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -748,6 +748,7 @@ class JitCode;
|
||||
typedef PreBarriered<JSObject*> PreBarrieredObject;
|
||||
typedef PreBarriered<JSScript*> PreBarrieredScript;
|
||||
typedef PreBarriered<jit::JitCode*> PreBarrieredJitCode;
|
||||
typedef PreBarriered<JSString*> PreBarrieredString;
|
||||
typedef PreBarriered<JSAtom*> PreBarrieredAtom;
|
||||
|
||||
typedef RelocatablePtr<JSObject*> RelocatablePtrObject;
|
||||
|
@ -908,10 +908,10 @@ class GCRuntime
|
||||
void sweepBackgroundThings(ZoneList &zones, LifoAlloc &freeBlocks, ThreadType threadType);
|
||||
void assertBackgroundSweepingFinished();
|
||||
bool shouldCompact();
|
||||
IncrementalProgress compactPhase(bool lastGC);
|
||||
IncrementalProgress compactPhase(bool lastGC, JS::gcreason::Reason reason);
|
||||
void sweepTypesAfterCompacting(Zone *zone);
|
||||
void sweepZoneAfterCompacting(Zone *zone);
|
||||
ArenaHeader *relocateArenas();
|
||||
ArenaHeader *relocateArenas(JS::gcreason::Reason reason);
|
||||
void updateAllCellPointersParallel(MovingTracer *trc);
|
||||
void updateAllCellPointersSerial(MovingTracer *trc);
|
||||
void updatePointersToRelocatedCells();
|
||||
|
@ -422,7 +422,7 @@ GetObjectAllocKindForCopy(const Nursery &nursery, JSObject *obj)
|
||||
|
||||
// Unboxed plain objects are sized according to the data they store.
|
||||
if (obj->is<UnboxedPlainObject>()) {
|
||||
size_t nbytes = obj->as<UnboxedPlainObject>().layout().size();
|
||||
size_t nbytes = obj->as<UnboxedPlainObject>().layoutDontCheckGeneration().size();
|
||||
return GetGCObjectKindForBytes(UnboxedPlainObject::offsetOfData() + nbytes);
|
||||
}
|
||||
|
||||
|
19
js/src/jit-test/lib/simd.js
Normal file
19
js/src/jit-test/lib/simd.js
Normal file
@ -0,0 +1,19 @@
|
||||
function binaryX4(op, v, w) {
|
||||
var arr = [];
|
||||
var [varr, warr] = [simdToArray(v), simdToArray(w)];
|
||||
[varr, warr] = [varr.map(Math.fround), warr.map(Math.fround)];
|
||||
for (var i = 0; i < 4; i++)
|
||||
arr[i] = op(varr[i], warr[i]);
|
||||
return arr.map(Math.fround);
|
||||
}
|
||||
|
||||
function assertEqX4(vec, arr) {
|
||||
assertEq(vec.x, arr[0]);
|
||||
assertEq(vec.y, arr[1]);
|
||||
assertEq(vec.z, arr[2]);
|
||||
assertEq(vec.w, arr[3]);
|
||||
}
|
||||
|
||||
function simdToArray(vec) {
|
||||
return [vec.x, vec.y, vec.z, vec.w];
|
||||
}
|
33
js/src/jit-test/tests/SIMD/float32x4-binary-arith.js
Normal file
33
js/src/jit-test/tests/SIMD/float32x4-binary-arith.js
Normal file
@ -0,0 +1,33 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function maxNum(x, y) {
|
||||
if (x != x)
|
||||
return y;
|
||||
if (y != y)
|
||||
return x;
|
||||
return Math.max(x, y);
|
||||
}
|
||||
|
||||
function minNum(x, y) {
|
||||
if (x != x)
|
||||
return y;
|
||||
if (y != y)
|
||||
return x;
|
||||
return Math.min(x, y);
|
||||
}
|
||||
|
||||
function f() {
|
||||
var f1 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.float32x4(4, 3, 2, 1);
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.float32x4.div(f1, f2), binaryX4((x, y) => x / y, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.min(f1, f2), binaryX4(Math.min, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.max(f1, f2), binaryX4(Math.max, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.minNum(f1, f2), binaryX4(minNum, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.maxNum(f1, f2), binaryX4(maxNum, f1, f2));
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
40
js/src/jit-test/tests/SIMD/float32x4-binary-bitwise.js
Normal file
40
js/src/jit-test/tests/SIMD/float32x4-binary-bitwise.js
Normal file
@ -0,0 +1,40 @@
|
||||
load(libdir + "simd.js");
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
var helpers = (function() {
|
||||
var i32 = new Int32Array(2);
|
||||
var f32 = new Float32Array(i32.buffer);
|
||||
return {
|
||||
and: function(x, y) {
|
||||
f32[0] = x;
|
||||
f32[1] = y;
|
||||
i32[0] = i32[0] & i32[1];
|
||||
return f32[0];
|
||||
},
|
||||
or: function(x, y) {
|
||||
f32[0] = x;
|
||||
f32[1] = y;
|
||||
i32[0] = i32[0] | i32[1];
|
||||
return f32[0];
|
||||
},
|
||||
xor: function(x, y) {
|
||||
f32[0] = x;
|
||||
f32[1] = y;
|
||||
i32[0] = i32[0] ^ i32[1];
|
||||
return f32[0];
|
||||
},
|
||||
}
|
||||
})();
|
||||
|
||||
function f() {
|
||||
var f1 = SIMD.float32x4(1, 2, 3, 4);
|
||||
var f2 = SIMD.float32x4(4, 3, 2, 1);
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.float32x4.and(f1, f2), binaryX4(helpers.and, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.or(f1, f2), binaryX4(helpers.or, f1, f2));
|
||||
assertEqX4(SIMD.float32x4.xor(f1, f2), binaryX4(helpers.xor, f1, f2));
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
18
js/src/jit-test/tests/basic/array-proto-outofrange.js
Normal file
18
js/src/jit-test/tests/basic/array-proto-outofrange.js
Normal file
@ -0,0 +1,18 @@
|
||||
function f(obj) {
|
||||
return typeof obj[15];
|
||||
}
|
||||
|
||||
function test() {
|
||||
var a = [1, 2];
|
||||
a.__proto__ = {15: 1337};
|
||||
var b = [1, 2, 3, 4];
|
||||
|
||||
for (var i = 0; i < 1000; i++) {
|
||||
var r = f(i % 2 ? a : b);
|
||||
assertEq(r, i % 2 ? "number" : "undefined");
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
test();
|
||||
test();
|
10
js/src/jit-test/tests/basic/bug1134146.js
Normal file
10
js/src/jit-test/tests/basic/bug1134146.js
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
function Foo(a, b) {
|
||||
b = {};
|
||||
this.b = b;
|
||||
};
|
||||
var a = [];
|
||||
for (var i = 0; i < 50; i++)
|
||||
a.push(new Foo(i, i + 1));
|
||||
i = 0;
|
||||
a[i].c = i;
|
28
js/src/jit-test/tests/basic/dense-elements-appear.js
Normal file
28
js/src/jit-test/tests/basic/dense-elements-appear.js
Normal file
@ -0,0 +1,28 @@
|
||||
function f() {
|
||||
var x = [1, 2, 3];
|
||||
var y = {};
|
||||
x.__proto__ = y;
|
||||
|
||||
for (var i = 0; i < 200; i++) {
|
||||
if (i == 100)
|
||||
y[100000] = 15;
|
||||
else
|
||||
assertEq(typeof x[100000], i > 100 ? "number" : "undefined");
|
||||
}
|
||||
}
|
||||
|
||||
function g() {
|
||||
var x = [1, 2, 3];
|
||||
var y = {};
|
||||
x.__proto__ = y;
|
||||
|
||||
for (var i = 0; i < 200; i++) {
|
||||
if (i == 100)
|
||||
y[4] = 15;
|
||||
else
|
||||
assertEq(typeof x[4], i > 100 ? "number" : "undefined");
|
||||
}
|
||||
}
|
||||
|
||||
f();
|
||||
g();
|
@ -107,6 +107,7 @@ check("o[~(o)]");
|
||||
check("o[+ (o)]");
|
||||
check("o[- (o)]");
|
||||
|
||||
|
||||
// A few one off tests
|
||||
check_one("6", (function () { 6() }), " is not a function");
|
||||
check_one("Array.prototype.reverse.call(...)", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
|
||||
@ -114,6 +115,8 @@ check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
|
||||
function () { var [{ x }] = [null, {}]; }, " is null");
|
||||
check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
|
||||
function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined");
|
||||
check_one("void 1", function() { (void 1)(); }, " is not a function");
|
||||
check_one("void o[1]", function() { var o = []; (void o[1])() }, " is not a function");
|
||||
|
||||
// Check fallback behavior
|
||||
assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError);
|
||||
|
@ -9167,6 +9167,16 @@ GetTemplateObjectForNative(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
return !!res;
|
||||
}
|
||||
#undef ADD_INT32X4_SIMD_OP_NAME_
|
||||
#define ADD_FLOAT32X4_SIMD_OP_NAME_(OP) || native == js::simd_float32x4_##OP
|
||||
if (false
|
||||
ARITH_FLOAT32X4_SIMD_OP(ADD_FLOAT32X4_SIMD_OP_NAME_)
|
||||
BITWISE_COMMONX4_SIMD_OP(ADD_FLOAT32X4_SIMD_OP_NAME_))
|
||||
{
|
||||
Rooted<SimdTypeDescr *> descr(cx, &cx->global()->float32x4TypeDescr().as<SimdTypeDescr>());
|
||||
res.set(cx->compartment()->jitCompartment()->getSimdTemplateObjectFor(cx, descr));
|
||||
return !!res;
|
||||
}
|
||||
#undef ADD_FLOAT32X4_SIMD_OP_NAME_
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -805,10 +805,10 @@ class IonBuilder
|
||||
|
||||
// SIMD intrinsics and natives.
|
||||
InliningStatus inlineConstructSimdObject(CallInfo &callInfo, SimdTypeDescr *target);
|
||||
InliningStatus inlineSimdInt32x4BinaryArith(CallInfo &callInfo, JSNative native,
|
||||
MSimdBinaryArith::Operation op);
|
||||
InliningStatus inlineSimdInt32x4BinaryBitwise(CallInfo &callInfo, JSNative native,
|
||||
MSimdBinaryBitwise::Operation op);
|
||||
|
||||
template <typename T>
|
||||
InliningStatus inlineBinarySimd(CallInfo &callInfo, JSNative native,
|
||||
typename T::Operation op, SimdTypeDescr::Type type);
|
||||
|
||||
// Utility intrinsics.
|
||||
InliningStatus inlineIsCallable(CallInfo &callInfo);
|
||||
|
@ -3258,6 +3258,160 @@ GetElementIC::attachDenseElement(JSContext *cx, HandleScript outerScript, IonScr
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "dense array");
|
||||
}
|
||||
|
||||
|
||||
/* static */ bool
|
||||
GetElementIC::canAttachDenseElementHole(JSObject *obj, const Value &idval, TypedOrValueRegister output)
|
||||
{
|
||||
if (!idval.isInt32())
|
||||
return false;
|
||||
|
||||
if (!output.hasValue())
|
||||
return false;
|
||||
|
||||
if (!obj->isNative())
|
||||
return false;
|
||||
|
||||
if (obj->as<NativeObject>().getDenseInitializedLength() == 0)
|
||||
return false;
|
||||
|
||||
while (obj) {
|
||||
if (obj->isIndexed())
|
||||
return false;
|
||||
|
||||
if (ClassCanHaveExtraProperties(obj->getClass()))
|
||||
return false;
|
||||
|
||||
JSObject *proto = obj->getProto();
|
||||
if (!proto)
|
||||
break;
|
||||
|
||||
if (!proto->isNative())
|
||||
return false;
|
||||
|
||||
// Make sure objects on the prototype don't have dense elements.
|
||||
if (proto->as<NativeObject>().getDenseInitializedLength() != 0)
|
||||
return false;
|
||||
|
||||
obj = proto;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GenerateDenseElementHole(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
IonScript *ion, JSObject *obj, const Value &idval,
|
||||
Register object, ConstantOrRegister index, TypedOrValueRegister output)
|
||||
{
|
||||
MOZ_ASSERT(GetElementIC::canAttachDenseElementHole(obj, idval, output));
|
||||
MOZ_ASSERT(obj->lastProperty());
|
||||
|
||||
Register scratchReg = output.valueReg().scratchReg();
|
||||
|
||||
// Guard on the shape and group, to prevent non-dense elements from appearing.
|
||||
Label failures;
|
||||
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
|
||||
Address(object, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(obj->lastProperty()), &failures);
|
||||
|
||||
|
||||
if (obj->hasUncacheableProto()) {
|
||||
masm.loadPtr(Address(object, JSObject::offsetOfGroup()), scratchReg);
|
||||
Address proto(scratchReg, ObjectGroup::offsetOfProto());
|
||||
masm.branchPtr(Assembler::NotEqual, proto,
|
||||
ImmMaybeNurseryPtr(obj->getProto()), &failures);
|
||||
}
|
||||
|
||||
JSObject *pobj = obj->getProto();
|
||||
while (pobj) {
|
||||
MOZ_ASSERT(pobj->lastProperty());
|
||||
|
||||
masm.movePtr(ImmMaybeNurseryPtr(pobj), scratchReg);
|
||||
if (pobj->hasUncacheableProto()) {
|
||||
MOZ_ASSERT(!pobj->isSingleton());
|
||||
Address groupAddr(scratchReg, JSObject::offsetOfGroup());
|
||||
masm.branchPtr(Assembler::NotEqual, groupAddr, ImmGCPtr(pobj->group()), &failures);
|
||||
}
|
||||
|
||||
// Make sure the shape matches, to avoid non-dense elements.
|
||||
masm.branchPtr(Assembler::NotEqual, Address(scratchReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(pobj->lastProperty()), &failures);
|
||||
|
||||
// Load elements vector.
|
||||
masm.loadPtr(Address(scratchReg, NativeObject::offsetOfElements()), scratchReg);
|
||||
|
||||
// Also make sure there are no dense elements.
|
||||
Label hole;
|
||||
Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength());
|
||||
masm.branch32(Assembler::NotEqual, initLength, Imm32(0), &failures);
|
||||
|
||||
pobj = pobj->getProto();
|
||||
}
|
||||
|
||||
// Ensure the index is an int32 value.
|
||||
Register indexReg = InvalidReg;
|
||||
Register elementsReg = InvalidReg;
|
||||
|
||||
if (index.reg().hasValue()) {
|
||||
indexReg = scratchReg;
|
||||
MOZ_ASSERT(indexReg != InvalidReg);
|
||||
ValueOperand val = index.reg().valueReg();
|
||||
|
||||
masm.branchTestInt32(Assembler::NotEqual, val, &failures);
|
||||
|
||||
// Unbox the index.
|
||||
masm.unboxInt32(val, indexReg);
|
||||
|
||||
// Save the object register.
|
||||
masm.push(object);
|
||||
elementsReg = object;
|
||||
} else {
|
||||
MOZ_ASSERT(!index.reg().typedReg().isFloat());
|
||||
indexReg = index.reg().typedReg().gpr();
|
||||
elementsReg = scratchReg;
|
||||
}
|
||||
|
||||
// Load elements vector.
|
||||
masm.loadPtr(Address(object, NativeObject::offsetOfElements()), elementsReg);
|
||||
|
||||
// Guard on the initialized length.
|
||||
Label hole;
|
||||
Address initLength(elementsReg, ObjectElements::offsetOfInitializedLength());
|
||||
masm.branch32(Assembler::BelowOrEqual, initLength, indexReg, &hole);
|
||||
|
||||
// Load the value.
|
||||
Label done;
|
||||
masm.loadValue(BaseObjectElementIndex(elementsReg, indexReg), output.valueReg());
|
||||
masm.branchTestMagic(Assembler::NotEqual, output.valueReg(), &done);
|
||||
|
||||
// Load undefined for the hole.
|
||||
masm.bind(&hole);
|
||||
masm.moveValue(UndefinedValue(), output.valueReg());
|
||||
|
||||
masm.bind(&done);
|
||||
// Restore the object register.
|
||||
if (elementsReg == object)
|
||||
masm.pop(object);
|
||||
attacher.jumpRejoin(masm);
|
||||
|
||||
// All failure flows through here.
|
||||
masm.bind(&failures);
|
||||
attacher.jumpNextStub(masm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetElementIC::attachDenseElementHole(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval)
|
||||
{
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateDenseElementHole(cx, masm, attacher, ion, obj, idval, object(), index(), output());
|
||||
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "dense hole");
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
GetElementIC::canAttachTypedArrayElement(JSObject *obj, const Value &idval,
|
||||
TypedOrValueRegister output)
|
||||
@ -3568,6 +3722,13 @@ GetElementIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex,
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
if (!attachedStub && cache.monitoredResult() &&
|
||||
canAttachDenseElementHole(obj, idval, cache.output()))
|
||||
{
|
||||
if (!cache.attachDenseElementHole(cx, outerScript, ion, obj, idval))
|
||||
return false;
|
||||
attachedStub = true;
|
||||
}
|
||||
if (!attachedStub && canAttachTypedArrayElement(obj, idval, cache.output())) {
|
||||
if (!cache.attachTypedArrayElement(cx, outerScript, ion, obj, idval))
|
||||
return false;
|
||||
|
@ -842,6 +842,8 @@ class GetElementIC : public RepatchIonCache
|
||||
|
||||
static bool canAttachGetProp(JSObject *obj, const Value &idval, jsid id);
|
||||
static bool canAttachDenseElement(JSObject *obj, const Value &idval);
|
||||
static bool canAttachDenseElementHole(JSObject *obj, const Value &idval,
|
||||
TypedOrValueRegister output);
|
||||
static bool canAttachTypedArrayElement(JSObject *obj, const Value &idval,
|
||||
TypedOrValueRegister output);
|
||||
|
||||
@ -851,6 +853,9 @@ class GetElementIC : public RepatchIonCache
|
||||
bool attachDenseElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval);
|
||||
|
||||
bool attachDenseElementHole(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, const Value &idval);
|
||||
|
||||
bool attachTypedArrayElement(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject tarr, const Value &idval);
|
||||
|
||||
|
@ -520,6 +520,9 @@ class LSimdBinaryBitwiseX4 : public LInstructionHelper<1, 2, 0>
|
||||
MSimdBinaryBitwise::Operation operation() const {
|
||||
return mir_->toSimdBinaryBitwise()->operation();
|
||||
}
|
||||
const char *extraName() const {
|
||||
return MSimdBinaryBitwise::OperationName(operation());
|
||||
}
|
||||
MIRType type() const {
|
||||
return mir_->type();
|
||||
}
|
||||
|
@ -257,17 +257,29 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target)
|
||||
return inlineBoundFunction(callInfo, target);
|
||||
|
||||
// Simd functions
|
||||
#define INLINE_INT32X4_SIMD_ARITH_(OP) \
|
||||
if (native == js::simd_int32x4_##OP) \
|
||||
return inlineSimdInt32x4BinaryArith(callInfo, native, MSimdBinaryArith::Op_##OP);
|
||||
#define INLINE_INT32X4_SIMD_ARITH_(OP) \
|
||||
if (native == js::simd_int32x4_##OP) \
|
||||
return inlineBinarySimd<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_##OP, \
|
||||
SimdTypeDescr::TYPE_INT32);
|
||||
ARITH_COMMONX4_SIMD_OP(INLINE_INT32X4_SIMD_ARITH_)
|
||||
#undef INLINE_INT32X4_SIMD_ARITH_
|
||||
|
||||
#define INLINE_INT32X4_SIMD_BITWISE_(OP) \
|
||||
if (native == js::simd_int32x4_##OP) \
|
||||
return inlineSimdInt32x4BinaryBitwise(callInfo, native, MSimdBinaryBitwise::OP##_);
|
||||
BITWISE_COMMONX4_SIMD_OP(INLINE_INT32X4_SIMD_BITWISE_)
|
||||
#undef INLINE_INT32X4_SIMD_BITWISE_
|
||||
#define INLINE_FLOAT32X4_SIMD_ARITH_(OP) \
|
||||
if (native == js::simd_float32x4_##OP) \
|
||||
return inlineBinarySimd<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_##OP, \
|
||||
SimdTypeDescr::TYPE_FLOAT32);
|
||||
ARITH_FLOAT32X4_SIMD_OP(INLINE_FLOAT32X4_SIMD_ARITH_)
|
||||
#undef INLINE_FLOAT32X4_SIMD_ARITH_
|
||||
|
||||
#define INLINE_SIMD_BITWISE_(OP) \
|
||||
if (native == js::simd_int32x4_##OP) \
|
||||
return inlineBinarySimd<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::OP##_, \
|
||||
SimdTypeDescr::TYPE_INT32); \
|
||||
if (native == js::simd_float32x4_##OP) \
|
||||
return inlineBinarySimd<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::OP##_, \
|
||||
SimdTypeDescr::TYPE_FLOAT32);
|
||||
BITWISE_COMMONX4_SIMD_OP(INLINE_SIMD_BITWISE_)
|
||||
#undef INLINE_SIMD_BITWISE_
|
||||
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@ -2860,41 +2872,21 @@ IonBuilder::inlineConstructSimdObject(CallInfo &callInfo, SimdTypeDescr *descr)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdInt32x4BinaryArith(CallInfo &callInfo, JSNative native,
|
||||
MSimdBinaryArith::Operation op)
|
||||
static MIRType
|
||||
SimdTypeDescrToMIRType(SimdTypeDescr::Type type)
|
||||
{
|
||||
if (callInfo.argc() != 2)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
JSObject *templateObject = inspector->getTemplateObjectForNative(pc, native);
|
||||
if (!templateObject)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
InlineTypedObject *inlineTypedObject = &templateObject->as<InlineTypedObject>();
|
||||
MOZ_ASSERT(inlineTypedObject->typeDescr().as<SimdTypeDescr>().type() == js::Int32x4::type);
|
||||
|
||||
// If the type of any of the arguments is neither a SIMD type, an Object
|
||||
// type, or a Value, then the applyTypes phase will add a fallible box &
|
||||
// unbox sequence. This does not matter much as the binary arithmetic
|
||||
// instruction is supposed to produce a TypeError once it is called.
|
||||
MSimdBinaryArith *ins = MSimdBinaryArith::New(alloc(), callInfo.getArg(0), callInfo.getArg(1),
|
||||
op, MIRType_Int32x4);
|
||||
|
||||
MSimdBox *obj = MSimdBox::New(alloc(), constraints(), ins, inlineTypedObject,
|
||||
inlineTypedObject->group()->initialHeap(constraints()));
|
||||
|
||||
current->add(ins);
|
||||
current->add(obj);
|
||||
current->push(obj);
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
return InliningStatus_Inlined;
|
||||
switch (type) {
|
||||
case SimdTypeDescr::TYPE_FLOAT32: return MIRType_Float32x4;
|
||||
case SimdTypeDescr::TYPE_INT32: return MIRType_Int32x4;
|
||||
case SimdTypeDescr::TYPE_FLOAT64: break;
|
||||
}
|
||||
MOZ_CRASH("unexpected SimdTypeDescr");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdInt32x4BinaryBitwise(CallInfo &callInfo, JSNative native,
|
||||
MSimdBinaryBitwise::Operation op)
|
||||
IonBuilder::inlineBinarySimd(CallInfo &callInfo, JSNative native, typename T::Operation op,
|
||||
SimdTypeDescr::Type type)
|
||||
{
|
||||
if (callInfo.argc() != 2)
|
||||
return InliningStatus_NotInlined;
|
||||
@ -2904,14 +2896,14 @@ IonBuilder::inlineSimdInt32x4BinaryBitwise(CallInfo &callInfo, JSNative native,
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
InlineTypedObject *inlineTypedObject = &templateObject->as<InlineTypedObject>();
|
||||
MOZ_ASSERT(inlineTypedObject->typeDescr().as<SimdTypeDescr>().type() == js::Int32x4::type);
|
||||
MOZ_ASSERT(inlineTypedObject->typeDescr().as<SimdTypeDescr>().type() == type);
|
||||
|
||||
// If the type of any of the arguments is neither a SIMD type, an Object
|
||||
// type, or a Value, then the applyTypes phase will add a fallible box &
|
||||
// unbox sequence. This does not matter much as the binary bitwise
|
||||
// instruction is supposed to produce a TypeError once it is called.
|
||||
MSimdBinaryBitwise *ins = MSimdBinaryBitwise::New(alloc(), callInfo.getArg(0), callInfo.getArg(1),
|
||||
op, MIRType_Int32x4);
|
||||
T *ins = T::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), op,
|
||||
SimdTypeDescrToMIRType(type));
|
||||
|
||||
MSimdBox *obj = MSimdBox::New(alloc(), constraints(), ins, inlineTypedObject,
|
||||
inlineTypedObject->group()->initialHeap(constraints()));
|
||||
|
@ -2036,6 +2036,15 @@ class MSimdBinaryBitwise
|
||||
xor_
|
||||
};
|
||||
|
||||
static const char* OperationName(Operation op) {
|
||||
switch (op) {
|
||||
case and_: return "and";
|
||||
case or_: return "or";
|
||||
case xor_: return "xor";
|
||||
}
|
||||
MOZ_CRASH("unexpected operation");
|
||||
}
|
||||
|
||||
private:
|
||||
Operation operation_;
|
||||
|
||||
|
@ -80,7 +80,7 @@ MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 1, JSEXN_TYPEERR, "yield from closing gen
|
||||
MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
|
||||
MSG_DEF(JSMSG_UNEXPECTED_TYPE, 2, JSEXN_TYPEERR, "{0} is {1}")
|
||||
MSG_DEF(JSMSG_MISSING_FUN_ARG, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}")
|
||||
MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 0, JSEXN_TYPEERR, "value is not a non-null object")
|
||||
MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 1, JSEXN_TYPEERR, "{0} is not a non-null object")
|
||||
MSG_DEF(JSMSG_INVALID_DESCRIPTOR, 0, JSEXN_TYPEERR, "property descriptors must not specify a value or be writable when a getter or setter has been specified")
|
||||
MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1, JSEXN_TYPEERR, "{0} is not extensible")
|
||||
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property '{0}'")
|
||||
|
@ -2145,7 +2145,7 @@ inline int CheckIsStrictPropertyOp(JSStrictPropertyOp op);
|
||||
#define JS_SELF_HOSTED_GET(name, getterName, flags) \
|
||||
{name, \
|
||||
uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
|
||||
{ nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo *) }, \
|
||||
{ { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo *) } }, \
|
||||
JSNATIVE_WRAPPER(nullptr) }
|
||||
#define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
|
||||
{name, \
|
||||
|
@ -495,14 +495,14 @@ JSCompartment::wrap(JSContext *cx, MutableHandle<PropDesc> desc)
|
||||
}
|
||||
|
||||
/*
|
||||
* This method marks pointers that cross compartment boundaries. It should be
|
||||
* called only for per-compartment GCs, since full GCs naturally follow pointers
|
||||
* across compartments.
|
||||
* This method marks pointers that cross compartment boundaries. It is called in
|
||||
* per-zone GCs (since full GCs naturally follow pointers across compartments)
|
||||
* and when compacting to update cross-compartment pointers.
|
||||
*/
|
||||
void
|
||||
JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
|
||||
{
|
||||
MOZ_ASSERT(!zone()->isCollecting());
|
||||
MOZ_ASSERT(!zone()->isCollecting() || trc->runtime()->isHeapCompacting());
|
||||
|
||||
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
|
||||
Value v = e.front().value();
|
||||
|
191
js/src/jsgc.cpp
191
js/src/jsgc.cpp
@ -1952,7 +1952,7 @@ size_t ArenaHeader::countUsedCells()
|
||||
}
|
||||
|
||||
ArenaHeader *
|
||||
ArenaList::removeRemainingArenas(ArenaHeader **arenap, const AutoLockGC &lock)
|
||||
ArenaList::removeRemainingArenas(ArenaHeader **arenap)
|
||||
{
|
||||
// This is only ever called to remove arenas that are after the cursor, so
|
||||
// we don't need to update it.
|
||||
@ -1966,53 +1966,52 @@ ArenaList::removeRemainingArenas(ArenaHeader **arenap, const AutoLockGC &lock)
|
||||
return remainingArenas;
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose which arenas to relocate all cells out of and remove them from the
|
||||
* arena list. Return the head of a list of arenas to relocate.
|
||||
*/
|
||||
ArenaHeader *
|
||||
ArenaList::pickArenasToRelocate(JSRuntime *runtime)
|
||||
static bool
|
||||
ShouldRelocateAllArenas(JSRuntime *runtime)
|
||||
{
|
||||
AutoLockGC lock(runtime);
|
||||
|
||||
check();
|
||||
if (isEmpty())
|
||||
return nullptr;
|
||||
|
||||
// In zeal mode and in debug builds on 64 bit architectures, we relocate all
|
||||
// arenas. The purpose of this is to balance test coverage of object moving
|
||||
// with test coverage of the arena selection routine below.
|
||||
bool relocateAll = runtime->gc.zeal() == ZealCompactValue;
|
||||
// In compacting zeal mode and in debug builds on 64 bit architectures, we
|
||||
// relocate all arenas. The purpose of this is to balance test coverage of
|
||||
// object moving with test coverage of the arena selection routine in
|
||||
// pickArenasToRelocate().
|
||||
#if defined(DEBUG) && defined(JS_PUNBOX64)
|
||||
relocateAll = true;
|
||||
return true;
|
||||
#else
|
||||
return runtime->gc.zeal() == ZealCompactValue;
|
||||
#endif
|
||||
if (relocateAll) {
|
||||
ArenaHeader *allArenas = head();
|
||||
clear();
|
||||
return allArenas;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise we relocate the greatest number of arenas such that the number
|
||||
// of used cells in relocated arenas is less than or equal to the number of
|
||||
// free cells in unrelocated arenas. In other words we only relocate cells
|
||||
// we can move into existing arenas, and we choose the least full areans to
|
||||
// relocate.
|
||||
/*
|
||||
* Choose which arenas to relocate all cells from. Return an arena cursor that
|
||||
* can be passed to removeRemainingArenas().
|
||||
*/
|
||||
ArenaHeader **
|
||||
ArenaList::pickArenasToRelocate(size_t &arenaTotalOut, size_t &relocTotalOut)
|
||||
{
|
||||
// Relocate the greatest number of arenas such that the number of used cells
|
||||
// in relocated arenas is less than or equal to the number of free cells in
|
||||
// unrelocated arenas. In other words we only relocate cells we can move
|
||||
// into existing arenas, and we choose the least full areans to relocate.
|
||||
//
|
||||
// This is made easier by the fact that the arena list has been sorted in
|
||||
// descending order of number of used cells, so we will always relocate a
|
||||
// tail of the arena list. All we need to do is find the point at which to
|
||||
// start relocating.
|
||||
|
||||
check();
|
||||
|
||||
if (isCursorAtEnd())
|
||||
return nullptr;
|
||||
|
||||
ArenaHeader **arenap = cursorp_; // Next arena to consider
|
||||
size_t previousFreeCells = 0; // Count of free cells before
|
||||
size_t followingUsedCells = 0; // Count of used cells after arenap.
|
||||
size_t arenaCount = 0; // Total number of arenas.
|
||||
size_t arenaIndex = 0; // Index of the next arena to consider.
|
||||
|
||||
// Count of used cells after arenap.
|
||||
size_t followingUsedCells = 0;
|
||||
for (ArenaHeader *arena = *arenap; arena; arena = arena->next)
|
||||
for (ArenaHeader *arena = *cursorp_; arena; arena = arena->next) {
|
||||
followingUsedCells += arena->countUsedCells();
|
||||
arenaCount++;
|
||||
}
|
||||
|
||||
mozilla::DebugOnly<size_t> lastFreeCells(0);
|
||||
size_t cellsPerArena = Arena::thingsPerArena((*arenap)->getThingSize());
|
||||
@ -2020,7 +2019,8 @@ ArenaList::pickArenasToRelocate(JSRuntime *runtime)
|
||||
while (*arenap) {
|
||||
ArenaHeader *arena = *arenap;
|
||||
if (followingUsedCells <= previousFreeCells)
|
||||
return removeRemainingArenas(arenap, lock);
|
||||
break;
|
||||
|
||||
size_t freeCells = arena->countFreeCells();
|
||||
size_t usedCells = cellsPerArena - freeCells;
|
||||
followingUsedCells -= usedCells;
|
||||
@ -2030,10 +2030,16 @@ ArenaList::pickArenasToRelocate(JSRuntime *runtime)
|
||||
#endif
|
||||
previousFreeCells += freeCells;
|
||||
arenap = &arena->next;
|
||||
arenaIndex++;
|
||||
}
|
||||
|
||||
check();
|
||||
return nullptr;
|
||||
size_t relocCount = arenaCount - arenaIndex;
|
||||
MOZ_ASSERT(relocCount < arenaCount);
|
||||
MOZ_ASSERT((relocCount == 0) == (!*arenap));
|
||||
arenaTotalOut += arenaCount;
|
||||
relocTotalOut += relocCount;
|
||||
|
||||
return arenap;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -2148,36 +2154,79 @@ ArenaList::relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated,
|
||||
return relocated;
|
||||
}
|
||||
|
||||
ArenaHeader *
|
||||
ArenaLists::relocateArenas(ArenaHeader *relocatedList, gcstats::Statistics& stats)
|
||||
// Skip compacting zones unless we can free a certain proportion of their GC
|
||||
// heap memory.
|
||||
static const double MIN_ZONE_RECLAIM_PERCENT = 2.0;
|
||||
|
||||
static bool ShouldRelocateZone(size_t arenaCount, size_t relocCount, JS::gcreason::Reason reason)
|
||||
{
|
||||
if (relocCount == 0)
|
||||
return false;
|
||||
|
||||
if (reason == JS::gcreason::MEM_PRESSURE || reason == JS::gcreason::LAST_DITCH)
|
||||
return true;
|
||||
|
||||
return (relocCount * 100.0) / arenaCount >= MIN_ZONE_RECLAIM_PERCENT;
|
||||
}
|
||||
|
||||
bool
|
||||
ArenaLists::relocateArenas(ArenaHeader *&relocatedListOut, JS::gcreason::Reason reason,
|
||||
gcstats::Statistics& stats)
|
||||
{
|
||||
|
||||
// This is only called from the main thread while we are doing a GC, so
|
||||
// there is no need to lock.
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(runtime_));
|
||||
MOZ_ASSERT(runtime_->isHeapCompacting());
|
||||
MOZ_ASSERT(!runtime_->gc.isBackgroundSweeping());
|
||||
|
||||
// Flush all the freeLists back into the arena headers
|
||||
purge();
|
||||
checkEmptyFreeLists();
|
||||
|
||||
for (size_t i = 0; i < FINALIZE_LIMIT; i++) {
|
||||
if (CanRelocateAllocKind(AllocKind(i))) {
|
||||
ArenaList &al = arenaLists[i];
|
||||
ArenaHeader *toRelocate = al.pickArenasToRelocate(runtime_);
|
||||
if (toRelocate)
|
||||
relocatedList = al.relocateArenas(toRelocate, relocatedList, stats);
|
||||
if (ShouldRelocateAllArenas(runtime_)) {
|
||||
for (size_t i = 0; i < FINALIZE_LIMIT; i++) {
|
||||
if (CanRelocateAllocKind(AllocKind(i))) {
|
||||
ArenaList &al = arenaLists[i];
|
||||
ArenaHeader *allArenas = al.head();
|
||||
al.clear();
|
||||
relocatedListOut = al.relocateArenas(allArenas, relocatedListOut, stats);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
size_t arenaCount = 0;
|
||||
size_t relocCount = 0;
|
||||
ArenaHeader **toRelocate[FINALIZE_LIMIT] = {nullptr};
|
||||
|
||||
for (size_t i = 0; i < FINALIZE_LIMIT; i++) {
|
||||
if (CanRelocateAllocKind(AllocKind(i)))
|
||||
toRelocate[i] = arenaLists[i].pickArenasToRelocate(arenaCount, relocCount);
|
||||
}
|
||||
|
||||
if (!ShouldRelocateZone(arenaCount, relocCount, reason))
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < FINALIZE_LIMIT; i++) {
|
||||
if (toRelocate[i]) {
|
||||
ArenaList &al = arenaLists[i];
|
||||
ArenaHeader *arenas = al.removeRemainingArenas(toRelocate[i]);
|
||||
relocatedListOut = al.relocateArenas(arenas, relocatedListOut, stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When we allocate new locations for cells, we use
|
||||
* allocateFromFreeList(). Reset the free list again so that
|
||||
* AutoCopyFreeListToArenasForGC doesn't complain that the free lists
|
||||
* are different now.
|
||||
*/
|
||||
// When we allocate new locations for cells, we use
|
||||
// allocateFromFreeList(). Reset the free list again so that
|
||||
// AutoCopyFreeListToArenasForGC doesn't complain that the free lists are
|
||||
// different now.
|
||||
purge();
|
||||
checkEmptyFreeLists();
|
||||
|
||||
return relocatedList;
|
||||
return true;
|
||||
}
|
||||
|
||||
ArenaHeader *
|
||||
GCRuntime::relocateArenas()
|
||||
GCRuntime::relocateArenas(JS::gcreason::Reason reason)
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT_MOVE);
|
||||
|
||||
@ -2187,9 +2236,9 @@ GCRuntime::relocateArenas()
|
||||
MOZ_ASSERT(!zone->isPreservingCode());
|
||||
|
||||
if (CanRelocateZone(rt, zone)) {
|
||||
zone->setGCState(Zone::Compact);
|
||||
jit::StopAllOffThreadCompilations(zone);
|
||||
relocatedList = zone->arenas.relocateArenas(relocatedList, stats);
|
||||
if (zone->arenas.relocateArenas(relocatedList, reason, stats))
|
||||
zone->setGCState(Zone::Compact);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2244,7 +2293,6 @@ GCRuntime::sweepZoneAfterCompacting(Zone *zone)
|
||||
|
||||
for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
|
||||
c->sweepInnerViews();
|
||||
c->sweepCrossCompartmentWrappers();
|
||||
c->sweepBaseShapeTable();
|
||||
c->sweepInitialShapeTable();
|
||||
c->objectGroups.sweep(fop);
|
||||
@ -2389,14 +2437,16 @@ ArenasToUpdate::next(AutoLockHelperThreadState& lock)
|
||||
|
||||
initialized = true;
|
||||
for (; !zone.done(); zone.next()) {
|
||||
for (kind = 0; kind < FINALIZE_LIMIT; ++kind) {
|
||||
if (shouldProcessKind(kind)) {
|
||||
for (arena = zone.get()->arenas.getFirstArena(AllocKind(kind));
|
||||
arena;
|
||||
arena = arena->next)
|
||||
{
|
||||
return arena;
|
||||
resumePoint:;
|
||||
if (zone->isGCCompacting()) {
|
||||
for (kind = 0; kind < FINALIZE_LIMIT; ++kind) {
|
||||
if (shouldProcessKind(kind)) {
|
||||
for (arena = zone.get()->arenas.getFirstArena(AllocKind(kind));
|
||||
arena;
|
||||
arena = arena->next)
|
||||
{
|
||||
return arena;
|
||||
resumePoint:;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2560,8 +2610,10 @@ GCRuntime::updatePointersToRelocatedCells()
|
||||
comp->fixupAfterMovingGC();
|
||||
|
||||
// Fixup cross compartment wrappers as we assert the existence of wrappers in the map.
|
||||
for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next())
|
||||
for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) {
|
||||
comp->sweepCrossCompartmentWrappers();
|
||||
comp->markCrossCompartmentWrappers(&trc);
|
||||
}
|
||||
|
||||
// Iterate through all cells that can contain JSObject pointers to update
|
||||
// them. Since updating each cell is independent we try to parallelize this
|
||||
@ -2595,7 +2647,7 @@ GCRuntime::updatePointersToRelocatedCells()
|
||||
WatchpointMap::sweepAll(rt);
|
||||
Debugger::sweepAll(rt->defaultFreeOp());
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (CanRelocateZone(rt, zone))
|
||||
if (zone->isGCCompacting())
|
||||
rt->gc.sweepZoneAfterCompacting(zone);
|
||||
}
|
||||
|
||||
@ -5419,7 +5471,7 @@ GCRuntime::endSweepPhase(bool lastGC)
|
||||
}
|
||||
|
||||
GCRuntime::IncrementalProgress
|
||||
GCRuntime::compactPhase(bool lastGC)
|
||||
GCRuntime::compactPhase(bool lastGC, JS::gcreason::Reason reason)
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_COMPACT);
|
||||
|
||||
@ -5435,8 +5487,9 @@ GCRuntime::compactPhase(bool lastGC)
|
||||
MOZ_ASSERT(rt->gc.nursery.isEmpty());
|
||||
assertBackgroundSweepingFinished();
|
||||
|
||||
ArenaHeader *relocatedList = relocateArenas();
|
||||
updatePointersToRelocatedCells();
|
||||
ArenaHeader *relocatedList = relocateArenas(reason);
|
||||
if (relocatedList)
|
||||
updatePointersToRelocatedCells();
|
||||
|
||||
#ifdef DEBUG
|
||||
for (ArenaHeader *arena = relocatedList; arena; arena = arena->next) {
|
||||
@ -5470,7 +5523,7 @@ GCRuntime::compactPhase(bool lastGC)
|
||||
#ifdef DEBUG
|
||||
CheckHashTablesAfterMovingGC(rt);
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (CanRelocateZone(rt, zone)) {
|
||||
if (zone->isGCCompacting()) {
|
||||
MOZ_ASSERT(!zone->isPreservingCode());
|
||||
zone->arenas.checkEmptyFreeLists();
|
||||
|
||||
@ -5877,9 +5930,11 @@ GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason rea
|
||||
break;
|
||||
|
||||
case COMPACT:
|
||||
if (isCompacting && compactPhase(lastGC) == NotFinished)
|
||||
if (isCompacting && compactPhase(lastGC, reason) == NotFinished)
|
||||
break;
|
||||
|
||||
finishCollection();
|
||||
|
||||
incrementalState = NO_INCREMENTAL;
|
||||
break;
|
||||
|
||||
|
@ -474,8 +474,8 @@ class ArenaList {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArenaHeader *removeRemainingArenas(ArenaHeader **arenap, const AutoLockGC &lock);
|
||||
ArenaHeader *pickArenasToRelocate(JSRuntime *runtime);
|
||||
ArenaHeader *removeRemainingArenas(ArenaHeader **arenap);
|
||||
ArenaHeader **pickArenasToRelocate(size_t &arenaTotalOut, size_t &relocTotalOut);
|
||||
ArenaHeader *relocateArenas(ArenaHeader *toRelocate, ArenaHeader *relocated,
|
||||
gcstats::Statistics& stats);
|
||||
};
|
||||
@ -804,7 +804,8 @@ class ArenaLists
|
||||
MOZ_ASSERT(freeLists[kind].isEmpty());
|
||||
}
|
||||
|
||||
ArenaHeader *relocateArenas(ArenaHeader *relocatedList, gcstats::Statistics& stats);
|
||||
bool relocateArenas(ArenaHeader *&relocatedListOut, JS::gcreason::Reason reason,
|
||||
gcstats::Statistics& stats);
|
||||
|
||||
void queueForegroundObjectsForSweep(FreeOp *fop);
|
||||
void queueForegroundThingsForSweep(FreeOp *fop);
|
||||
|
@ -92,7 +92,11 @@ JSObject *
|
||||
js::NonNullObject(JSContext *cx, const Value &v)
|
||||
{
|
||||
if (v.isPrimitive()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
RootedValue value(cx, v);
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, value, NullPtr());
|
||||
if (!bytes)
|
||||
return nullptr;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes);
|
||||
return nullptr;
|
||||
}
|
||||
return &v.toObject();
|
||||
@ -280,7 +284,10 @@ PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors)
|
||||
|
||||
/* 8.10.5 step 1 */
|
||||
if (v.isPrimitive()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NullPtr());
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes);
|
||||
return false;
|
||||
}
|
||||
RootedObject desc(cx, &v.toObject());
|
||||
|
@ -1620,6 +1620,8 @@ ExpressionDecompiler::decompilePC(jsbytecode *pc)
|
||||
return false;
|
||||
return write(str);
|
||||
}
|
||||
case JSOP_VOID:
|
||||
return write("void ") && decompilePCForStackOperand(pc, -1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -384,7 +384,10 @@ WeakMap_set_impl(JSContext *cx, CallArgs args)
|
||||
MOZ_ASSERT(IsWeakMap(args.thisv()));
|
||||
|
||||
if (!args.get(0).isObject()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, args.get(0), NullPtr());
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -565,7 +568,10 @@ WeakMap_construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
// Steps 12k-l.
|
||||
if (isOriginalAdder) {
|
||||
if (keyVal.isPrimitive()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, NullPtr());
|
||||
if (!bytes)
|
||||
return false;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,10 @@ static PerfMeasurement*
|
||||
GetPM(JSContext* cx, JS::HandleValue value, const char* fname)
|
||||
{
|
||||
if (!value.isObject()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, 0, JSMSG_NOT_NONNULL_OBJECT);
|
||||
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, value, NullPtr());
|
||||
if (!bytes)
|
||||
return nullptr;
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, 0, JSMSG_NOT_NONNULL_OBJECT, bytes);
|
||||
return nullptr;
|
||||
}
|
||||
RootedObject obj(cx, &value.toObject());
|
||||
|
@ -46,16 +46,19 @@ function expectSyntaxError(code)
|
||||
expectSyntaxError("function f1() {} 'use strict'; function f2() {}");
|
||||
expectSyntaxError("function f3() { var x; 'use strict'; }");
|
||||
|
||||
expectSyntaxError("function f4() {} 'use asm'; function f5() {}");
|
||||
if (isAsmJSCompilationAvailable())
|
||||
expectSyntaxError("function f4() {} 'use asm'; function f5() {}");
|
||||
expectSyntaxError("function f6() { var x; 'use strict'; }");
|
||||
expectSyntaxError("'use asm'; function f7() {}");
|
||||
if (isAsmJSCompilationAvailable())
|
||||
expectSyntaxError("'use asm'; function f7() {}");
|
||||
|
||||
// No errors expected -- useless non-directives, but not contrary to used
|
||||
// semantics.
|
||||
evaluateNoRval("'use strict'; function f8() {} 'use strict'; function f9() {}");
|
||||
evaluateNoRval("'use strict'; function f10() { var z; 'use strict' }");
|
||||
|
||||
evaluateNoRval("function f11() { 'use asm'; return {}; }");
|
||||
if (isAsmJSCompilationAvailable())
|
||||
evaluateNoRval("function f11() { 'use asm'; return {}; }");
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -7,14 +7,16 @@ assertEq(RegExp.prototype.flags, "");
|
||||
assertEq(/foo/iymg.flags, "gimy");
|
||||
assertEq(RegExp("").flags, "");
|
||||
assertEq(RegExp("", "mygi").flags, "gimy");
|
||||
// TODO: Uncomment lines 12, 16, 19 and remove lines 11, 15, 18 when bug 1135377 is fixed.
|
||||
assertThrowsInstanceOf(() => RegExp("", "mygui").flags, SyntaxError);
|
||||
// When the /u flag is supported, uncomment the line below and remove the line above
|
||||
// assertEq(RegExp("", "mygui").flags, "gimuy");
|
||||
assertEq(genericFlags({}), "");
|
||||
assertEq(genericFlags({ignoreCase: true}), "i");
|
||||
assertEq(genericFlags({sticky:1, unicode:1, global: 0}), "uy");
|
||||
assertEq(genericFlags({sticky:1, unicode:1, global: 0}), "y");
|
||||
// assertEq(genericFlags({sticky:1, unicode:1, global: 0}), "uy");
|
||||
assertEq(genericFlags({__proto__: {multiline: true}}), "m");
|
||||
assertEq(genericFlags(new Proxy({}, {get(){return true}})), "gimuy");
|
||||
assertEq(genericFlags(new Proxy({}, {get(){return true}})), "gimy");
|
||||
// assertEq(genericFlags(new Proxy({}, {get(){return true}})), "gimuy");
|
||||
|
||||
assertThrowsInstanceOf(() => genericFlags(), TypeError);
|
||||
assertThrowsInstanceOf(() => genericFlags(1), TypeError);
|
||||
|
@ -123,7 +123,7 @@ GetOrCreateFunctionScript(JSContext *cx, HandleFunction fun)
|
||||
bool
|
||||
js::ReportObjectRequired(JSContext *cx)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, "value");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ DebuggerMemory::checkThis(JSContext *cx, CallArgs &args, const char *fnName)
|
||||
const Value &thisValue = args.thisv();
|
||||
|
||||
if (!thisValue.isObject()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, InformalValueTypeName(thisValue));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -34,19 +34,6 @@ class ErrorObject : public NativeObject
|
||||
friend JSObject *
|
||||
::js_InitExceptionClasses(JSContext *cx, JS::HandleObject global);
|
||||
|
||||
/* For access to assignInitialShape. */
|
||||
friend bool
|
||||
EmptyShape::ensureInitialCustomShape<ErrorObject>(ExclusiveContext *cx,
|
||||
Handle<ErrorObject*> obj);
|
||||
|
||||
/*
|
||||
* Assign the initial error shape to the empty object. (This shape does
|
||||
* *not* include .message, which must be added separately if needed; see
|
||||
* ErrorObject::init.)
|
||||
*/
|
||||
static Shape *
|
||||
assignInitialShape(ExclusiveContext *cx, Handle<ErrorObject*> obj);
|
||||
|
||||
static bool
|
||||
init(JSContext *cx, Handle<ErrorObject*> obj, JSExnType type,
|
||||
ScopedJSFreePtr<JSErrorReport> *errorReport, HandleString fileName, HandleString stack,
|
||||
@ -85,6 +72,14 @@ class ErrorObject : public NativeObject
|
||||
uint32_t lineNumber, uint32_t columnNumber, ScopedJSFreePtr<JSErrorReport> *report,
|
||||
HandleString message);
|
||||
|
||||
/*
|
||||
* Assign the initial error shape to the empty object. (This shape does
|
||||
* *not* include .message, which must be added separately if needed; see
|
||||
* ErrorObject::init.)
|
||||
*/
|
||||
static Shape *
|
||||
assignInitialShape(ExclusiveContext *cx, Handle<ErrorObject*> obj);
|
||||
|
||||
JSExnType type() const {
|
||||
return JSExnType(getReservedSlot(EXNTYPE_SLOT).toInt32());
|
||||
}
|
||||
|
@ -289,9 +289,14 @@ class ObjectGroup : public gc::TenuredCell
|
||||
return maybeUnboxedLayoutDontCheckGeneration();
|
||||
}
|
||||
|
||||
UnboxedLayout &unboxedLayout() {
|
||||
UnboxedLayout &unboxedLayoutDontCheckGeneration() const {
|
||||
MOZ_ASSERT(addendumKind() == Addendum_UnboxedLayout);
|
||||
return *maybeUnboxedLayout();
|
||||
return *maybeUnboxedLayoutDontCheckGeneration();
|
||||
}
|
||||
|
||||
UnboxedLayout &unboxedLayout() {
|
||||
maybeSweep(nullptr);
|
||||
return unboxedLayoutDontCheckGeneration();
|
||||
}
|
||||
|
||||
void setUnboxedLayout(UnboxedLayout *layout) {
|
||||
|
@ -376,6 +376,14 @@ class RegExpObject : public NativeObject
|
||||
createNoStatics(ExclusiveContext *cx, HandleAtom atom, RegExpFlag flags,
|
||||
frontend::TokenStream *ts, LifoAlloc &alloc);
|
||||
|
||||
/*
|
||||
* Compute the initial shape to associate with fresh RegExp objects,
|
||||
* encoding their initial properties. Return the shape after
|
||||
* changing |obj|'s last property to it.
|
||||
*/
|
||||
static Shape *
|
||||
assignInitialShape(ExclusiveContext *cx, Handle<RegExpObject*> obj);
|
||||
|
||||
/* Accessors. */
|
||||
|
||||
static unsigned lastIndexSlot() { return LAST_INDEX_SLOT; }
|
||||
@ -446,19 +454,6 @@ class RegExpObject : public NativeObject
|
||||
private:
|
||||
friend class RegExpObjectBuilder;
|
||||
|
||||
/* For access to assignInitialShape. */
|
||||
friend bool
|
||||
EmptyShape::ensureInitialCustomShape<RegExpObject>(ExclusiveContext *cx,
|
||||
Handle<RegExpObject*> obj);
|
||||
|
||||
/*
|
||||
* Compute the initial shape to associate with fresh RegExp objects,
|
||||
* encoding their initial properties. Return the shape after
|
||||
* changing |obj|'s last property to it.
|
||||
*/
|
||||
static Shape *
|
||||
assignInitialShape(ExclusiveContext *cx, Handle<RegExpObject*> obj);
|
||||
|
||||
bool init(ExclusiveContext *cx, HandleAtom source, RegExpFlag flags);
|
||||
|
||||
/*
|
||||
|
@ -341,7 +341,7 @@ SavedFrame::checkThis(JSContext *cx, CallArgs &args, const char *fnName,
|
||||
const Value &thisValue = args.thisv();
|
||||
|
||||
if (!thisValue.isObject()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, InformalValueTypeName(thisValue));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,14 @@ class StringObject : public NativeObject
|
||||
static inline StringObject *create(JSContext *cx, HandleString str,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
/*
|
||||
* Compute the initial shape to associate with fresh String objects, which
|
||||
* encodes the initial length property. Return the shape after changing
|
||||
* |obj|'s last property to it.
|
||||
*/
|
||||
static Shape *
|
||||
assignInitialShape(ExclusiveContext *cx, Handle<StringObject*> obj);
|
||||
|
||||
JSString *unbox() const {
|
||||
return getFixedSlot(PRIMITIVE_VALUE_SLOT).toString();
|
||||
}
|
||||
@ -58,19 +66,6 @@ class StringObject : public NativeObject
|
||||
/* For access to init, as String.prototype is special. */
|
||||
friend JSObject *
|
||||
::js_InitStringClass(JSContext *cx, js::HandleObject global);
|
||||
|
||||
/* For access to assignInitialShape. */
|
||||
friend bool
|
||||
EmptyShape::ensureInitialCustomShape<StringObject>(ExclusiveContext *cx,
|
||||
Handle<StringObject*> obj);
|
||||
|
||||
/*
|
||||
* Compute the initial shape to associate with fresh String objects, which
|
||||
* encodes the initial length property. Return the shape after changing
|
||||
* |obj|'s last property to it.
|
||||
*/
|
||||
static Shape *
|
||||
assignInitialShape(ExclusiveContext *cx, Handle<StringObject*> obj);
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
@ -2268,8 +2268,8 @@ TemporaryTypeSet::propertyNeedsBarrier(CompilerConstraintList *constraints, jsid
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ClassCanHaveExtraProperties(const Class *clasp)
|
||||
bool
|
||||
js::ClassCanHaveExtraProperties(const Class *clasp)
|
||||
{
|
||||
return clasp->resolve
|
||||
|| clasp->ops.lookupProperty
|
||||
|
@ -909,6 +909,9 @@ class TypeNewScript
|
||||
/* Is this a reasonable PC to be doing inlining on? */
|
||||
inline bool isInlinableCall(jsbytecode *pc);
|
||||
|
||||
bool
|
||||
ClassCanHaveExtraProperties(const Class *clasp);
|
||||
|
||||
/*
|
||||
* Whether Array.prototype, or an object on its proto chain, has an
|
||||
* indexed property.
|
||||
|
@ -87,7 +87,8 @@ UnboxedPlainObject::setValue(JSContext *cx, const UnboxedLayout::Property &prope
|
||||
|
||||
case JSVAL_TYPE_STRING:
|
||||
if (v.isString()) {
|
||||
*reinterpret_cast<HeapPtrString*>(p) = v.toString();
|
||||
MOZ_ASSERT(!IsInsideNursery(v.toString()));
|
||||
*reinterpret_cast<PreBarrieredString*>(p) = v.toString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -99,7 +100,14 @@ UnboxedPlainObject::setValue(JSContext *cx, const UnboxedLayout::Property &prope
|
||||
// created.
|
||||
AddTypePropertyId(cx, this, NameToId(property.name), v);
|
||||
|
||||
*reinterpret_cast<HeapPtrObject*>(p) = v.toObjectOrNull();
|
||||
// Manually trigger post barriers on the whole object. If we treat
|
||||
// the pointer as a HeapPtrObject we will get confused later if the
|
||||
// object is converted to its native representation.
|
||||
JSObject *obj = v.toObjectOrNull();
|
||||
if (IsInsideNursery(v.toObjectOrNull()) && !IsInsideNursery(this))
|
||||
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(this);
|
||||
|
||||
*reinterpret_cast<PreBarrieredObject*>(p) = obj;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -138,7 +146,7 @@ UnboxedPlainObject::getValue(const UnboxedLayout::Property &property)
|
||||
void
|
||||
UnboxedPlainObject::trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
const UnboxedLayout &layout = obj->as<UnboxedPlainObject>().layout();
|
||||
const UnboxedLayout &layout = obj->as<UnboxedPlainObject>().layoutDontCheckGeneration();
|
||||
const int32_t *list = layout.traceList();
|
||||
if (!list)
|
||||
return;
|
||||
|
@ -176,6 +176,10 @@ class UnboxedPlainObject : public JSObject
|
||||
return group()->unboxedLayout();
|
||||
}
|
||||
|
||||
const UnboxedLayout &layoutDontCheckGeneration() const {
|
||||
return group()->unboxedLayoutDontCheckGeneration();
|
||||
}
|
||||
|
||||
uint8_t *data() {
|
||||
return &data_[0];
|
||||
}
|
||||
|
@ -396,6 +396,23 @@ bool OpenSlesInput::EnqueueAllBuffers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenSlesInput::SetupVoiceMode() {
|
||||
SLAndroidConfigurationItf configItf;
|
||||
SLresult res = (*sles_recorder_)->GetInterface(sles_recorder_, SL_IID_ANDROIDCONFIGURATION_,
|
||||
(void*)&configItf);
|
||||
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, id_, "OpenSL GetInterface: %d", res);
|
||||
|
||||
if (res == SL_RESULT_SUCCESS) {
|
||||
SLuint32 voiceMode = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
|
||||
SLuint32 voiceSize = sizeof(voiceMode);
|
||||
|
||||
res = (*configItf)->SetConfiguration(configItf,
|
||||
SL_ANDROID_KEY_RECORDING_PRESET,
|
||||
&voiceMode, voiceSize);
|
||||
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, id_, "OpenSL Set Voice mode res: %d", res);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_GONK) && defined(WEBRTC_HARDWARE_AEC_NS)
|
||||
bool OpenSlesInput::CheckPlatformAEC() {
|
||||
effect_descriptor_t fxDesc;
|
||||
@ -519,16 +536,7 @@ bool OpenSlesInput::CreateAudioRecorder() {
|
||||
&recorder_config),
|
||||
false);
|
||||
|
||||
// Set audio recorder configuration to
|
||||
// SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION which ensures that we
|
||||
// use the main microphone tuned for audio communications.
|
||||
SLuint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
|
||||
OPENSL_RETURN_ON_FAILURE(
|
||||
(*recorder_config)->SetConfiguration(recorder_config,
|
||||
SL_ANDROID_KEY_RECORDING_PRESET,
|
||||
&stream_type,
|
||||
sizeof(SLint32)),
|
||||
false);
|
||||
SetupVoiceMode();
|
||||
|
||||
// Realize the recorder in synchronous mode.
|
||||
OPENSL_RETURN_ON_FAILURE((*sles_recorder_)->Realize(sles_recorder_,
|
||||
|
@ -147,9 +147,9 @@ class OpenSlesInput {
|
||||
// etc, so it should be called when starting recording.
|
||||
bool CreateAudioRecorder();
|
||||
void DestroyAudioRecorder();
|
||||
void SetupVoiceMode();
|
||||
#if defined(WEBRTC_GONK) && defined(WEBRTC_HARDWARE_AEC_NS)
|
||||
void SetupAECAndNS();
|
||||
void SetupVoiceMode();
|
||||
bool CheckPlatformAEC();
|
||||
#endif
|
||||
|
||||
|
@ -607,6 +607,11 @@ pref("gfx.color_management.enablev4", false);
|
||||
|
||||
pref("gfx.downloadable_fonts.enabled", true);
|
||||
pref("gfx.downloadable_fonts.fallback_delay", 3000);
|
||||
|
||||
// disable downloadable font cache so that behavior is consistently
|
||||
// the uncached load behavior across pages (useful for testing reflow problems)
|
||||
pref("gfx.downloadable_fonts.disable_cache", false);
|
||||
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("gfx.downloadable_fonts.woff2.enabled", false);
|
||||
#else
|
||||
|
@ -412,14 +412,11 @@ NS_IMETHODIMP CacheEntry::OnFileReady(nsresult aResult, bool aIsNew)
|
||||
|
||||
if (NS_SUCCEEDED(aResult)) {
|
||||
if (aIsNew) {
|
||||
mozilla::Telemetry::AccumulateTimeDelta(
|
||||
mozilla::Telemetry::NETWORK_CACHE_V2_MISS_TIME_MS,
|
||||
mLoadStart);
|
||||
}
|
||||
else {
|
||||
mozilla::Telemetry::AccumulateTimeDelta(
|
||||
mozilla::Telemetry::NETWORK_CACHE_V2_HIT_TIME_MS,
|
||||
mLoadStart);
|
||||
CacheFileUtils::DetailedCacheHitTelemetry::AddRecord(
|
||||
CacheFileUtils::DetailedCacheHitTelemetry::MISS, mLoadStart);
|
||||
} else {
|
||||
CacheFileUtils::DetailedCacheHitTelemetry::AddRecord(
|
||||
CacheFileUtils::DetailedCacheHitTelemetry::HIT, mLoadStart);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3576,6 +3576,45 @@ CacheFileIOManager::CreateCacheTree()
|
||||
|
||||
StartRemovingTrash();
|
||||
|
||||
if (!CacheObserver::CacheFSReported()) {
|
||||
uint32_t fsType = 4; // Other OS
|
||||
|
||||
#ifdef XP_WIN
|
||||
nsAutoString target;
|
||||
nsresult rv = mCacheDirectory->GetTarget(target);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
wchar_t volume_path[MAX_PATH + 1] = { 0 };
|
||||
if (!::GetVolumePathNameW(target.get(),
|
||||
volume_path,
|
||||
mozilla::ArrayLength(volume_path))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
wchar_t fsName[6] = { 0 };
|
||||
if (!::GetVolumeInformationW(volume_path, nullptr, 0, nullptr, nullptr,
|
||||
nullptr, fsName,
|
||||
mozilla::ArrayLength(fsName))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (wcscmp(fsName, L"NTFS") == 0) {
|
||||
fsType = 0;
|
||||
} else if (wcscmp(fsName, L"FAT32") == 0) {
|
||||
fsType = 1;
|
||||
} else if (wcscmp(fsName, L"FAT") == 0) {
|
||||
fsType = 2;
|
||||
} else {
|
||||
fsType = 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_CACHE_FS_TYPE, fsType);
|
||||
CacheObserver::SetCacheFSReported();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3619,6 +3658,18 @@ CacheFileIOManager::OpenNSPRHandle(CacheFileHandle *aHandle, bool aCreate)
|
||||
LOG(("CacheFileIOManager::OpenNSPRHandle() - Successfully evicted entry"
|
||||
" with hash %08x%08x%08x%08x%08x. %s to create the new file.",
|
||||
LOGSHA1(&hash), NS_SUCCEEDED(rv) ? "Succeeded" : "Failed"));
|
||||
|
||||
// Report the full size only once per session
|
||||
static bool sSizeReported = false;
|
||||
if (!sSizeReported) {
|
||||
uint32_t cacheUsage;
|
||||
if (NS_SUCCEEDED(CacheIndex::GetCacheSize(&cacheUsage))) {
|
||||
cacheUsage >>= 10;
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_CACHE_SIZE_FULL_FAT,
|
||||
cacheUsage);
|
||||
sSizeReported = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG(("CacheFileIOManager::OpenNSPRHandle() - Couldn't evict an existing"
|
||||
" entry."));
|
||||
|
@ -64,6 +64,7 @@ CacheFileMetadata::CacheFileMetadata(CacheFileHandle *aHandle, const nsACString
|
||||
CacheFileMetadata::CacheFileMetadata(bool aMemoryOnly, const nsACString &aKey)
|
||||
: CacheMemoryConsumer(aMemoryOnly ? MEMORY_ONLY : NORMAL)
|
||||
, mHandle(nullptr)
|
||||
, mFirstRead(true)
|
||||
, mHashArray(nullptr)
|
||||
, mHashArraySize(0)
|
||||
, mHashCount(0)
|
||||
@ -95,6 +96,7 @@ CacheFileMetadata::CacheFileMetadata(bool aMemoryOnly, const nsACString &aKey)
|
||||
CacheFileMetadata::CacheFileMetadata()
|
||||
: CacheMemoryConsumer(DONT_REPORT /* This is a helper class */)
|
||||
, mHandle(nullptr)
|
||||
, mFirstRead(true)
|
||||
, mHashArray(nullptr)
|
||||
, mHashArraySize(0)
|
||||
, mHashCount(0)
|
||||
@ -206,6 +208,7 @@ CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
|
||||
LOG(("CacheFileMetadata::ReadMetadata() - Reading metadata from disk, trying "
|
||||
"offset=%lld, filesize=%lld [this=%p]", offset, size, this));
|
||||
|
||||
mReadStart = mozilla::TimeStamp::Now();
|
||||
mListener = aListener;
|
||||
rv = CacheFileIOManager::Read(mHandle, offset, mBuf, mBufSize, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -629,6 +632,16 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mFirstRead) {
|
||||
Telemetry::AccumulateTimeDelta(
|
||||
Telemetry::NETWORK_CACHE_METADATA_FIRST_READ_TIME_MS, mReadStart);
|
||||
Telemetry::Accumulate(
|
||||
Telemetry::NETWORK_CACHE_METADATA_FIRST_READ_SIZE, mBufSize);
|
||||
} else {
|
||||
Telemetry::AccumulateTimeDelta(
|
||||
Telemetry::NETWORK_CACHE_METADATA_SECOND_READ_TIME_MS, mReadStart);
|
||||
}
|
||||
|
||||
// check whether we have read all necessary data
|
||||
uint32_t realOffset = NetworkEndian::readUint32(mBuf + mBufSize -
|
||||
sizeof(uint32_t));
|
||||
@ -663,6 +676,8 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
|
||||
LOG(("CacheFileMetadata::OnDataRead() - We need to read %d more bytes to "
|
||||
"have full metadata. [this=%p]", missing, this));
|
||||
|
||||
mFirstRead = false;
|
||||
mReadStart = mozilla::TimeStamp::Now();
|
||||
rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
|
||||
@ -680,6 +695,9 @@ CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_CACHE_METADATA_SIZE,
|
||||
size - realOffset);
|
||||
|
||||
// We have all data according to offset information at the end of the entry.
|
||||
// Try to parse it.
|
||||
rv = ParseMetadata(realOffset, realOffset - usedOffset, true);
|
||||
|
@ -176,6 +176,8 @@ private:
|
||||
|
||||
nsRefPtr<CacheFileHandle> mHandle;
|
||||
nsCString mKey;
|
||||
bool mFirstRead;
|
||||
mozilla::TimeStamp mReadStart;
|
||||
CacheHash::Hash16_t *mHashArray;
|
||||
uint32_t mHashArraySize;
|
||||
uint32_t mHashCount;
|
||||
|
@ -424,6 +424,116 @@ ValidityMap::operator[](uint32_t aIdx)
|
||||
return mMap.ElementAt(aIdx);
|
||||
}
|
||||
|
||||
StaticMutex DetailedCacheHitTelemetry::sLock;
|
||||
uint32_t DetailedCacheHitTelemetry::sRecordCnt = 0;
|
||||
DetailedCacheHitTelemetry::HitRate DetailedCacheHitTelemetry::sHRStats[kNumOfRanges];
|
||||
|
||||
DetailedCacheHitTelemetry::HitRate::HitRate()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void
|
||||
DetailedCacheHitTelemetry::HitRate::AddRecord(ERecType aType)
|
||||
{
|
||||
if (aType == HIT) {
|
||||
++mHitCnt;
|
||||
} else {
|
||||
++mMissCnt;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
DetailedCacheHitTelemetry::HitRate::GetHitRateBucket(uint32_t aNumOfBuckets) const
|
||||
{
|
||||
uint32_t bucketIdx = (aNumOfBuckets * mHitCnt) / (mHitCnt + mMissCnt);
|
||||
if (bucketIdx == aNumOfBuckets) { // make sure 100% falls into the last bucket
|
||||
--bucketIdx;
|
||||
}
|
||||
|
||||
return bucketIdx;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
DetailedCacheHitTelemetry::HitRate::Count()
|
||||
{
|
||||
return mHitCnt + mMissCnt;
|
||||
}
|
||||
|
||||
void
|
||||
DetailedCacheHitTelemetry::HitRate::Reset()
|
||||
{
|
||||
mHitCnt = 0;
|
||||
mMissCnt = 0;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
DetailedCacheHitTelemetry::AddRecord(ERecType aType, TimeStamp aLoadStart)
|
||||
{
|
||||
bool isUpToDate = false;
|
||||
CacheIndex::IsUpToDate(&isUpToDate);
|
||||
if (!isUpToDate) {
|
||||
// Ignore the record when the entry file count might be incorrect
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t entryCount;
|
||||
nsresult rv = CacheIndex::GetEntryFileCount(&entryCount);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t rangeIdx = entryCount / kRangeSize;
|
||||
if (rangeIdx >= kNumOfRanges) { // The last range has no upper limit.
|
||||
rangeIdx = kNumOfRanges - 1;
|
||||
}
|
||||
|
||||
uint32_t hitMissValue = 2 * rangeIdx; // 2 values per range
|
||||
if (aType == MISS) { // The order is HIT, MISS
|
||||
++hitMissValue;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
|
||||
if (aType == MISS) {
|
||||
mozilla::Telemetry::AccumulateTimeDelta(
|
||||
mozilla::Telemetry::NETWORK_CACHE_V2_MISS_TIME_MS,
|
||||
aLoadStart);
|
||||
} else {
|
||||
mozilla::Telemetry::AccumulateTimeDelta(
|
||||
mozilla::Telemetry::NETWORK_CACHE_V2_HIT_TIME_MS,
|
||||
aLoadStart);
|
||||
}
|
||||
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_CACHE_HIT_MISS_STAT_PER_CACHE_SIZE,
|
||||
hitMissValue);
|
||||
|
||||
sHRStats[rangeIdx].AddRecord(aType);
|
||||
++sRecordCnt;
|
||||
|
||||
if (sRecordCnt < kTotalSamplesReportLimit) {
|
||||
return;
|
||||
}
|
||||
|
||||
sRecordCnt = 0;
|
||||
|
||||
for (uint32_t i = 0; i < kNumOfRanges; ++i) {
|
||||
if (sHRStats[i].Count() >= kHitRateSamplesReportLimit) {
|
||||
// The telemetry enums are grouped by buckets as follows:
|
||||
// Telemetry value : 0,1,2,3, ... ,19,20,21,22, ... ,398,399
|
||||
// Hit rate bucket : 0,0,0,0, ... , 0, 1, 1, 1, ... , 19, 19
|
||||
// Cache size range: 0,1,2,3, ... ,19, 0, 1, 2, ... , 18, 19
|
||||
uint32_t bucketOffset = sHRStats[i].GetHitRateBucket(kHitRateBuckets) *
|
||||
kNumOfRanges;
|
||||
|
||||
Telemetry::Accumulate(Telemetry::NETWORK_CACHE_HIT_RATE_PER_CACHE_SIZE,
|
||||
bucketOffset + i);
|
||||
sHRStats[i].Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // CacheFileUtils
|
||||
} // net
|
||||
} // mozilla
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class nsILoadContextInfo;
|
||||
class nsACString;
|
||||
@ -86,6 +88,64 @@ private:
|
||||
nsTArray<ValidityPair> mMap;
|
||||
};
|
||||
|
||||
|
||||
class DetailedCacheHitTelemetry {
|
||||
public:
|
||||
enum ERecType {
|
||||
HIT = 0,
|
||||
MISS = 1
|
||||
};
|
||||
|
||||
static void AddRecord(ERecType aType, TimeStamp aLoadStart);
|
||||
|
||||
private:
|
||||
class HitRate {
|
||||
public:
|
||||
HitRate();
|
||||
|
||||
void AddRecord(ERecType aType);
|
||||
// Returns the bucket index that the current hit rate falls into according
|
||||
// to the given aNumOfBuckets.
|
||||
uint32_t GetHitRateBucket(uint32_t aNumOfBuckets) const;
|
||||
uint32_t Count();
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
uint32_t mHitCnt;
|
||||
uint32_t mMissCnt;
|
||||
};
|
||||
|
||||
// Group the hits and misses statistics by cache files count ranges (0-5000,
|
||||
// 5001-10000, ... , 95001- )
|
||||
static const uint32_t kRangeSize = 5000;
|
||||
static const uint32_t kNumOfRanges = 20;
|
||||
|
||||
// Use the same ranges to report an average hit rate. Report the hit rates
|
||||
// (and reset the counters) every kTotalSamplesReportLimit samples.
|
||||
static const uint32_t kTotalSamplesReportLimit = 1000;
|
||||
|
||||
// Report hit rate for a given cache size range only if it contains
|
||||
// kHitRateSamplesReportLimit or more samples. This limit should avoid
|
||||
// reporting a biased statistics.
|
||||
static const uint32_t kHitRateSamplesReportLimit = 500;
|
||||
|
||||
// All hit rates are accumulated in a single telemetry probe, so to use
|
||||
// a sane number of enumerated values the hit rate is divided into buckets
|
||||
// instead of using a percent value. This constant defines number of buckets
|
||||
// that we divide the hit rates into. I.e. we'll report ranges 0%-5%, 5%-10%,
|
||||
// 10-%15%, ...
|
||||
static const uint32_t kHitRateBuckets = 20;
|
||||
|
||||
// Protects sRecordCnt, sHitStats and Telemetry::Accumulated() calls.
|
||||
static StaticMutex sLock;
|
||||
|
||||
// Counter of samples that is compared against kTotalSamplesReportLimit.
|
||||
static uint32_t sRecordCnt;
|
||||
|
||||
// Hit rate statistics for every cache size range.
|
||||
static HitRate sHRStats[kNumOfRanges];
|
||||
};
|
||||
|
||||
} // CacheFileUtils
|
||||
} // net
|
||||
} // mozilla
|
||||
|
@ -1309,6 +1309,29 @@ CacheIndex::GetCacheSize(uint32_t *_retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheIndex::GetEntryFileCount(uint32_t *_retval)
|
||||
{
|
||||
LOG(("CacheIndex::GetEntryFileCount()"));
|
||||
|
||||
nsRefPtr<CacheIndex> index = gInstance;
|
||||
|
||||
if (!index) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
CacheIndexAutoLock lock(index);
|
||||
|
||||
if (!index->IsIndexUsable()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
*_retval = index->mIndexStats.ActiveEntriesCount();
|
||||
LOG(("CacheIndex::GetEntryFileCount() - returning %u", *_retval));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheIndex::GetCacheStats(nsILoadContextInfo *aInfo, uint32_t *aSize, uint32_t *aCount)
|
||||
|
@ -651,6 +651,9 @@ public:
|
||||
// Returns cache size in kB.
|
||||
static nsresult GetCacheSize(uint32_t *_retval);
|
||||
|
||||
// Returns number of entry files in the cache
|
||||
static nsresult GetEntryFileCount(uint32_t *_retval);
|
||||
|
||||
// Synchronously returns the disk occupation and number of entries per-context.
|
||||
// Callable on any thread.
|
||||
static nsresult GetCacheStats(nsILoadContextInfo *aInfo, uint32_t *aSize, uint32_t *aCount);
|
||||
|
@ -86,6 +86,9 @@ bool CacheObserver::sSanitizeOnShutdown = kDefaultSanitizeOnShutdown;
|
||||
static bool kDefaultClearCacheOnShutdown = false;
|
||||
bool CacheObserver::sClearCacheOnShutdown = kDefaultClearCacheOnShutdown;
|
||||
|
||||
static bool kDefaultCacheFSReported = false;
|
||||
bool CacheObserver::sCacheFSReported = kDefaultCacheFSReported;
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheObserver,
|
||||
nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
@ -317,6 +320,32 @@ CacheObserver::StoreDiskCacheCapacity()
|
||||
sDiskCacheCapacity);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
CacheObserver::SetCacheFSReported()
|
||||
{
|
||||
sCacheFSReported = true;
|
||||
|
||||
if (!sSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
sSelf->StoreCacheFSReported();
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(sSelf, &CacheObserver::StoreCacheFSReported);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CacheObserver::StoreCacheFSReported()
|
||||
{
|
||||
mozilla::Preferences::SetInt("browser.cache.disk.filesystem_reported",
|
||||
sCacheFSReported);
|
||||
}
|
||||
|
||||
// static
|
||||
void CacheObserver::ParentDirOverride(nsIFile** aDir)
|
||||
{
|
||||
|
@ -61,6 +61,9 @@ class CacheObserver : public nsIObserver
|
||||
{ return sHalfLifeExperiment; }
|
||||
static bool const ClearCacheOnShutdown()
|
||||
{ return sSanitizeOnShutdown && sClearCacheOnShutdown; }
|
||||
static bool const CacheFSReported()
|
||||
{ return sCacheFSReported; }
|
||||
static void SetCacheFSReported();
|
||||
static void ParentDirOverride(nsIFile ** aDir);
|
||||
|
||||
static bool const EntryIsTooBig(int64_t aSize, bool aUsingDisk);
|
||||
@ -69,6 +72,7 @@ private:
|
||||
static CacheObserver* sSelf;
|
||||
|
||||
void StoreDiskCacheCapacity();
|
||||
void StoreCacheFSReported();
|
||||
void AttachToPreferences();
|
||||
|
||||
static uint32_t sUseNewCache;
|
||||
@ -91,6 +95,7 @@ private:
|
||||
static int32_t sHalfLifeExperiment;
|
||||
static bool sSanitizeOnShutdown;
|
||||
static bool sClearCacheOnShutdown;
|
||||
static bool sCacheFSReported;
|
||||
|
||||
// Non static properties, accessible via sSelf
|
||||
nsCOMPtr<nsIFile> mCacheParentDirectoryOverride;
|
||||
|
@ -492,7 +492,7 @@ class CCacheStats(object):
|
||||
DIRECTORY_DESCRIPTION = "cache directory"
|
||||
PRIMARY_CONFIG_DESCRIPTION = "primary config"
|
||||
SECONDARY_CONFIG_DESCRIPTION = "secondary config (readonly)"
|
||||
ABSOLUTE_KEYS = {'cache_max_size'}
|
||||
ABSOLUTE_KEYS = {'cache_files', 'cache_size', 'cache_max_size'}
|
||||
FORMAT_KEYS = {'cache_size', 'cache_max_size'}
|
||||
|
||||
GiB = 1024 ** 3
|
||||
|
@ -80,6 +80,50 @@ class TestCcacheStats(unittest.TestCase):
|
||||
max cache size 8.6 GB
|
||||
"""
|
||||
|
||||
STAT4 = """
|
||||
cache directory /Users/tlin/.ccache
|
||||
primary config /Users/tlin/.ccache/ccache.conf
|
||||
secondary config (readonly) /usr/local/Cellar/ccache/3.2.1/etc/ccache.conf
|
||||
cache hit (direct) 21039
|
||||
cache hit (preprocessed) 2315
|
||||
cache miss 39370
|
||||
called for link 3651
|
||||
called for preprocessing 6693
|
||||
compile failed 723
|
||||
ccache internal error 1
|
||||
preprocessor error 588
|
||||
bad compiler arguments 128
|
||||
unsupported source language 99
|
||||
autoconf compile/link 3669
|
||||
unsupported compiler option 187
|
||||
no input file 1711
|
||||
files in cache 18313
|
||||
cache size 6.3 GB
|
||||
max cache size 6.0 GB
|
||||
"""
|
||||
|
||||
STAT5 = """
|
||||
cache directory /Users/tlin/.ccache
|
||||
primary config /Users/tlin/.ccache/ccache.conf
|
||||
secondary config (readonly) /usr/local/Cellar/ccache/3.2.1/etc/ccache.conf
|
||||
cache hit (direct) 21039
|
||||
cache hit (preprocessed) 2315
|
||||
cache miss 39372
|
||||
called for link 3653
|
||||
called for preprocessing 6693
|
||||
compile failed 723
|
||||
ccache internal error 1
|
||||
preprocessor error 588
|
||||
bad compiler arguments 128
|
||||
unsupported source language 99
|
||||
autoconf compile/link 3669
|
||||
unsupported compiler option 187
|
||||
no input file 1711
|
||||
files in cache 17411
|
||||
cache size 6.0 GB
|
||||
max cache size 6.0 GB
|
||||
"""
|
||||
|
||||
def test_parse_garbage_stats_message(self):
|
||||
self.assertRaises(ValueError, CCacheStats, self.STAT_GARBAGE)
|
||||
|
||||
@ -116,6 +160,13 @@ class TestCcacheStats(unittest.TestCase):
|
||||
self.assertTrue(stat3)
|
||||
self.assertTrue(stats_diff)
|
||||
|
||||
def test_cache_size_shrinking(self):
|
||||
stat4 = CCacheStats(self.STAT4)
|
||||
stat5 = CCacheStats(self.STAT5)
|
||||
stats_diff = stat5 - stat4
|
||||
self.assertTrue(stat4)
|
||||
self.assertTrue(stat5)
|
||||
self.assertTrue(stats_diff)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -9,6 +9,7 @@ if CONFIG['CLANG_CXX']:
|
||||
'-Wno-missing-prototypes',
|
||||
'-Wno-missing-variable-declarations',
|
||||
'-Wno-padded',
|
||||
'-Wno-reserved-id-macro', # NSPR and NSS use reserved IDs in their include guards.
|
||||
'-Wno-shadow', # XXX: Clang's rules are too strict for constructors.
|
||||
'-Wno-weak-vtables', # We rely on the linker to merge the duplicate vtables.
|
||||
]
|
||||
|
@ -50,6 +50,7 @@ user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
|
||||
user_pref("dom.w3c_touch_events.enabled", 1);
|
||||
user_pref("dom.undo_manager.enabled", true);
|
||||
user_pref("dom.webcomponents.enabled", true);
|
||||
user_pref("dom.htmlimports.enabled", true);
|
||||
user_pref("dom.animations-api.core.enabled", true);
|
||||
// Set a future policy version to avoid the telemetry prompt.
|
||||
user_pref("toolkit.telemetry.prompted", 999);
|
||||
|
@ -6589,6 +6589,61 @@
|
||||
"n_values": "7",
|
||||
"description": "Final status of the CacheFileInputStream (0=ok, 1=other error, 2=out of memory, 3=disk full, 4=file corrupted, 5=file not found, 6=binding aborted)"
|
||||
},
|
||||
"NETWORK_CACHE_FS_TYPE": {
|
||||
"expires_in_version": "42",
|
||||
"kind": "enumerated",
|
||||
"n_values": "5",
|
||||
"description": "Type of FS that the cache is stored on (0=NTFS (Win), 1=FAT32 (Win), 2=FAT (Win), 3=other FS (Win), 4=other OS)"
|
||||
},
|
||||
"NETWORK_CACHE_SIZE_FULL_FAT": {
|
||||
"expires_in_version": "42",
|
||||
"kind": "linear",
|
||||
"high": "500",
|
||||
"n_buckets": 50,
|
||||
"description": "Size (in MB) of a cache that reached a file count limit"
|
||||
},
|
||||
"NETWORK_CACHE_HIT_MISS_STAT_PER_CACHE_SIZE": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
"n_values": 40,
|
||||
"description": "Hit/Miss count split by cache size in file count (0=Hit 0-5000, 1=Miss 0-5000, 2=Hit 5001-10000, ...)"
|
||||
},
|
||||
"NETWORK_CACHE_HIT_RATE_PER_CACHE_SIZE": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
"n_values": 400,
|
||||
"description": "Hit rate for a specific cache size in file count. The hit rate is split into 20 buckets, the lower limit of the range in percents is 5*n/20. The cache size is divided into 20 ranges of length 5000, the lower limit of the range is 5000*(n%20)"
|
||||
},
|
||||
"NETWORK_CACHE_METADATA_FIRST_READ_TIME_MS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "10000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Time spent to read the first part of the metadata from the cache entry file."
|
||||
},
|
||||
"NETWORK_CACHE_METADATA_SECOND_READ_TIME_MS": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "exponential",
|
||||
"high": "10000",
|
||||
"n_buckets": 50,
|
||||
"extended_statistics_ok": true,
|
||||
"description": "Time spent to read the missing part of the metadata from the cache entry file."
|
||||
},
|
||||
"NETWORK_CACHE_METADATA_FIRST_READ_SIZE": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "linear",
|
||||
"high": "5119",
|
||||
"n_buckets": 256,
|
||||
"description": "Guessed size of the metadata that we read from the cache file as the first part."
|
||||
},
|
||||
"NETWORK_CACHE_METADATA_SIZE": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "linear",
|
||||
"high": "5119",
|
||||
"n_buckets": 256,
|
||||
"description": "Actual size of the metadata parsed from the disk."
|
||||
},
|
||||
"DATABASE_LOCKED_EXCEPTION": {
|
||||
"expires_in_version": "42",
|
||||
"kind": "enumerated",
|
||||
|
@ -3,6 +3,8 @@
|
||||
* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
@ -344,7 +346,7 @@ var gUpdates = {
|
||||
onLoad: function() {
|
||||
this.wiz = document.documentElement;
|
||||
|
||||
gLogEnabled = getPref("getBoolPref", PREF_APP_UPDATE_LOG, false)
|
||||
gLogEnabled = getPref("getBoolPref", PREF_APP_UPDATE_LOG, false);
|
||||
|
||||
this.strings = document.getElementById("updateStrings");
|
||||
var brandStrings = document.getElementById("brandStrings");
|
||||
@ -427,13 +429,8 @@ var gUpdates = {
|
||||
|
||||
var p = this.update.selectedPatch;
|
||||
if (p) {
|
||||
var state = p.state;
|
||||
var patchFailed;
|
||||
try {
|
||||
patchFailed = this.update.getProperty("patchingFailed");
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
let state = p.state;
|
||||
let patchFailed = this.update.getProperty("patchingFailed");
|
||||
if (patchFailed) {
|
||||
if (patchFailed == "partial" && this.update.patchCount == 2) {
|
||||
// If the system failed to apply the partial patch, show the
|
||||
@ -453,24 +450,24 @@ var gUpdates = {
|
||||
// Now select the best page to start with, given the current state of
|
||||
// the Update.
|
||||
switch (state) {
|
||||
case STATE_PENDING:
|
||||
case STATE_PENDING_SVC:
|
||||
case STATE_APPLIED:
|
||||
case STATE_APPLIED_SVC:
|
||||
this.sourceEvent = SRCEVT_BACKGROUND;
|
||||
aCallback("finishedBackground");
|
||||
return;
|
||||
case STATE_DOWNLOADING:
|
||||
aCallback("downloading");
|
||||
return;
|
||||
case STATE_FAILED:
|
||||
window.getAttention();
|
||||
aCallback("errorpatching");
|
||||
return;
|
||||
case STATE_DOWNLOAD_FAILED:
|
||||
case STATE_APPLYING:
|
||||
aCallback("errors");
|
||||
return;
|
||||
case STATE_PENDING:
|
||||
case STATE_PENDING_SVC:
|
||||
case STATE_APPLIED:
|
||||
case STATE_APPLIED_SVC:
|
||||
this.sourceEvent = SRCEVT_BACKGROUND;
|
||||
aCallback("finishedBackground");
|
||||
return;
|
||||
case STATE_DOWNLOADING:
|
||||
aCallback("downloading");
|
||||
return;
|
||||
case STATE_FAILED:
|
||||
window.getAttention();
|
||||
aCallback("errorpatching");
|
||||
return;
|
||||
case STATE_DOWNLOAD_FAILED:
|
||||
case STATE_APPLYING:
|
||||
aCallback("errors");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.update.licenseURL)
|
||||
@ -1615,48 +1612,48 @@ var gDownloadingPage = {
|
||||
|
||||
var u = gUpdates.update;
|
||||
switch (status) {
|
||||
case CoR.NS_ERROR_CORRUPTED_CONTENT:
|
||||
case CoR.NS_ERROR_UNEXPECTED:
|
||||
if (u.selectedPatch.state == STATE_DOWNLOAD_FAILED &&
|
||||
(u.isCompleteUpdate || u.patchCount != 2)) {
|
||||
// Verification error of complete patch, informational text is held in
|
||||
// the update object.
|
||||
case CoR.NS_ERROR_CORRUPTED_CONTENT:
|
||||
case CoR.NS_ERROR_UNEXPECTED:
|
||||
if (u.selectedPatch.state == STATE_DOWNLOAD_FAILED &&
|
||||
(u.isCompleteUpdate || u.patchCount != 2)) {
|
||||
// Verification error of complete patch, informational text is held in
|
||||
// the update object.
|
||||
this.cleanUp();
|
||||
gUpdates.wiz.goTo("errors");
|
||||
break;
|
||||
}
|
||||
// Verification failed for a partial patch, complete patch is now
|
||||
// downloading so return early and do NOT remove the download listener!
|
||||
|
||||
// Reset the progress meter to "undertermined" mode so that we don't
|
||||
// show old progress for the new download of the "complete" patch.
|
||||
this._downloadProgress.mode = "undetermined";
|
||||
this._pauseButton.disabled = true;
|
||||
document.getElementById("verificationFailed").hidden = false;
|
||||
break;
|
||||
case CoR.NS_BINDING_ABORTED:
|
||||
LOG("gDownloadingPage", "onStopRequest - pausing download");
|
||||
// Do not remove UI listener since the user may resume downloading again.
|
||||
break;
|
||||
case CoR.NS_OK:
|
||||
LOG("gDownloadingPage", "onStopRequest - patch verification succeeded");
|
||||
// If the background update pref is set, we should wait until the update
|
||||
// is actually staged in the background.
|
||||
let aus = CoC["@mozilla.org/updates/update-service;1"].
|
||||
getService(CoI.nsIApplicationUpdateService);
|
||||
if (aus.canStageUpdates) {
|
||||
this._setUpdateApplying();
|
||||
} else {
|
||||
this.cleanUp();
|
||||
gUpdates.wiz.goTo("finished");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG("gDownloadingPage", "onStopRequest - transfer failed");
|
||||
// Some kind of transfer error, die.
|
||||
this.cleanUp();
|
||||
gUpdates.wiz.goTo("errors");
|
||||
break;
|
||||
}
|
||||
// Verification failed for a partial patch, complete patch is now
|
||||
// downloading so return early and do NOT remove the download listener!
|
||||
|
||||
// Reset the progress meter to "undertermined" mode so that we don't
|
||||
// show old progress for the new download of the "complete" patch.
|
||||
this._downloadProgress.mode = "undetermined";
|
||||
this._pauseButton.disabled = true;
|
||||
document.getElementById("verificationFailed").hidden = false;
|
||||
break;
|
||||
case CoR.NS_BINDING_ABORTED:
|
||||
LOG("gDownloadingPage", "onStopRequest - pausing download");
|
||||
// Do not remove UI listener since the user may resume downloading again.
|
||||
break;
|
||||
case CoR.NS_OK:
|
||||
LOG("gDownloadingPage", "onStopRequest - patch verification succeeded");
|
||||
// If the background update pref is set, we should wait until the update
|
||||
// is actually staged in the background.
|
||||
var aus = CoC["@mozilla.org/updates/update-service;1"].
|
||||
getService(CoI.nsIApplicationUpdateService);
|
||||
if (aus.canStageUpdates) {
|
||||
this._setUpdateApplying();
|
||||
} else {
|
||||
this.cleanUp();
|
||||
gUpdates.wiz.goTo("finished");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG("gDownloadingPage", "onStopRequest - transfer failed");
|
||||
// Some kind of transfer error, die.
|
||||
this.cleanUp();
|
||||
gUpdates.wiz.goTo("errors");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1775,16 +1772,16 @@ var gErrorPatchingPage = {
|
||||
|
||||
onWizardNext: function() {
|
||||
switch (gUpdates.update.selectedPatch.state) {
|
||||
case STATE_PENDING:
|
||||
case STATE_PENDING_SVC:
|
||||
gUpdates.wiz.goTo("finished");
|
||||
break;
|
||||
case STATE_DOWNLOADING:
|
||||
gUpdates.wiz.goTo("downloading");
|
||||
break;
|
||||
case STATE_DOWNLOAD_FAILED:
|
||||
gUpdates.wiz.goTo("errors");
|
||||
break;
|
||||
case STATE_PENDING:
|
||||
case STATE_PENDING_SVC:
|
||||
gUpdates.wiz.goTo("finished");
|
||||
break;
|
||||
case STATE_DOWNLOADING:
|
||||
gUpdates.wiz.goTo("downloading");
|
||||
break;
|
||||
case STATE_DOWNLOAD_FAILED:
|
||||
gUpdates.wiz.goTo("errors");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1598,19 +1598,19 @@ function UpdatePatch(patch) {
|
||||
var attr = patch.attributes.item(i);
|
||||
attr.QueryInterface(Ci.nsIDOMAttr);
|
||||
switch (attr.name) {
|
||||
case "selected":
|
||||
this.selected = attr.value == "true";
|
||||
break;
|
||||
case "size":
|
||||
if (0 == parseInt(attr.value)) {
|
||||
LOG("UpdatePatch:init - 0-sized patch!");
|
||||
throw Cr.NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
this[attr.name] = attr.value;
|
||||
break;
|
||||
};
|
||||
case "selected":
|
||||
this.selected = attr.value == "true";
|
||||
break;
|
||||
case "size":
|
||||
if (0 == parseInt(attr.value)) {
|
||||
LOG("UpdatePatch:init - 0-sized patch!");
|
||||
throw Cr.NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
this[attr.name] = attr.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdatePatch.prototype = {
|
||||
@ -1622,17 +1622,21 @@ UpdatePatch.prototype = {
|
||||
patch.setAttribute("type", this.type);
|
||||
patch.setAttribute("URL", this.URL);
|
||||
// finalURL is not available until after the download has started
|
||||
if (this.finalURL)
|
||||
if (this.finalURL) {
|
||||
patch.setAttribute("finalURL", this.finalURL);
|
||||
}
|
||||
patch.setAttribute("hashFunction", this.hashFunction);
|
||||
patch.setAttribute("hashValue", this.hashValue);
|
||||
patch.setAttribute("size", this.size);
|
||||
patch.setAttribute("selected", this.selected);
|
||||
if (this.selected) {
|
||||
patch.setAttribute("selected", this.selected);
|
||||
}
|
||||
patch.setAttribute("state", this.state);
|
||||
|
||||
for (var p in this._properties) {
|
||||
if (this._properties[p].present)
|
||||
if (this._properties[p].present) {
|
||||
patch.setAttribute(p, this._properties[p].data);
|
||||
}
|
||||
}
|
||||
|
||||
return patch;
|
||||
@ -1672,12 +1676,15 @@ UpdatePatch.prototype = {
|
||||
|
||||
/**
|
||||
* See nsIPropertyBag.idl
|
||||
* Note: returns null instead of throwing when the property doesn't exist to
|
||||
* simplify code and to silence warnings in debug builds.
|
||||
*/
|
||||
getProperty: function UpdatePatch_getProperty(name) {
|
||||
if (name in this._properties &&
|
||||
this._properties[name].present)
|
||||
this._properties[name].present) {
|
||||
return this._properties[name].data;
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1728,15 +1735,17 @@ function Update(update) {
|
||||
|
||||
// Null <update>, assume this is a message container and do no
|
||||
// further initialization
|
||||
if (!update)
|
||||
if (!update) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ELEMENT_NODE = Ci.nsIDOMNode.ELEMENT_NODE;
|
||||
for (var i = 0; i < update.childNodes.length; ++i) {
|
||||
var patchElement = update.childNodes.item(i);
|
||||
if (patchElement.nodeType != ELEMENT_NODE ||
|
||||
patchElement.localName != "patch")
|
||||
patchElement.localName != "patch") {
|
||||
continue;
|
||||
}
|
||||
|
||||
patchElement.QueryInterface(Ci.nsIDOMElement);
|
||||
try {
|
||||
@ -1747,8 +1756,9 @@ function Update(update) {
|
||||
this._patches.push(patch);
|
||||
}
|
||||
|
||||
if (this._patches.length == 0 && !update.hasAttribute("unsupported"))
|
||||
if (this._patches.length == 0 && !update.hasAttribute("unsupported")) {
|
||||
throw Cr.NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// Fallback to the behavior prior to bug 530872 if the update does not have an
|
||||
// appVersion attribute.
|
||||
@ -1762,82 +1772,84 @@ function Update(update) {
|
||||
}
|
||||
}
|
||||
|
||||
// Set the installDate value with the current time. If the update has an
|
||||
// installDate attribute this will be replaced with that value if it doesn't
|
||||
// equal 0.
|
||||
this.installDate = (new Date()).getTime();
|
||||
|
||||
for (var i = 0; i < update.attributes.length; ++i) {
|
||||
var attr = update.attributes.item(i);
|
||||
attr.QueryInterface(Ci.nsIDOMAttr);
|
||||
if (attr.value == "undefined")
|
||||
if (attr.value == "undefined") {
|
||||
continue;
|
||||
else if (attr.name == "detailsURL")
|
||||
} else if (attr.name == "detailsURL") {
|
||||
this._detailsURL = attr.value;
|
||||
else if (attr.name == "extensionVersion") {
|
||||
} else if (attr.name == "extensionVersion") {
|
||||
// Prevent extensionVersion from replacing appVersion if appVersion is
|
||||
// present in the update xml.
|
||||
if (!this.appVersion)
|
||||
if (!this.appVersion) {
|
||||
this.appVersion = attr.value;
|
||||
}
|
||||
else if (attr.name == "installDate" && attr.value)
|
||||
this.installDate = parseInt(attr.value);
|
||||
else if (attr.name == "isCompleteUpdate")
|
||||
}
|
||||
} else if (attr.name == "installDate" && attr.value) {
|
||||
let val = parseInt(attr.value);
|
||||
if (val) {
|
||||
this.installDate = val;
|
||||
}
|
||||
} else if (attr.name == "isCompleteUpdate") {
|
||||
this.isCompleteUpdate = attr.value == "true";
|
||||
else if (attr.name == "isSecurityUpdate")
|
||||
} else if (attr.name == "isSecurityUpdate") {
|
||||
this.isSecurityUpdate = attr.value == "true";
|
||||
else if (attr.name == "isOSUpdate")
|
||||
} else if (attr.name == "isOSUpdate") {
|
||||
this.isOSUpdate = attr.value == "true";
|
||||
else if (attr.name == "showNeverForVersion")
|
||||
} else if (attr.name == "showNeverForVersion") {
|
||||
this.showNeverForVersion = attr.value == "true";
|
||||
else if (attr.name == "showPrompt")
|
||||
} else if (attr.name == "showPrompt") {
|
||||
this.showPrompt = attr.value == "true";
|
||||
else if (attr.name == "promptWaitTime")
|
||||
{
|
||||
if(!isNaN(attr.value))
|
||||
} else if (attr.name == "promptWaitTime") {
|
||||
if(!isNaN(attr.value)) {
|
||||
this.promptWaitTime = parseInt(attr.value);
|
||||
}
|
||||
else if (attr.name == "unsupported")
|
||||
}
|
||||
} else if (attr.name == "unsupported") {
|
||||
this.unsupported = attr.value == "true";
|
||||
else if (attr.name == "version") {
|
||||
} else if (attr.name == "version") {
|
||||
// Prevent version from replacing displayVersion if displayVersion is
|
||||
// present in the update xml.
|
||||
if (!this.displayVersion)
|
||||
if (!this.displayVersion) {
|
||||
this.displayVersion = attr.value;
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
this[attr.name] = attr.value;
|
||||
|
||||
switch (attr.name) {
|
||||
case "appVersion":
|
||||
case "billboardURL":
|
||||
case "buildID":
|
||||
case "channel":
|
||||
case "displayVersion":
|
||||
case "licenseURL":
|
||||
case "name":
|
||||
case "platformVersion":
|
||||
case "previousAppVersion":
|
||||
case "serviceURL":
|
||||
case "statusText":
|
||||
case "type":
|
||||
break;
|
||||
default:
|
||||
// Save custom attributes when serializing to the local xml file but
|
||||
// don't use this method for the expected attributes which are already
|
||||
// handled in serialize.
|
||||
this.setProperty(attr.name, attr.value);
|
||||
break;
|
||||
};
|
||||
case "appVersion":
|
||||
case "billboardURL":
|
||||
case "buildID":
|
||||
case "channel":
|
||||
case "displayVersion":
|
||||
case "licenseURL":
|
||||
case "name":
|
||||
case "platformVersion":
|
||||
case "previousAppVersion":
|
||||
case "serviceURL":
|
||||
case "statusText":
|
||||
case "type":
|
||||
break;
|
||||
default:
|
||||
// Save custom attributes when serializing to the local xml file but
|
||||
// don't use this method for the expected attributes which are already
|
||||
// handled in serialize.
|
||||
this.setProperty(attr.name, attr.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the initial value with the current time when it doesn't already have a
|
||||
// value or the value is already set to 0 (bug 316328).
|
||||
if (!this.installDate && this.installDate != 0)
|
||||
this.installDate = (new Date()).getTime();
|
||||
|
||||
// The Update Name is either the string provided by the <update> element, or
|
||||
// the string: "<App Name> <Update App Version>"
|
||||
var name = "";
|
||||
if (update.hasAttribute("name"))
|
||||
if (update.hasAttribute("name")) {
|
||||
name = update.getAttribute("name");
|
||||
else {
|
||||
} else {
|
||||
var brandBundle = Services.strings.createBundle(URI_BRAND_PROPERTIES);
|
||||
var appName = brandBundle.GetStringFromName("brandShortName");
|
||||
name = gUpdateBundle.formatStringFromName("updateName",
|
||||
@ -1917,6 +1929,12 @@ Update.prototype = {
|
||||
* See nsIUpdateService.idl
|
||||
*/
|
||||
serialize: function Update_serialize(updates) {
|
||||
// If appVersion isn't defined just return null. This happens when a
|
||||
// temporary nsIUpdate is passed to the UI when the
|
||||
// app.update.showInstalledUI prefence is set to true.
|
||||
if (!this.appVersion) {
|
||||
return null;
|
||||
}
|
||||
var update = updates.createElementNS(URI_UPDATE_NS, "update");
|
||||
update.setAttribute("appVersion", this.appVersion);
|
||||
update.setAttribute("buildID", this.buildID);
|
||||
@ -1937,29 +1955,38 @@ Update.prototype = {
|
||||
update.setAttribute("version", this.displayVersion);
|
||||
|
||||
// Optional attributes
|
||||
if (this.billboardURL)
|
||||
if (this.billboardURL) {
|
||||
update.setAttribute("billboardURL", this.billboardURL);
|
||||
if (this.detailsURL)
|
||||
}
|
||||
if (this.detailsURL) {
|
||||
update.setAttribute("detailsURL", this.detailsURL);
|
||||
if (this.licenseURL)
|
||||
}
|
||||
if (this.licenseURL) {
|
||||
update.setAttribute("licenseURL", this.licenseURL);
|
||||
if (this.platformVersion)
|
||||
}
|
||||
if (this.platformVersion) {
|
||||
update.setAttribute("platformVersion", this.platformVersion);
|
||||
if (this.previousAppVersion)
|
||||
}
|
||||
if (this.previousAppVersion) {
|
||||
update.setAttribute("previousAppVersion", this.previousAppVersion);
|
||||
if (this.statusText)
|
||||
}
|
||||
if (this.statusText) {
|
||||
update.setAttribute("statusText", this.statusText);
|
||||
if (this.unsupported)
|
||||
}
|
||||
if (this.unsupported) {
|
||||
update.setAttribute("unsupported", this.unsupported);
|
||||
}
|
||||
updates.documentElement.appendChild(update);
|
||||
|
||||
for (var p in this._properties) {
|
||||
if (this._properties[p].present)
|
||||
if (this._properties[p].present) {
|
||||
update.setAttribute(p, this._properties[p].data);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.patchCount; ++i)
|
||||
for (let i = 0; i < this.patchCount; ++i) {
|
||||
update.appendChild(this.getPatchAt(i).serialize(updates));
|
||||
}
|
||||
|
||||
return update;
|
||||
},
|
||||
@ -1998,11 +2025,14 @@ Update.prototype = {
|
||||
|
||||
/**
|
||||
* See nsIPropertyBag.idl
|
||||
* Note: returns null instead of throwing when the property doesn't exist to
|
||||
* simplify code and to silence warnings in debug builds.
|
||||
*/
|
||||
getProperty: function Update_getProperty(name) {
|
||||
if (name in this._properties && this._properties[name].present)
|
||||
if (name in this._properties && this._properties[name].present) {
|
||||
return this._properties[name].data;
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdate,
|
||||
@ -2081,41 +2111,41 @@ UpdateService.prototype = {
|
||||
*/
|
||||
observe: function AUS_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "post-update-processing":
|
||||
// Clean up any extant updates
|
||||
this._postUpdateProcessing();
|
||||
break;
|
||||
case "network:offline-status-changed":
|
||||
this._offlineStatusChanged(data);
|
||||
break;
|
||||
case "nsPref:changed":
|
||||
if (data == PREF_APP_UPDATE_LOG) {
|
||||
gLogEnabled = getPref("getBoolPref", PREF_APP_UPDATE_LOG, false);
|
||||
}
|
||||
break;
|
||||
case "post-update-processing":
|
||||
// Clean up any extant updates
|
||||
this._postUpdateProcessing();
|
||||
break;
|
||||
case "network:offline-status-changed":
|
||||
this._offlineStatusChanged(data);
|
||||
break;
|
||||
case "nsPref:changed":
|
||||
if (data == PREF_APP_UPDATE_LOG) {
|
||||
gLogEnabled = getPref("getBoolPref", PREF_APP_UPDATE_LOG, false);
|
||||
}
|
||||
break;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
case "profile-change-net-teardown": // fall thru
|
||||
case "profile-change-net-teardown": // fall thru
|
||||
#endif
|
||||
case "xpcom-shutdown":
|
||||
Services.obs.removeObserver(this, topic);
|
||||
Services.prefs.removeObserver(PREF_APP_UPDATE_LOG, this);
|
||||
case "xpcom-shutdown":
|
||||
Services.obs.removeObserver(this, topic);
|
||||
Services.prefs.removeObserver(PREF_APP_UPDATE_LOG, this);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// If we hold the update mutex, let it go!
|
||||
// The OS would clean this up sometime after shutdown,
|
||||
// but that would have no guarantee on timing.
|
||||
if (gUpdateMutexHandle) {
|
||||
closeHandle(gUpdateMutexHandle);
|
||||
}
|
||||
// If we hold the update mutex, let it go!
|
||||
// The OS would clean this up sometime after shutdown,
|
||||
// but that would have no guarantee on timing.
|
||||
if (gUpdateMutexHandle) {
|
||||
closeHandle(gUpdateMutexHandle);
|
||||
}
|
||||
#endif
|
||||
if (this._retryTimer) {
|
||||
this._retryTimer.cancel();
|
||||
}
|
||||
if (this._retryTimer) {
|
||||
this._retryTimer.cancel();
|
||||
}
|
||||
|
||||
this.pauseDownload();
|
||||
// Prevent leaking the downloader (bug 454964)
|
||||
this._downloader = null;
|
||||
break;
|
||||
this.pauseDownload();
|
||||
// Prevent leaking the downloader (bug 454964)
|
||||
this._downloader = null;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -3217,11 +3247,8 @@ UpdateService.prototype = {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
let osApplyToDir;
|
||||
try {
|
||||
aUpdate.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
osApplyToDir = aUpdate.getProperty("osApplyToDir");
|
||||
} catch (e) {}
|
||||
aUpdate.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
let osApplyToDir = aUpdate.getProperty("osApplyToDir");
|
||||
|
||||
if (!osApplyToDir) {
|
||||
LOG("UpdateService:applyOsUpdate - Error: osApplyToDir is not defined" +
|
||||
@ -3478,8 +3505,9 @@ UpdateManager.prototype = {
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
var modeFlags = FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE |
|
||||
FileUtils.MODE_TRUNCATE;
|
||||
if (!file.exists())
|
||||
if (!file.exists()) {
|
||||
file.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
|
||||
}
|
||||
fos.init(file, modeFlags, FileUtils.PERMS_FILE, 0);
|
||||
|
||||
try {
|
||||
@ -3489,15 +3517,18 @@ UpdateManager.prototype = {
|
||||
var doc = parser.parseFromString(EMPTY_UPDATES_DOCUMENT, "text/xml");
|
||||
|
||||
for (var i = 0; i < updates.length; ++i) {
|
||||
if (updates[i])
|
||||
// If appVersion isn't defined don't add the update. This happens when a
|
||||
// temporary nsIUpdate is passed to the UI when the
|
||||
// app.update.showInstalledUI prefence is set to true.
|
||||
if (updates[i] && updates[i].appVersion) {
|
||||
doc.documentElement.appendChild(updates[i].serialize(doc));
|
||||
}
|
||||
}
|
||||
|
||||
var serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].
|
||||
createInstance(Ci.nsIDOMSerializer);
|
||||
serializer.serializeToStream(doc.documentElement, fos, null);
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
FileUtils.closeSafeFileOutputStream(fos);
|
||||
@ -3829,7 +3860,7 @@ Checker.prototype = {
|
||||
if (this._isHttpStatusCode(status)) {
|
||||
update.errorCode = HTTP_ERROR_OFFSET + status;
|
||||
}
|
||||
if (e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
|
||||
if (e.result && e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
|
||||
update.errorCode = updates[0] ? CERT_ATTR_CHECK_FAILED_HAS_UPDATE
|
||||
: CERT_ATTR_CHECK_FAILED_NO_UPDATE;
|
||||
}
|
||||
@ -3896,13 +3927,13 @@ Checker.prototype = {
|
||||
this._request.abort();
|
||||
|
||||
switch (duration) {
|
||||
case Ci.nsIUpdateChecker.CURRENT_SESSION:
|
||||
this._enabled = false;
|
||||
break;
|
||||
case Ci.nsIUpdateChecker.ANY_CHECKS:
|
||||
this._enabled = false;
|
||||
Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, this._enabled);
|
||||
break;
|
||||
case Ci.nsIUpdateChecker.CURRENT_SESSION:
|
||||
this._enabled = false;
|
||||
break;
|
||||
case Ci.nsIUpdateChecker.ANY_CHECKS:
|
||||
this._enabled = false;
|
||||
Services.prefs.setBoolPref(PREF_APP_UPDATE_ENABLED, this._enabled);
|
||||
break;
|
||||
}
|
||||
|
||||
this._callback = null;
|
||||
@ -3981,10 +4012,11 @@ Downloader.prototype = {
|
||||
*/
|
||||
_verifyDownload: function Downloader__verifyDownload() {
|
||||
LOG("Downloader:_verifyDownload called");
|
||||
if (!this._request)
|
||||
if (!this._request) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var destination = this._request.destination;
|
||||
let destination = this._request.destination;
|
||||
|
||||
// Ensure that the file size matches the expected file size.
|
||||
if (destination.fileSize != this._patch.size) {
|
||||
@ -3993,16 +4025,18 @@ Downloader.prototype = {
|
||||
}
|
||||
|
||||
LOG("Downloader:_verifyDownload downloaded size == expected size.");
|
||||
var fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
fileStream.init(destination, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
|
||||
|
||||
let digest;
|
||||
try {
|
||||
var hash = Cc["@mozilla.org/security/hash;1"].
|
||||
let hash = Cc["@mozilla.org/security/hash;1"].
|
||||
createInstance(Ci.nsICryptoHash);
|
||||
var hashFunction = Ci.nsICryptoHash[this._patch.hashFunction.toUpperCase()];
|
||||
if (hashFunction == undefined)
|
||||
if (hashFunction == undefined) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
hash.init(hashFunction);
|
||||
hash.updateFromStream(fileStream, -1);
|
||||
// NOTE: For now, we assume that the format of _patch.hashValue is hex
|
||||
@ -4069,35 +4103,35 @@ Downloader.prototype = {
|
||||
LOG("Downloader:_selectPatch - found existing patch with state: " +
|
||||
state);
|
||||
switch (state) {
|
||||
case STATE_DOWNLOADING:
|
||||
LOG("Downloader:_selectPatch - resuming download");
|
||||
return selectedPatch;
|
||||
case STATE_DOWNLOADING:
|
||||
LOG("Downloader:_selectPatch - resuming download");
|
||||
return selectedPatch;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
case STATE_PENDING:
|
||||
case STATE_APPLYING:
|
||||
LOG("Downloader:_selectPatch - resuming interrupted apply");
|
||||
return selectedPatch;
|
||||
case STATE_APPLIED:
|
||||
LOG("Downloader:_selectPatch - already downloaded and staged");
|
||||
return null;
|
||||
#else
|
||||
case STATE_PENDING_SVC:
|
||||
case STATE_PENDING:
|
||||
LOG("Downloader:_selectPatch - already downloaded and staged");
|
||||
return null;
|
||||
#endif
|
||||
default:
|
||||
// Something went wrong when we tried to apply the previous patch.
|
||||
// Try the complete patch next time.
|
||||
if (update && selectedPatch.type == "partial") {
|
||||
useComplete = true;
|
||||
} else {
|
||||
// This is a pretty fatal error. Just bail.
|
||||
LOG("Downloader:_selectPatch - failed to apply complete patch!");
|
||||
writeStatusFile(updateDir, STATE_NONE);
|
||||
writeVersionFile(getUpdatesDir(), null);
|
||||
case STATE_PENDING:
|
||||
case STATE_APPLYING:
|
||||
LOG("Downloader:_selectPatch - resuming interrupted apply");
|
||||
return selectedPatch;
|
||||
case STATE_APPLIED:
|
||||
LOG("Downloader:_selectPatch - already downloaded and staged");
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
case STATE_PENDING_SVC:
|
||||
case STATE_PENDING:
|
||||
LOG("Downloader:_selectPatch - already downloaded and staged");
|
||||
return null;
|
||||
#endif
|
||||
default:
|
||||
// Something went wrong when we tried to apply the previous patch.
|
||||
// Try the complete patch next time.
|
||||
if (update && selectedPatch.type == "partial") {
|
||||
useComplete = true;
|
||||
} else {
|
||||
// This is a pretty fatal error. Just bail.
|
||||
LOG("Downloader:_selectPatch - failed to apply complete patch!");
|
||||
writeStatusFile(updateDir, STATE_NONE);
|
||||
writeVersionFile(getUpdatesDir(), null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
selectedPatch = null;
|
||||
@ -4571,14 +4605,8 @@ Downloader.prototype = {
|
||||
// notify the user about the error. If the update was a background
|
||||
// update there is no notification since the user won't be expecting it.
|
||||
if (!Services.wm.getMostRecentWindow(UPDATE_WINDOW_NAME)) {
|
||||
try {
|
||||
this._update.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
var fgdl = this._update.getProperty("foregroundDownload");
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
|
||||
if (fgdl == "true") {
|
||||
this._update.QueryInterface(Ci.nsIWritablePropertyBag);
|
||||
if (this._update.getProperty("foregroundDownload") == "true") {
|
||||
var prompter = Cc["@mozilla.org/updates/update-prompt;1"].
|
||||
createInstance(Ci.nsIUpdatePrompt);
|
||||
prompter.showUpdateError(this._update);
|
||||
|
@ -114,6 +114,8 @@
|
||||
* install completes.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
// The tests have to use the pageid instead of the pageIndex due to the
|
||||
@ -158,7 +160,6 @@ const PREF_APP_UPDATE_LASTUPDATETIME = "app.update.lastUpdateTime.background-upd
|
||||
// from interefering with the tests.
|
||||
const PREF_DISABLEDADDONS = "app.update.test.disabledAddons";
|
||||
const PREF_EM_HOTFIX_ID = "extensions.hotfix.id";
|
||||
const PREF_EM_SILENT = "app.update.silent";
|
||||
const TEST_ADDONS = [ "appdisabled_1", "appdisabled_2",
|
||||
"compatible_1", "compatible_2",
|
||||
"noupdate_1", "noupdate_2",
|
||||
@ -922,9 +923,9 @@ function setupPrefs() {
|
||||
|
||||
Services.prefs.setIntPref(PREF_APP_UPDATE_IDLETIME, 0);
|
||||
Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 0);
|
||||
Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, false);
|
||||
Services.prefs.setBoolPref(PREF_EXTENSIONS_STRICT_COMPAT, true);
|
||||
Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, "hotfix" + ADDON_ID_SUFFIX);
|
||||
Services.prefs.setBoolPref(PREF_EM_SILENT, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1078,6 +1079,10 @@ function resetPrefs() {
|
||||
catch(e) {
|
||||
}
|
||||
|
||||
if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SILENT)) {
|
||||
Services.prefs.clearUserPref(PREF_APP_UPDATE_SILENT);
|
||||
}
|
||||
|
||||
if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_STRICT_COMPAT)) {
|
||||
Services.prefs.clearUserPref(PREF_EXTENSIONS_STRICT_COMPAT);
|
||||
}
|
||||
@ -1085,10 +1090,6 @@ function resetPrefs() {
|
||||
if (Services.prefs.prefHasUserValue(PREF_EM_HOTFIX_ID)) {
|
||||
Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID);
|
||||
}
|
||||
|
||||
if (Services.prefs.prefHasUserValue(PREF_EM_SILENT)) {
|
||||
Services.prefs.clearUserPref(PREF_EM_SILENT);
|
||||
}
|
||||
}
|
||||
|
||||
function setupTimer(aTestTimeout) {
|
||||
@ -1187,7 +1188,7 @@ function setupAddons(aCallback) {
|
||||
|
||||
if (--xpiCount == 0) {
|
||||
let installCount = installs.length;
|
||||
function installCompleted(aInstall) {
|
||||
let installCompleted = function(aInstall) {
|
||||
aInstall.removeListener(listener);
|
||||
|
||||
if (getAddonTestType(aInstall.addon.name) == "userdisabled") {
|
||||
@ -1196,7 +1197,7 @@ function setupAddons(aCallback) {
|
||||
if (--installCount == 0) {
|
||||
setNoUpdateAddonsDisabledState();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let listener = {
|
||||
onDownloadFailed: installCompleted,
|
||||
|
@ -36,15 +36,6 @@ class AutoLocalJNIFrame;
|
||||
|
||||
void InitAndroidJavaWrappers(JNIEnv *jEnv);
|
||||
|
||||
/*
|
||||
* Note: do not store global refs to any WrappedJavaObject;
|
||||
* these are live only during a particular JNI method, as
|
||||
* NewGlobalRef is -not- called on the jobject.
|
||||
*
|
||||
* If this is needed, WrappedJavaObject can be extended to
|
||||
* handle it.
|
||||
*/
|
||||
|
||||
class RefCountedJavaObject {
|
||||
public:
|
||||
RefCountedJavaObject(JNIEnv* env, jobject obj) : mRefCnt(0), mObject(env->NewGlobalRef(obj)) {}
|
||||
@ -66,6 +57,14 @@ private:
|
||||
jobject mObject;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: do not store global refs to any WrappedJavaObject;
|
||||
* these are live only during a particular JNI method, as
|
||||
* NewGlobalRef is -not- called on the jobject.
|
||||
*
|
||||
* If this is needed, WrappedJavaObject can be extended to
|
||||
* handle it.
|
||||
*/
|
||||
class WrappedJavaObject {
|
||||
public:
|
||||
WrappedJavaObject() :
|
||||
|
@ -234,10 +234,14 @@ WindowsOSVersion()
|
||||
|
||||
if (winVersion == UNINITIALIZED_VALUE) {
|
||||
vinfo.dwOSVersionInfoSize = sizeof (vinfo);
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4996)
|
||||
#endif
|
||||
if (!GetVersionEx(&vinfo)) {
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
winVersion = kWindowsUnknown;
|
||||
} else {
|
||||
winVersion = int32_t(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion;
|
||||
|
@ -237,7 +237,6 @@ nsresult JumpListBuilder::RemoveIconCacheForAllItems()
|
||||
if (NS_FAILED(currFile->GetPath(path)))
|
||||
continue;
|
||||
|
||||
int32_t len = path.Length();
|
||||
if (StringTail(path, 4).LowerCaseEqualsASCII(".ico")) {
|
||||
// Check if the cached ICO file exists
|
||||
bool exists;
|
||||
|
@ -1625,7 +1625,6 @@ NativeKey::HandleCharMessage(const MSG& aCharMsg,
|
||||
// Bug 50255 and Bug 351310: Keep the characters unshifted for shortcuts and
|
||||
// accesskeys and make sure that numbers are always passed as such.
|
||||
if (uniChar && (mModKeyState.IsControl() || mModKeyState.IsAlt())) {
|
||||
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
|
||||
char16_t unshiftedCharCode =
|
||||
(mVirtualKeyCode >= '0' && mVirtualKeyCode <= '9') ?
|
||||
mVirtualKeyCode : mModKeyState.IsShift() ?
|
||||
@ -2126,7 +2125,6 @@ NativeKey::DispatchKeyPressEventsWithKeyboardLayout() const
|
||||
uint32_t skipUniChars = longestLength - inputtingChars.mLength;
|
||||
uint32_t skipShiftedChars = longestLength - shiftedChars.mLength;
|
||||
uint32_t skipUnshiftedChars = longestLength - unshiftedChars.mLength;
|
||||
UINT keyCode = !inputtingChars.mLength ? mDOMKeyCode : 0;
|
||||
bool defaultPrevented = false;
|
||||
for (uint32_t cnt = 0; cnt < longestLength; cnt++) {
|
||||
uint16_t uniChar, shiftedChar, unshiftedChar;
|
||||
|
@ -295,8 +295,8 @@ private:
|
||||
|
||||
private:
|
||||
bool mInitialized;
|
||||
int32_t mScrollLines;
|
||||
int32_t mScrollChars;
|
||||
uint32_t mScrollLines;
|
||||
uint32_t mScrollChars;
|
||||
};
|
||||
|
||||
SystemSettings mSystemSettings;
|
||||
|
@ -481,12 +481,11 @@ WinUtils::LogW(const wchar_t *fmt, ...)
|
||||
OutputDebugStringW(buffer);
|
||||
OutputDebugStringW(L"\n");
|
||||
|
||||
int len = wcslen(buffer);
|
||||
int len = WideCharToMultiByte(CP_ACP, 0, buffer, -1, nullptr, 0, nullptr, nullptr);
|
||||
if (len) {
|
||||
char* utf8 = new char[len+1];
|
||||
memset(utf8, 0, sizeof(utf8));
|
||||
char* utf8 = new char[len];
|
||||
if (WideCharToMultiByte(CP_ACP, 0, buffer,
|
||||
-1, utf8, len+1, nullptr,
|
||||
-1, utf8, len, nullptr,
|
||||
nullptr) > 0) {
|
||||
// desktop console
|
||||
printf("%s\n", utf8);
|
||||
@ -1077,11 +1076,11 @@ WinUtils::InvalidatePluginAsWorkaround(nsIWidget *aWidget, const nsIntRect &aRec
|
||||
}
|
||||
|
||||
#ifdef MOZ_PLACES
|
||||
/************************************************************************/
|
||||
/* Constructs as AsyncFaviconDataReady Object
|
||||
/* @param aIOThread : the thread which performs the action
|
||||
/* @param aURLShortcut : Differentiates between (false)Jumplistcache and (true)Shortcutcache
|
||||
/************************************************************************/
|
||||
/************************************************************************
|
||||
* Constructs as AsyncFaviconDataReady Object
|
||||
* @param aIOThread : the thread which performs the action
|
||||
* @param aURLShortcut : Differentiates between (false)Jumplistcache and (true)Shortcutcache
|
||||
************************************************************************/
|
||||
|
||||
AsyncFaviconDataReady::AsyncFaviconDataReady(nsIURI *aNewURI,
|
||||
nsCOMPtr<nsIThread> &aIOThread,
|
||||
|
@ -29,7 +29,7 @@ using namespace mozilla::widget;
|
||||
// A wake lock listener that disables screen saver when requested by
|
||||
// Gecko. For example when we're playing video in a foreground tab we
|
||||
// don't want the screen saver to turn on.
|
||||
class WinWakeLockListener : public nsIDOMMozWakeLockListener {
|
||||
class WinWakeLockListener MOZ_FINAL : public nsIDOMMozWakeLockListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS;
|
||||
|
||||
|
@ -51,6 +51,10 @@ class nsDataObjCollection MOZ_FINAL : public nsIDataObjCollection, public nsData
|
||||
virtual HRESULT GetFileContents(LPFORMATETC pFE, LPSTGMEDIUM pSTM);
|
||||
virtual HRESULT GetFirstSupporting(LPFORMATETC pFE, LPSTGMEDIUM pSTM);
|
||||
|
||||
using nsDataObj::GetFile;
|
||||
using nsDataObj::GetFileContents;
|
||||
using nsDataObj::GetText;
|
||||
|
||||
// support for clipboard
|
||||
void AddDataFlavor(const char * aDataFlavor, LPFORMATETC aFE);
|
||||
|
||||
|
@ -573,6 +573,8 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID,
|
||||
case LookAndFeel::eFont_Tooltips:
|
||||
ptrLogFont = &ncm.lfStatusFont;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1025,7 +1025,6 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
|
||||
case NS_THEME_PROGRESSBAR_CHUNK:
|
||||
case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL: {
|
||||
nsIFrame* parentFrame = aFrame->GetParent();
|
||||
EventStates eventStates = GetContentState(parentFrame, aWidgetType);
|
||||
if (aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
|
||||
IsVerticalProgress(parentFrame)) {
|
||||
aPart = IsVistaOrLater() ?
|
||||
@ -1463,12 +1462,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
|
||||
case NS_THEME_MENUCHECKBOX:
|
||||
case NS_THEME_MENURADIO:
|
||||
{
|
||||
bool isChecked;
|
||||
EventStates eventState = GetContentState(aFrame, aWidgetType);
|
||||
|
||||
// NOTE: we can probably use NS_EVENT_STATE_CHECKED
|
||||
isChecked = CheckBooleanAttr(aFrame, nsGkAtoms::checked);
|
||||
|
||||
aPart = MENU_POPUPCHECK;
|
||||
aState = MC_CHECKMARKNORMAL;
|
||||
|
||||
@ -3178,7 +3173,6 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, uint8_t
|
||||
case NS_THEME_RADIOMENUITEM: {
|
||||
bool isTopLevel = false;
|
||||
bool isOpen = false;
|
||||
bool isContainer = false;
|
||||
nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
|
||||
EventStates eventState = GetContentState(aFrame, aWidgetType);
|
||||
|
||||
@ -3194,7 +3188,6 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, uint8_t
|
||||
// rendering.
|
||||
isTopLevel = menuFrame->IsOnMenuBar();
|
||||
isOpen = menuFrame->IsOpen();
|
||||
isContainer = menuFrame->IsMenu();
|
||||
}
|
||||
|
||||
if (IsDisabled(aFrame, eventState))
|
||||
@ -3477,6 +3470,8 @@ static void DrawTab(HDC hdc, const RECT& R, int32_t aPosition, bool aSelected,
|
||||
::SetRect(&lightRect, R.left, R.bottom-3, R.left+2, R.bottom-1);
|
||||
::SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// Background
|
||||
@ -3812,7 +3807,6 @@ RENDER_AGAIN:
|
||||
bool indeterminate = IsIndeterminateProgress(stateFrame, eventStates);
|
||||
bool vertical = IsVerticalProgress(stateFrame) ||
|
||||
aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL;
|
||||
int32_t overlayPart = GetProgressOverlayStyle(vertical);
|
||||
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (!indeterminate || !content) {
|
||||
|
@ -1173,11 +1173,11 @@ bool nsTextStore::sDoNotReturnNoLayoutErrorToEasyChangjei = false;
|
||||
#define TEXTSTORE_DEFAULT_VIEW (1)
|
||||
|
||||
nsTextStore::nsTextStore()
|
||||
: mLockedContent(mComposition, mSelection)
|
||||
, mEditCookie(0)
|
||||
: mEditCookie(0)
|
||||
, mSinkMask(0)
|
||||
, mLock(0)
|
||||
, mLockQueued(0)
|
||||
, mLockedContent(mComposition, mSelection)
|
||||
, mRequestedAttrValues(false)
|
||||
, mIsRecordingActionsWithoutLock(false)
|
||||
, mPendingOnSelectionChange(false)
|
||||
|
@ -1701,8 +1701,6 @@ NS_METHOD nsWindow::ConstrainPosition(bool aAllowSlop,
|
||||
int32_t logWidth = std::max<int32_t>(NSToIntRound(mBounds.width / dpiScale), 1);
|
||||
int32_t logHeight = std::max<int32_t>(NSToIntRound(mBounds.height / dpiScale), 1);
|
||||
|
||||
bool doConstrain = false; // whether we have enough info to do anything
|
||||
|
||||
/* get our playing field. use the current screen, or failing that
|
||||
for any reason, use device caps for the default screen. */
|
||||
RECT screenRect;
|
||||
@ -1726,7 +1724,6 @@ NS_METHOD nsWindow::ConstrainPosition(bool aAllowSlop,
|
||||
screenRect.right = left + width;
|
||||
screenRect.top = top;
|
||||
screenRect.bottom = top + height;
|
||||
doConstrain = true;
|
||||
}
|
||||
} else {
|
||||
if (mWnd) {
|
||||
@ -1740,7 +1737,6 @@ NS_METHOD nsWindow::ConstrainPosition(bool aAllowSlop,
|
||||
screenRect.right = GetSystemMetrics(SM_CXFULLSCREEN);
|
||||
screenRect.bottom = GetSystemMetrics(SM_CYFULLSCREEN);
|
||||
}
|
||||
doConstrain = true;
|
||||
}
|
||||
::ReleaseDC(mWnd, dc);
|
||||
}
|
||||
@ -2701,6 +2697,8 @@ void nsWindow::UpdateGlass()
|
||||
case eTransparencyGlass:
|
||||
policy = DWMNCRP_ENABLED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
|
||||
@ -5179,7 +5177,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
||||
*aRetValue = 0;
|
||||
// Do explicit casting to make it working on 64bit systems (see bug 649236
|
||||
// for details).
|
||||
DWORD objId = static_cast<DWORD>(lParam);
|
||||
int32_t objId = static_cast<DWORD>(lParam);
|
||||
if (objId == OBJID_CLIENT) { // oleacc.dll will be loaded dynamically
|
||||
a11y::Accessible* rootAccessible = GetAccessible(); // Held by a11y cache
|
||||
if (rootAccessible) {
|
||||
@ -6568,8 +6566,6 @@ nsWindow::GetPreferredCompositorBackends(nsTArray<LayersBackend>& aHints)
|
||||
aHints.AppendElement(LayersBackend::LAYERS_OPENGL);
|
||||
}
|
||||
|
||||
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
|
||||
|
||||
if (!prefs.mPreferD3D9) {
|
||||
aHints.AppendElement(LayersBackend::LAYERS_D3D11);
|
||||
}
|
||||
|
@ -90,6 +90,8 @@ public:
|
||||
virtual nsWindowBase* GetParentWindowBase(bool aIncludeOwner) MOZ_OVERRIDE;
|
||||
virtual bool IsTopLevelWidget() MOZ_OVERRIDE { return mIsTopWidgetWindow; }
|
||||
|
||||
using nsWindowBase::DispatchPluginEvent;
|
||||
|
||||
// nsIWidget interface
|
||||
NS_IMETHOD Create(nsIWidget *aParent,
|
||||
nsNativeWidget aNativeParent,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user