Merge last green PGO build from mozilla-inbound to mozilla-central

This commit is contained in:
Marco Bonardo 2011-12-29 12:02:01 +01:00
commit 532fd7b9d2
116 changed files with 2561 additions and 679 deletions

View File

@ -147,6 +147,7 @@
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_b2g.xpt
#endif
@BINPATH@/components/dom_battery.xpt
@ -396,6 +397,8 @@
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
@BINPATH@/components/nsWifiWorker.js
@BINPATH@/components/nsWifiWorker.manifest
#endif
#ifdef XP_MACOSX
@BINPATH@/components/libalerts_s.dylib

View File

@ -47,14 +47,7 @@ tabbrowser {
.tab-label:not([fadein]):not([pinned]),
.tab-icon-image:not([fadein]):not([pinned]),
.tab-close-button:not([fadein]):not([pinned]) {
opacity: 0 !important;
}
.tab-throbber,
.tab-label,
.tab-icon-image,
.tab-close-button {
-moz-transition: opacity 250ms;
display: none;
}
.tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {

View File

@ -398,20 +398,20 @@
<tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
<tooltip id="back-button-tooltip">
<label value="&backButton.tooltip;"/>
<label class="tooltip-label" value="&backButton.tooltip;"/>
#ifdef XP_MACOSX
<label value="&backForwardButtonMenuMac.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
#else
<label value="&backForwardButtonMenu.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
#endif
</tooltip>
<tooltip id="forward-button-tooltip">
<label value="&forwardButton.tooltip;"/>
<label class="tooltip-label" value="&forwardButton.tooltip;"/>
#ifdef XP_MACOSX
<label value="&backForwardButtonMenuMac.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenuMac.tooltip;"/>
#else
<label value="&backForwardButtonMenu.tooltip;"/>
<label class="tooltip-label" value="&backForwardButtonMenu.tooltip;"/>
#endif
</tooltip>
</popupset>

View File

@ -138,6 +138,7 @@
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_b2g.xpt
#endif
@BINPATH@/components/dom_battery.xpt
@ -366,6 +367,8 @@
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
@BINPATH@/components/nsWifiWorker.js
@BINPATH@/components/nsWifiWorker.manifest
#endif
@BINPATH@/components/BrowserProfileMigrators.manifest
@BINPATH@/components/ChromeProfileMigrator.js

View File

@ -70,6 +70,7 @@ components/pluginGlue.js
components/sidebar.xpt
#ifdef MOZ_B2G_RIL
components/dom_telephony.xpt
components/dom_wifi.xpt
components/dom_system_b2g.xpt
#endif
components/uconvd.dll
@ -922,6 +923,8 @@ xpicleanup@BIN_SUFFIX@
components/nsTelephonyWorker.js
components/Telephony.manifest
components/Telephony.js
components/nsWifiWorker.js
components/nsWifiWorker.manifest
#endif
components/txEXSLTRegExFunctions.js
components/Weave.js
@ -1143,6 +1146,7 @@ xpicleanup@BIN_SUFFIX@
components/dom_base.xpt
#ifdef MOZ_B2G_RIL
components/dom_telephony.xpt
components/dom_wifi.xpt
components/dom_system_b2g.xpt
#endif
components/dom_canvas.xpt

View File

@ -1864,15 +1864,20 @@ if test "$GNU_CC"; then
_MOZ_RTTI_FLAGS_ON=-frtti
_MOZ_RTTI_FLAGS_OFF=-fno-rtti
# Turn on GNU specific features
# -Wall - turn on all warnings
# -pedantic - make compiler warn about non-ANSI stuff, and
# be a little bit stricter
# -Wdeclaration-after-statement - MSVC doesn't like these
# Warnings slamm took out for now (these were giving more noise than help):
# -Wbad-function-cast - warns when casting a function to a new return type
# -Wshadow - removed because it generates more noise than help --pete
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -W -Wno-unused -Wpointer-arith -Wdeclaration-after-statement"
# Turn on GNU-specific warnings:
# -Wall - turn on a lot of warnings
# -pedantic - this is turned on below
# -Wpointer-arith - enabled with -pedantic, but good to have even if not
# -Werror=declaration-after-statement - MSVC doesn't like these
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
#
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement -Wempty-body"
# Turn off the following warnings that -Wall/-pedantic turn on:
# -Woverlength-strings - we exceed the minimum maximum length all the time
#
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wno-overlength-strings"
if test -z "$INTEL_CC" -a -z "$CLANG_CC"; then
# Don't use -Wcast-align with ICC or clang
case "$CPU_ARCH" in
@ -1888,12 +1893,26 @@ if test "$GNU_CC"; then
dnl Turn pedantic on but disable the warnings for long long
_PEDANTIC=1
if test -z "$INTEL_CC"; then
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -W"
fi
_DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT'
_USE_CPP_INCLUDE_FLAG=1
AC_CACHE_CHECK(whether the compiler supports -Wtype-limits,
ac_cc_has_wtype_limits,
[
AC_LANG_SAVE
AC_LANG_C
_SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wtype-limits"
AC_TRY_COMPILE([],
[return(0);],
ac_cc_has_wtype_limits="yes",
ac_cc_has_wtype_limits="no")
CFLAGS="$_SAVE_CFLAGS"
AC_LANG_RESTORE
])
if test "$ac_cc_has_wtype_limits" = "yes"; then
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wtype-limits"
fi
elif test "$SOLARIS_SUNPRO_CC"; then
DSO_CFLAGS=''
if test "$CPU_ARCH" = "sparc"; then
@ -1921,8 +1940,22 @@ fi
if test "$GNU_CXX"; then
# FIXME: Let us build with strict aliasing. bug 414641.
CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-strict-aliasing"
# Turn on GNU specific features
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor"
# Turn on GNU-specific warnings:
# -Wall - turn on a lot of warnings
# -pedantic - this is turned on below
# -Wpointer-arith - enabled with -pedantic, but good to have even if not
# -Woverloaded-virtual - ???
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
#
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual -Wempty-body"
# Turn off the following warnings that -Wall/-pedantic turn on:
# -Woverlength-strings - we exceed the minimum maximum length all the time
# -Wctor-dtor-privacy - ???
#
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-overlength-strings -Wno-ctor-dtor-privacy"
if test -z "$INTEL_CXX" -a -z "$CLANG_CXX"; then
# Don't use -Wcast-align with ICC or clang
case "$CPU_ARCH" in
@ -2023,6 +2056,24 @@ if test "$GNU_CXX"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=return-type"
fi
AC_CACHE_CHECK(whether the compiler supports -Wtype-limits,
ac_has_wtype_limits,
[
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
_SAVE_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -Wtype-limits"
AC_TRY_COMPILE([],
[return(0);],
ac_has_wtype_limits="yes",
ac_has_wtype_limits="no")
CXXFLAGS="$_SAVE_CXXFLAGS"
AC_LANG_RESTORE
])
if test "$ac_has_wtype_limits" = "yes"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wtype-limits"
fi
else
_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_MOZILLA_CONFIG_H_ $(ACDEFINES)'
fi

View File

@ -102,8 +102,7 @@ protected:
const txExpandedName key()
{
NS_ASSERTION(mCurrentPos >= 0 &&
mCurrentPos < mMap.mItems.Length(),
NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
"invalid position in txExpandedNameMap::iterator");
return txExpandedName(mMap.mItems[mCurrentPos].mNamespaceID,
mMap.mItems[mCurrentPos].mLocalName);
@ -112,8 +111,7 @@ protected:
protected:
void* itemValue()
{
NS_ASSERTION(mCurrentPos >= 0 &&
mCurrentPos < mMap.mItems.Length(),
NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
"invalid position in txExpandedNameMap::iterator");
return mMap.mItems[mCurrentPos].mValue;
}

View File

@ -84,7 +84,10 @@ DIRS += \
$(NULL)
ifdef MOZ_B2G_RIL #{
DIRS += telephony
DIRS += \
telephony \
wifi \
$(NULL)
endif #}
ifdef ENABLE_TESTS

View File

@ -1035,6 +1035,14 @@ Navigator::SizeOf() const
return size;
}
void
Navigator::SetWindow(nsPIDOMWindow *aInnerWindow)
{
NS_ASSERTION(aInnerWindow->IsInnerWindow(),
"Navigator must get an inner window!");
mWindow = do_GetWeakReference(aInnerWindow);
}
} // namespace dom
} // namespace mozilla

View File

@ -103,6 +103,11 @@ public:
PRInt64 SizeOf() const;
/**
* For use during document.write where our inner window changes.
*/
void SetWindow(nsPIDOMWindow *aInnerWindow);
private:
bool IsSmsAllowed() const;
bool IsSmsSupported() const;

View File

@ -1679,6 +1679,25 @@ jsid nsDOMClassInfo::sMultiEntry_id = JSID_VOID;
jsid nsDOMClassInfo::sOnload_id = JSID_VOID;
jsid nsDOMClassInfo::sOnerror_id = JSID_VOID;
static const JSClass *sObjectClass = nsnull;
/**
* Set our JSClass pointer for the Object class
*/
static void
FindObjectClass(JSObject* aGlobalObject)
{
NS_ASSERTION(!sObjectClass,
"Double set of sObjectClass");
JSObject *obj, *proto = aGlobalObject;
do {
obj = proto;
proto = js::GetObjectProto(obj);
} while (proto);
sObjectClass = js::GetObjectJSClass(obj);
}
static void
PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
{
@ -4702,52 +4721,6 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
nsScriptNameSpaceManager *nameSpaceManager,
JSObject *dot_prototype, bool install, bool *did_resolve);
static nsresult
LookupPrototypeProto(JSContext *cx, JSObject *winobj,
const nsDOMClassInfoData *ci_data,
const nsGlobalNameStruct *name_struct,
JSObject **aProtoProto);
static nsGlobalWindow*
FindUsableInnerWindow(nsIXPConnect *xpc, JSContext *cx, JSObject *global)
{
// Only do this if the global object is a window.
// XXX Is there a better way to check this?
nsISupports *globalNative = xpc->GetNativeOfWrapper(cx, global);
nsCOMPtr<nsPIDOMWindow> piwin = do_QueryInterface(globalNative);
if (!piwin) {
return nsnull;
}
nsGlobalWindow *win = nsGlobalWindow::FromSupports(globalNative);
if (win->IsClosedOrClosing()) {
return nsnull;
}
// If the window is in a different compartment than the global object, then
// it's likely that global is a sandbox object whose prototype is a window.
// Don't do anything in this case.
if (win->FastGetGlobalJSObject() &&
js::GetObjectCompartment(global) != js::GetObjectCompartment(win->FastGetGlobalJSObject())) {
return nsnull;
}
if (win->IsOuterWindow()) {
// XXXjst: Do security checks here when we remove the security
// checks on the inner window.
win = win->GetCurrentInnerWindowInternal();
JSObject* global;
if (!win || !(global = win->GetGlobalJSObject()) ||
win->IsClosedOrClosing()) {
return nsnull;
}
}
return win;
}
NS_IMETHODIMP
nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
@ -4766,6 +4739,19 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
JS_ClearPendingException(cx);
}
// This is called before any other location that requires
// sObjectClass, so compute it here. We assume that nobody has had a
// chance to monkey around with proto's prototype chain before this.
if (!sObjectClass) {
FindObjectClass(proto);
NS_ASSERTION(sObjectClass && !strcmp(sObjectClass->name, "Object"),
"Incorrect object class!");
}
NS_ASSERTION(::JS_GetPrototype(cx, proto) &&
JS_GET_CLASS(cx, ::JS_GetPrototype(cx, proto)) == sObjectClass,
"Hmm, somebody did something evil?");
#ifdef DEBUG
if (mData->mHasClassInterface && mData->mProtoChainInterface &&
mData->mProtoChainInterface != &NS_GET_IID(nsISupports)) {
@ -4793,12 +4779,38 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
// document.body's prototype will find the right function.
JSObject *global = ::JS_GetGlobalForObject(cx, proto);
nsGlobalWindow *win = FindUsableInnerWindow(XPConnect(), cx, global);
if (!win) {
// Only do this if the global object is a window.
// XXX Is there a better way to check this?
nsISupports *globalNative = XPConnect()->GetNativeOfWrapper(cx, global);
nsCOMPtr<nsPIDOMWindow> piwin = do_QueryInterface(globalNative);
if (!piwin) {
return NS_OK;
}
global = win->FastGetGlobalJSObject();
nsGlobalWindow *win = nsGlobalWindow::FromSupports(globalNative);
if (win->IsClosedOrClosing()) {
return NS_OK;
}
// If the window is in a different compartment than the global object, then
// it's likely that global is a sandbox object whose prototype is a window.
// Don't do anything in this case.
if (win->FastGetGlobalJSObject() &&
js::GetObjectCompartment(global) != js::GetObjectCompartment(win->FastGetGlobalJSObject())) {
return NS_OK;
}
if (win->IsOuterWindow()) {
// XXXjst: Do security checks here when we remove the security
// checks on the inner window.
win = win->GetCurrentInnerWindowInternal();
if (!win || !(global = win->GetGlobalJSObject()) ||
win->IsClosedOrClosing()) {
return NS_OK;
}
}
// Don't overwrite a property set by content.
JSBool found;
@ -4817,23 +4829,6 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
&unused);
}
NS_IMETHODIMP
nsDOMClassInfo::PreCreatePrototype(JSContext * cx, JSObject * global,
JSObject **protoProto)
{
*protoProto = nsnull;
nsGlobalWindow *win = FindUsableInnerWindow(XPConnect(), cx, global);
if (!win) {
return NS_OK;
}
JSObject *winObj = win->FastGetGlobalJSObject();
return LookupPrototypeProto(cx, winObj, mData, nsnull, protoProto);
}
// static
nsIClassInfo *
NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID)
@ -5186,7 +5181,7 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
// scope polluter (right before Object.prototype).
while ((proto = ::JS_GetPrototype(cx, o))) {
if (js::GetObjectClass(proto) == &js::ObjectClass) {
if (JS_GET_CLASS(cx, proto) == sObjectClass) {
// Set the global scope polluters prototype to Object.prototype
::JS_SplicePrototype(cx, gsp, proto);
@ -6008,105 +6003,6 @@ GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
return aXPConnect->HoldObject(cx, proto_obj, aProto);
}
static nsresult
LookupPrototypeProto(JSContext *cx, JSObject *winobj,
const nsDOMClassInfoData *ci_data,
const nsGlobalNameStruct *name_struct,
JSObject **aProtoProto)
{
NS_ASSERTION(ci_data ||
(name_struct &&
name_struct->mType == nsGlobalNameStruct::eTypeClassProto),
"Wrong type or missing ci_data!");
const nsIID *primary_iid = &NS_GET_IID(nsISupports);
if (!ci_data) {
primary_iid = &name_struct->mIID;
} else if (ci_data->mProtoChainInterface) {
primary_iid = ci_data->mProtoChainInterface;
}
if (primary_iid->Equals(NS_GET_IID(nsISupports))) {
*aProtoProto = nsnull;
return NS_OK;
}
nsCOMPtr<nsIInterfaceInfoManager>
iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
nsCOMPtr<nsIInterfaceInfo> if_info;
iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
NS_ENSURE_TRUE(if_info, NS_ERROR_UNEXPECTED);
const nsIID *iid = nsnull;
nsCOMPtr<nsIInterfaceInfo> parent;
if (ci_data && !ci_data->mHasClassInterface) {
if_info->GetIIDShared(&iid);
} else {
if_info->GetParent(getter_AddRefs(parent));
NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
parent->GetIIDShared(&iid);
}
if (!iid || iid->Equals(NS_GET_IID(nsISupports))) {
*aProtoProto = nsnull;
return NS_OK;
}
const char *class_parent_name = nsnull;
if (ci_data && !ci_data->mHasClassInterface) {
// If the class doesn't have a class interface the primary
// interface is the interface that should be
// constructor.prototype.__proto__.
if_info->GetNameShared(&class_parent_name);
} else {
// If the class does have a class interface (or there's no
// real class for this name) then the parent of the
// primary interface is what we want on
// constructor.prototype.__proto__.
NS_ASSERTION(parent, "Whoa, this is bad, null parent here!");
parent->GetNameShared(&class_parent_name);
}
JSObject *protoProto = nsnull;
// Get class_parent_name here
if (class_parent_name) {
jsval val;
JSAutoEnterCompartment ac;
if (!ac.enter(cx, winobj)) {
return NS_ERROR_UNEXPECTED;
}
if (!::JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), &val)) {
return NS_ERROR_UNEXPECTED;
}
JSObject *tmp = JSVAL_IS_OBJECT(val) ? JSVAL_TO_OBJECT(val) : nsnull;
if (tmp) {
if (!::JS_LookupProperty(cx, tmp, "prototype", &val)) {
return NS_ERROR_UNEXPECTED;
}
if (JSVAL_IS_OBJECT(val)) {
protoProto = JSVAL_TO_OBJECT(val);
}
}
}
*aProtoProto = protoProto;
return NS_OK;
}
// Either ci_data must be non-null or name_struct must be non-null and of type
// eTypeClassProto.
static nsresult
@ -6152,6 +6048,10 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
primary_iid = ci_data->mProtoChainInterface;
}
nsCOMPtr<nsIInterfaceInfo> if_info;
nsCOMPtr<nsIInterfaceInfo> parent;
const char *class_parent_name = nsnull;
if (!primary_iid->Equals(NS_GET_IID(nsISupports))) {
JSAutoEnterCompartment ac;
@ -6175,14 +6075,76 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
!indexedDB::IDBKeyRange::DefineConstructors(cx, class_obj)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIInterfaceInfoManager>
iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
NS_ENSURE_TRUE(if_info, NS_ERROR_UNEXPECTED);
const nsIID *iid = nsnull;
if (ci_data && !ci_data->mHasClassInterface) {
if_info->GetIIDShared(&iid);
} else {
if_info->GetParent(getter_AddRefs(parent));
NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
parent->GetIIDShared(&iid);
}
if (iid) {
if (!iid->Equals(NS_GET_IID(nsISupports))) {
if (ci_data && !ci_data->mHasClassInterface) {
// If the class doesn't have a class interface the primary
// interface is the interface that should be
// constructor.prototype.__proto__.
if_info->GetNameShared(&class_parent_name);
} else {
// If the class does have a class interface (or there's no
// real class for this name) then the parent of the
// primary interface is what we want on
// constructor.prototype.__proto__.
NS_ASSERTION(parent, "Whoa, this is bad, null parent here!");
parent->GetNameShared(&class_parent_name);
}
}
}
}
{
JSObject *winobj = aWin->FastGetGlobalJSObject();
JSObject *proto;
rv = LookupPrototypeProto(cx, winobj, ci_data, name_struct, &proto);
NS_ENSURE_SUCCESS(rv, rv);
JSObject *proto = nsnull;
if (class_parent_name) {
jsval val;
JSAutoEnterCompartment ac;
if (!ac.enter(cx, winobj)) {
return NS_ERROR_UNEXPECTED;
}
if (!::JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), &val)) {
return NS_ERROR_UNEXPECTED;
}
JSObject *tmp = JSVAL_IS_OBJECT(val) ? JSVAL_TO_OBJECT(val) : nsnull;
if (tmp) {
if (!::JS_LookupProperty(cx, tmp, "prototype", &val)) {
return NS_ERROR_UNEXPECTED;
}
if (JSVAL_IS_OBJECT(val)) {
proto = JSVAL_TO_OBJECT(val);
}
}
}
if (dot_prototype) {
JSAutoEnterCompartment ac;
@ -6194,7 +6156,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
if (proto &&
(!xpc_proto_proto ||
js::GetObjectClass(xpc_proto_proto) == &js::ObjectClass)) {
JS_GET_CLASS(cx, xpc_proto_proto) == sObjectClass)) {
if (!JS_WrapObject(cx, &proto) ||
!JS_SetPrototype(cx, dot_prototype, proto)) {
return NS_ERROR_UNEXPECTED;
@ -9581,7 +9543,7 @@ nsHTMLPluginObjElementSH::SetupProtoChain(nsIXPConnectWrappedNative *wrapper,
return NS_ERROR_UNEXPECTED;
}
if (pi_proto && js::GetObjectClass(pi_proto) != &js::ObjectClass) {
if (pi_proto && JS_GET_CLASS(cx, pi_proto) != sObjectClass) {
// The plugin wrapper has a proto that's not Object.prototype, set
// 'pi.__proto__.__proto__' to the original 'this.__proto__'
if (pi_proto != my_proto && !::JS_SetPrototype(cx, pi_proto, my_proto)) {

View File

@ -1988,7 +1988,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (aState) {
newInnerWindow = wsh->GetInnerWindow();
mInnerWindowHolder = wsh->GetInnerWindowHolder();
NS_ASSERTION(newInnerWindow, "Got a state without inner window");
} else if (thisChrome) {
newInnerWindow = new nsGlobalChromeWindow(this);
@ -2038,6 +2038,15 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
bool termFuncSet = false;
if (oldDoc == aDocument) {
// Move the navigator from the old inner window to the new one since
// this is a document.write. This is safe from a same-origin point of
// view because document.write can only be used by the same origin.
newInnerWindow->mNavigator = currentInner->mNavigator;
currentInner->mNavigator = nsnull;
if (newInnerWindow->mNavigator) {
newInnerWindow->mNavigator->SetWindow(newInnerWindow);
}
// Suspend the current context's request before Pop() resumes the old
// context's request.
JSAutoSuspendRequest asr(cx);

View File

@ -66,6 +66,7 @@ XPIDLSRCS = \
LOCAL_INCLUDES = \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/dom/telephony \
-I$(topsrcdir)/dom/wifi \
-I$(topsrcdir)/content/events/src \
$(NULL)

View File

@ -45,7 +45,11 @@
#include "nsIObserverService.h"
#include "mozilla/dom/workers/Workers.h"
#include "jstypedarray.h"
#include "nsTelephonyWorker.h"
#include "nsITelephone.h"
#include "nsWifiWorker.h"
#include "nsIWifi.h"
#include "nsThreadUtils.h"
@ -60,6 +64,7 @@ USING_WORKERS_NAMESPACE
using namespace mozilla::ipc;
static NS_DEFINE_CID(kTelephonyWorkerCID, NS_TELEPHONYWORKER_CID);
static NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID);
// Topic we listen to for shutdown.
#define PROFILE_BEFORE_CHANGE_TOPIC "profile-before-change"
@ -225,16 +230,6 @@ RadioManager::Init()
nsresult rv = obs->AddObserver(this, PROFILE_BEFORE_CHANGE_TOPIC, false);
NS_ENSURE_SUCCESS(rv, rv);
// The telephony worker component is a hack that gives us a global object for
// our own functions and makes creating the worker possible.
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
jsval workerval;
rv = worker->GetWorker(&workerval);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(workerval), "bad worker value");
JSContext *cx;
rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
NS_ENSURE_SUCCESS(rv, rv);
@ -243,30 +238,11 @@ RadioManager::Init()
return NS_ERROR_FAILURE;
}
JSObject *workerobj = JSVAL_TO_OBJECT(workerval);
rv = InitTelephone(cx);
NS_ENSURE_SUCCESS(rv, rv);
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, workerobj)) {
return NS_ERROR_OUT_OF_MEMORY;
}
WorkerCrossThreadDispatcher *wctd = GetWorkerCrossThreadDispatcher(cx, workerval);
if (!wctd) {
return NS_ERROR_FAILURE;
}
nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
if (!wctd->PostTask(connection)) {
return NS_ERROR_UNEXPECTED;
}
// Now that we're set up, connect ourselves to the RIL thread.
mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
StartRil(receiver);
mTelephone = do_QueryInterface(worker);
NS_ENSURE_TRUE(mTelephone, NS_ERROR_FAILURE);
rv = InitWifi(cx);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@ -278,6 +254,7 @@ RadioManager::Shutdown()
StopRil();
mTelephone = nsnull;
mWifi = nsnull;
mShutdown = true;
}
@ -316,6 +293,59 @@ RadioManager::GetTelephone()
return nsnull;
}
nsresult
RadioManager::InitTelephone(JSContext *cx)
{
// The telephony worker component is a hack that gives us a global object for
// our own functions and makes creating the worker possible.
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kTelephonyWorkerCID));
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
jsval workerval;
nsresult rv = worker->GetWorker(&workerval);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(!JSVAL_IS_PRIMITIVE(workerval), "bad worker value");
JSObject *workerobj = JSVAL_TO_OBJECT(workerval);
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, workerobj)) {
return NS_ERROR_OUT_OF_MEMORY;
}
WorkerCrossThreadDispatcher *wctd = GetWorkerCrossThreadDispatcher(cx, workerval);
if (!wctd) {
return NS_ERROR_FAILURE;
}
nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
if (!wctd->PostTask(connection)) {
return NS_ERROR_UNEXPECTED;
}
// Now that we're set up, connect ourselves to the RIL thread.
mozilla::RefPtr<RILReceiver> receiver = new RILReceiver(wctd);
StartRil(receiver);
mTelephone = do_QueryInterface(worker);
NS_ENSURE_TRUE(mTelephone, NS_ERROR_FAILURE);
return NS_OK;
}
nsresult
RadioManager::InitWifi(JSContext *cx)
{
nsCOMPtr<nsIRadioWorker> worker(do_CreateInstance(kWifiWorkerCID));
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
mWifi = do_QueryInterface(worker);
NS_ENSURE_TRUE(mWifi, NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMPL_ISUPPORTS1(RadioManager, nsIObserver)

View File

@ -48,7 +48,6 @@
#include "nsIObserver.h"
#include "mozilla/ipc/Ril.h"
#include "nsITelephone.h"
#define TELEPHONYRADIO_CONTRACTID "@mozilla.org/telephony/radio;1"
#define TELEPHONYRADIOINTERFACE_CONTRACTID "@mozilla.org/telephony/radio-interface;1"
@ -70,6 +69,8 @@
class nsIXPConnectJSObjectHolder;
class nsITelephone;
class nsIWifi;
BEGIN_TELEPHONY_NAMESPACE
@ -92,7 +93,11 @@ protected:
RadioManager();
~RadioManager();
nsresult InitTelephone(JSContext *cx);
nsresult InitWifi(JSContext *cx);
nsCOMPtr<nsITelephone> mTelephone;
nsCOMPtr<nsIWifi> mWifi;
bool mShutdown;
};

View File

@ -152,6 +152,7 @@ _TEST_FILES = \
devicemotion_outer.html \
devicemotion_inner.html \
test_bug698061.html \
test_bug707749.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=707749
-->
<head>
<title>Test for Bug 707749</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=707749 ">Mozilla Bug 707749 </a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 707749 **/
SimpleTest.waitForExplicitFinish();
function loaded() {
$('ifr').contentDocument.open();
$('ifr').contentDocument.close();
ok(true, "Don't throw an exception from contentDocument.open()");
SimpleTest.finish();
}
</script>
<iframe id="ifr" onload="loaded()" src="data:text/html,<script>navigator</script>"></iframe>
</pre>
</body>
</html>

View File

@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
bug507902-frame.html \
test_bug507902.html \
$(NULL)

View File

@ -0,0 +1,30 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Frame for watchPosition </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<script type="text/javascript">
var ok = window.parent.ok;
var SimpleTest = window.parent.SimpleTest;
function boom()
{
window.addEventListener("unload", function(){}, false);
window.addEventListener("devicemotion", function(){}, false);
location = "data:text/html,2";
ok(1, "leak will be at the end of mochitests. so pass.");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", function() { setTimeout(boom, 0); }, false);
</script>
</body>
</html>

View File

@ -4,15 +4,15 @@
https://bugzilla.mozilla.org/show_bug.cgi?id=507902
-->
<head>
<title>Test for watchPosition </title>
<title>Test for devicemotion</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=507902">Mozilla Bug 507902</a>
<p id="display"></p>
<div id="content" style="display: none">
<div id="content">
<iframe id="frame" src="bug507902-frame.html"></iframe>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
@ -29,8 +29,6 @@ function boom()
SimpleTest.waitForExplicitFinish();
window.addEventListener("load", function() { setTimeout(boom, 0); }, false);
</script>
</pre>
</body>

70
dom/wifi/Makefile.in Normal file
View File

@ -0,0 +1,70 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Telephony.
#
# The Initial Developer of the Original Code is
# The Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Turner <bent.mozilla@gmail.com> (Original Author)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = dom
LIBRARY_NAME = domwifi_s
XPIDL_MODULE = dom_wifi
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
include $(topsrcdir)/dom/dom-config.mk
XPIDLSRCS = \
nsIWifi.idl \
$(NULL)
EXTRA_COMPONENTS = \
nsWifiWorker.js \
nsWifiWorker.manifest \
$(NULL)
EXTRA_JS_MODULES = \
libcutils.js \
libhardware_legacy.js \
libnetutils.js \
network_worker.js \
$(NULL)
include $(topsrcdir)/config/rules.mk

13
dom/wifi/libcutils.js Normal file
View File

@ -0,0 +1,13 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
let libcutils = (function () {
let library = ctypes.open("/system/lib/libcutils.so");
return {
property_get: library.declare("property_get", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.char.ptr, ctypes.char.ptr),
property_set: library.declare("property_set", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.char.ptr)
};
})();

View File

@ -0,0 +1,36 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
let libhardware_legacy = (function () {
let library = ctypes.open("/system/lib/libhardware_legacy.so");
return {
// Load wifi driver, 0 on success, < 0 on failure.
load_driver: library.declare("wifi_load_driver", ctypes.default_abi, ctypes.int),
// Unload wifi driver, 0 on success, < 0 on failure.
unload_driver: library.declare("wifi_unload_driver", ctypes.default_abi, ctypes.int),
// Start supplicant, 0 on success, < 0 on failure.
start_supplicant: library.declare("wifi_start_supplicant", ctypes.default_abi, ctypes.int),
// Stop supplicant, 0 on success, < 0 on failure.
stop_supplicant: library.declare("wifi_stop_supplicant", ctypes.default_abi, ctypes.int),
// Open a connection to the supplicant, 0 on success, < 0 on failure.
connect_to_supplicant: library.declare("wifi_connect_to_supplicant", ctypes.default_abi, ctypes.int),
// Close connection to connection to the supplicant, 0 on success, < 0 on failure.
close_supplicant_connection: library.declare("wifi_close_supplicant_connection", ctypes.default_abi, ctypes.int),
// Block until a wifi event is returned, buf is the buffer, len is the max length of the buffer.
// Return value is number of bytes in buffer, or 0 if no event (no connection for instance), and < 0 on failure.
wait_for_event: library.declare("wifi_wait_for_event", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.size_t),
// Issue a command to the wifi driver. command is the command string, reply will hold the reply, reply_len contains
// the maximum reply length initially and is updated with the actual length. 0 is returned on success, < 0 on failure.
command: library.declare("wifi_command", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.char.ptr, ctypes.size_t.ptr),
};
})();

30
dom/wifi/libnetutils.js Normal file
View File

@ -0,0 +1,30 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
let libnetutils = (function () {
let library = ctypes.open("/system/lib/libnetutils.so");
return {
ifc_enable: library.declare("ifc_enable", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_disable: library.declare("ifc_disable", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_add_host_route: library.declare("ifc_add_host_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.int),
ifc_remove_host_routes: library.declare("ifc_remove_host_routes", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_set_default_route: library.declare("ifc_set_default_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.int),
ifc_get_default_route: library.declare("ifc_get_default_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_remove_default_route: library.declare("ifc_remove_default_route", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_reset_connections: library.declare("ifc_reset_connections", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
ifc_configure: library.declare("ifc_configure", ctypes.default_abi, ctypes.int, ctypes.char.ptr,
ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int),
dhcp_do_request: library.declare("dhcp_do_request", ctypes.default_abi, ctypes.int,
ctypes.char.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr,
ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr),
dhcp_stop: library.declare("dhcp_stop", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
dhcp_release_lease: library.declare("dhcp_release_lease", ctypes.default_abi, ctypes.int, ctypes.char.ptr),
dhcp_get_errmsg: library.declare("dhcp_get_errmsg", ctypes.default_abi, ctypes.char.ptr),
dhcp_do_request_renew: library.declare("dhcp_do_request_renew", ctypes.default_abi, ctypes.int,
ctypes.char.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr,
ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr, ctypes.int.ptr)
};
})();

View File

@ -0,0 +1,94 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
"use strict";
importScripts("libhardware_legacy.js", "libnetutils.js", "libcutils.js");
var cbuf = ctypes.char.array(4096)();
var hwaddr = ctypes.uint8_t.array(6)();
var len = ctypes.size_t();
var ints = ctypes.int.array(8)();
self.onmessage = function(e) {
var data = e.data;
var id = data.id;
var cmd = data.cmd;
switch (cmd) {
case "command":
len.value = 4096;
var ret = libhardware_legacy.command(data.request, cbuf, len.address());
dump("For command " + data.request + " ret is " + ret + "\n");
var reply = "";
if (!ret) {
var reply_len = len.value;
var str = cbuf.readString();
if (str[reply_len-1] == "\n")
--reply_len;
reply = str.substr(0, reply_len);
}
postMessage({ id: id, status: ret, reply: reply });
break;
case "wait_for_event":
var ret = libhardware_legacy.wait_for_event(cbuf, 4096);
var event = cbuf.readString().substr(0, ret.value);
postMessage({ id: id, event: event });
break;
case "ifc_enable":
case "ifc_disable":
case "ifc_remove_host_routes":
case "ifc_remove_default_route":
case "ifc_reset_connections":
case "dhcp_stop":
case "dhcp_release_lease":
var ret = libnetutils[cmd](data.ifname);
postMessage({ id: id, status: ret });
break;
case "ifc_get_default_route":
var route = libnetutils.ifc_get_default_route(data.ifname);
postMessage({ id: id, route: route });
break;
case "ifc_add_host_route":
case "ifc_set_default_route":
var ret = libnetutils[cmd](data.ifname, data.route);
postMessage({ id: id, status: ret });
break;
case "ifc_configure":
dump("WIFI: data: " + uneval(data) + "\n");
var ret = libnetutils.ifc_configure(data.ifname, data.ipaddr, data.mask, data.gateway, data.dns1, data.dns2);
postMessage({ id: id, status: ret });
break;
case "dhcp_get_errmsg":
var error = libnetutils.get_dhcp_get_errmsg();
postMessage({ id: id, error: error.readString() });
break;
case "dhcp_do_request":
case "dhcp_do_request_renew":
var ret = libnetutils[cmd](data.ifname,
ints.addressOfElement(0),
ints.addressOfElement(1),
ints.addressOfElement(2),
ints.addressOfElement(3),
ints.addressOfElement(4),
ints.addressOfElement(5),
ints.addressOfElement(6));
postMessage({ id: id, status: ret, ipaddr: ints[0], gateway: ints[1], mask: ints[2],
dns1: ints[3], dns2: ints[4], server: ints[5], lease: ints[6]});
break;
case "property_get":
var ret = libcutils.property_get(data.key, cbuf, data.defaultValue);
postMessage({ id: id, status: ret, value: cbuf.readString() });
break;
case "property_set":
var ret = libcutils.property_set(data.key, data.value);
postMessage({ id: id, status: ret });
break;
default:
var f = libhardware_legacy[cmd] || libnetutils[cmd];
var ret = f();
dump("WIFI: " + cmd + " returned: " + ret);
postMessage({ id: id, status: ret });
break;
}
}

42
dom/wifi/nsIWifi.idl Normal file
View File

@ -0,0 +1,42 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Telephony.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Philipp von Weitershausen <philipp@weitershausen.de>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
[scriptable, uuid(9DCE05BF-659C-4427-A050-0EAC3BB6C1C0)]
interface nsIWifi : nsISupports {
};

40
dom/wifi/nsWifiWorker.h Normal file
View File

@ -0,0 +1,40 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Telephony.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#define NS_WIFIWORKER_CID \
{ 0xA14E8977, 0xD259, 0x433A, \
{ 0xA8, 0x8D, 0x58, 0xDD, 0x44, 0x65, 0x7E, 0x5B } }

853
dom/wifi/nsWifiWorker.js Normal file
View File

@ -0,0 +1,853 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Telephony.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
* Blake Kaplan <mrbkap@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const DEBUG = true; // set to false to suppress debug messages
const WIFIWORKER_CONTRACTID = "@mozilla.org/wifi/worker;1";
const WIFIWORKER_CID = Components.ID("{a14e8977-d259-433a-a88d-58dd44657e5b}");
const WIFIWORKER_WORKER = "resource://gre/modules/network_worker.js";
var WifiManager = (function() {
var controlWorker = new ChromeWorker(WIFIWORKER_WORKER);
var eventWorker = new ChromeWorker(WIFIWORKER_WORKER);
// Callbacks to invoke when a reply arrives from the controlWorker.
var controlCallbacks = Object.create(null);
var idgen = 0;
function controlMessage(obj, callback) {
var id = idgen++;
obj.id = id;
if (callback)
controlCallbacks[id] = callback;
controlWorker.postMessage(obj);
}
function onerror(e) {
// It is very important to call preventDefault on the event here.
// If an exception is thrown on the worker, it bubbles out to the
// component that created it. If that component doesn't have an
// onerror handler, the worker will try to call the error reporter
// on the context it was created on. However, That doesn't work
// for component contexts and can result in crashes. This onerror
// handler has to make sure that it calls preventDefault on the
// incoming event.
e.preventDefault();
var worker = (this === controlWorker) ? "control" : "event";
debug("Got an error from the " + worker + " worker: " + e.filename +
":" + e.lineno + ": " + e.message + "\n");
}
controlWorker.onerror = onerror;
eventWorker.onerror = onerror;
controlWorker.onmessage = function(e) {
var data = e.data;
var id = data.id;
var callback = controlCallbacks[id];
if (callback) {
callback(data);
delete controlCallbacks[id];
}
};
// Polling the status worker
var recvErrors = 0;
eventWorker.onmessage = function(e) {
// process the event and tell the event worker to listen for more events
if (handleEvent(e.data.event))
waitForEvent();
};
function waitForEvent() {
eventWorker.postMessage({ cmd: "wait_for_event" });
}
// Commands to the control worker
function voidControlMessage(cmd, callback) {
controlMessage({ cmd: cmd }, function (data) {
callback(data.status);
});
}
function loadDriver(callback) {
voidControlMessage("load_driver", callback);
}
function unloadDriver(callback) {
voidControlMessage("unload_driver", callback);
}
function startSupplicant(callback) {
voidControlMessage("start_supplicant", callback);
}
function stopSupplicant(callback) {
voidControlMessage("stop_supplicant", callback);
}
function connectToSupplicant(callback) {
voidControlMessage("connect_to_supplicant", callback);
}
function closeSupplicantConnection(callback) {
voidControlMessage("close_supplicant_connection", callback);
}
function doCommand(request, callback) {
controlMessage({ cmd: "command", request: request }, callback);
}
function doIntCommand(request, callback) {
doCommand(request, function(data) {
callback(data.status ? -1 : (data.reply|0));
});
}
function doBooleanCommand(request, expected, callback) {
doCommand(request, function(data) {
callback(data.status ? false : (data.reply == expected));
});
}
function doStringCommand(request, callback) {
doCommand(request, function(data) {
callback(data.status ? null : data.reply);
});
}
function listNetworksCommand(callback) {
doStringCommand("LIST_NETWORKS", callback);
}
function addNetworkCommand(callback) {
doIntCommand("ADD_NETWORK", callback);
}
function setNetworkVariableCommand(netId, name, value, callback) {
doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value, "OK", callback);
}
function getNetworkVariableCommand(netId, name, callback) {
doStringCommand("GET_NETWORK " + netId + " " + name, callback);
}
function removeNetworkCommand(netId, callback) {
doBooleanCommand("REMOVE_NETWORK " + netId, callback);
}
function enableNetworkCommand(netId, disableOthers, callback) {
doBooleanCommand((disableOthers ? "SELECT_NETWORK " : "ENABLE_NETWORK ") + netId, "OK", callback);
}
function disableNetworkCommand(netId, callback) {
doBooleanCommand("DISABLE_NETWORK " + netId, "OK", callback);
}
function statusCommand(callback) {
doStringCommand("STATUS", callback);
}
function pingCommand(callback) {
doBooleanCommand("PING", "PONG", callback);
}
function scanResultsCommand(callback) {
doStringCommand("SCAN_RESULTS", callback);
}
function disconnectCommand(callback) {
doBooleanCommand("DISCONNECT", "OK", callback);
}
function reconnectCommand(callback) {
doBooleanCommand("RECONNECT", "OK", callback);
}
function reassociateCommand(callback) {
doBooleanCommand("REASSOCIATE", "OK", callback);
}
var scanModeActive = false;
function doSetScanModeCommand(setActive, callback) {
doBooleanCommand(setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE", "OK", callback);
}
function scanCommand(forceActive, callback) {
if (forceActive && !scanModeActive) {
doSetScanModeCommand(true, function(ok) {
ok && doBooleanCommand("SCAN", "OK", function(ok) {
ok && doSetScanModeCommand(false, callback);
});
});
return;
}
doBooleanCommand("SCAN", "OK", callback);
}
function setScanModeCommand(setActive, callback) {
sScanModeActive = setActive;
doSetScanModeCommand(setActive, callback);
}
function startDriverCommand(callback) {
doBooleanCommand("DRIVER START", "OK");
}
function stopDriverCommand(callback) {
doBooleanCommand("DRIVER STOP", "OK");
}
function startPacketFiltering(callback) {
doBooleanCommand("DRIVER RXFILTER-ADD 0", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-ADD 1", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-ADD 3", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-START", "OK", callback)
});
});
});
}
function stopPacketFiltering(callback) {
doBooleanCommand("DRIVER RXFILTER-STOP", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 3", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 1", "OK", function(ok) {
ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 0", "OK", callback)
});
});
});
}
function doGetRssiCommand(cmd, callback) {
doCommand(cmd, function(data) {
var rssi = -200;
if (!data.status) {
// If we are associating, the reply is "OK".
var reply = data.reply;
if (reply != "OK") {
// Format is: <SSID> rssi XX". SSID can contain spaces.
var offset = reply.lastIndexOf("rssi ");
if (offset != -1)
rssi = reply.substr(offset + 5) | 0;
}
}
callback(rssi);
});
}
function getRssiCommand(callback) {
doGetRssiCommand("DRIVER RSSI", callback);
}
function getRssiApproxCommand(callback) {
doGetRssiCommand("DRIVER RSSI-APPROX", callback);
}
function getLinkSpeedCommand(callback) {
doStringCommand("DRIVER LINKSPEED", function(reply) {
if (reply)
reply = reply.split()[1] | 0; // Format: LinkSpeed XX
callback(reply);
});
}
function getMacAddressCommand(callback) {
doStringCommand("DRIVER MACADDR", function(reply) {
if (reply)
reply = reply.split(" ")[2]; // Format: Macaddr = XX.XX.XX.XX.XX.XX
callback(reply);
});
}
function setPowerModeCommand(mode, callback) {
doBooleanCommand("DRIVER POWERMODE " + mode, "OK", callback);
}
function getPowerModeCommand(callback) {
doStringCommand("DRIVER GETPOWER", function(reply) {
if (reply)
reply = (reply.split()[2]|0); // Format: powermode = XX
callback(reply);
});
}
function setNumAllowedChannelsCommand(numChannels, callback) {
doBooleanCommand("DRIVER SCAN-CHANNELS " + numChannels, "OK", callback);
}
function getNumAllowedChannelsCommand(callback) {
doStringCommand("DRIVER SCAN-CHANNELS", function(reply) {
if (reply)
reply = (reply.split()[2]|0); // Format: Scan-Channels = X
callback(reply);
});
}
function setBluetoothCoexistenceModeCommand(mode, callback) {
doBooleanCommand("DRIVER BTCOEXMODE " + mode, "OK", callback);
}
function setBluetoothCoexistenceScanModeCommand(mode, callback) {
doBooleanCommand("DRIVER BTCOEXSCAN-" + (mode ? "START" : "STOP"), "OK", callback);
}
function saveConfigCommand(callback) {
// Make sure we never write out a value for AP_SCAN other than 1
doBooleanCommand("AP_SCAN 1", "OK", function(ok) {
doBooleanCommand("SAVE_CONFIG", "OK", callback);
});
}
function reloadConfigCommand(callback) {
doBooleanCommand("RECONFIGURE", "OK", callback);
}
function setScanResultHandlingCommand(mode, callback) {
doBooleanCommand("AP_SCAN " + mode, "OK", callback);
}
function addToBlacklistCommand(bssid, callback) {
doBooleanCommand("BLACKLIST " + bssid, "OK", callback);
}
function clearBlacklistCommand(callback) {
doBooleanCommand("BLACKLIST clear", "OK", callback);
}
function setSuspendOptimizationsCommand(enabled, callback) {
doBooleanCommand("DRIVER SETSUSPENDOPT " + (enabled ? 0 : 1), "OK", callback);
}
function getProperty(key, defaultValue, callback) {
controlMessage({ cmd: "property_get", key: key, defaultValue: defaultValue }, function(data) {
callback(data.status < 0 ? null : data.value);
});
}
function setProperty(key, value, callback) {
controlMessage({ cmd: "property_set", key: key, value: value }, function(data) {
callback(!data.status);
});
}
function enableInterface(ifname, callback) {
controlMessage({ cmd: "ifc_enable", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function disableInterface(ifname, callback) {
controlMessage({ cmd: "ifc_disable", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function addHostRoute(ifname, route, callback) {
controlMessage({ cmd: "ifc_add_host_route", ifname: ifname, route: route }, function(data) {
callback(!data.status);
});
}
function removeHostRoutes(ifname, callback) {
controlMessage({ cmd: "ifc_remove_host_routes", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function setDefaultRoute(ifname, route, callback) {
controlMessage({ cmd: "ifc_set_default_route", ifname: ifname, route: route }, function(data) {
callback(!data.status);
});
}
function getDefaultRoute(ifname, callback) {
controlMessage({ cmd: "ifc_get_default_route", ifname: ifname }, function(data) {
callback(!data.route);
});
}
function removeDefaultRoute(ifname, callback) {
controlMessage({ cmd: "ifc_remove_default_route", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function resetConnections(ifname, callback) {
controlMessage({ cmd: "ifc_reset_connections", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function runDhcp(ifname, callback) {
controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
callback(data.status ? null : data);
});
}
function stopDhcp(ifname, callback) {
controlMessage({ cmd: "dhcp_stop", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function releaseDhcpLease(ifname, callback) {
controlMessage({ cmd: "dhcp_release_lease", ifname: ifname }, function(data) {
callback(!data.status);
});
}
function getDhcpError(callback) {
controlMessage({ cmd: "dhcp_get_errmsg" }, function(data) {
callback(data.error);
});
}
function configureInterface(ifname, ipaddr, mask, gateway, dns1, dns2, callback) {
controlMessage({ cmd: "ifc_configure", ifname: ifname,
ipaddr: ipaddr, mask: mask, gateway: gateway,
dns1: dns1, dns2: dns2}, function(data) {
callback(!data.status);
});
}
function runDhcpRenew(ifname, callback) {
controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
callback(data.status ? null : data);
});
}
var manager = {};
function notify(eventName, eventObject) {
var handler = manager["on" + eventName];
if (handler) {
if (!eventObject)
eventObject = ({});
handler.call(eventObject);
}
}
// try to connect to the supplicant
var connectTries = 0;
var retryTimer = null;
function connectCallback(ok) {
if (ok === 0) {
// tell the event worker to start waiting for events
retryTimer = null;
waitForEvent();
notify("supplicantconnection");
return;
}
if (connectTries++ < 3) {
// try again in 5 seconds
if (!retryTimer)
retryTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
retryTimer.initWithCallback(function(timer) {
connectToSupplicant(connectCallback);
}, 5000, Ci.nsITimer.TYPE_ONE_SHOT);
return;
}
retryTimer = null;
notify("supplicantlost");
}
manager.start = function() {
connectToSupplicant(connectCallback);
}
var supplicantStatesMap = ["DISCONNECTED", "INACTIVE", "SCANNING", "ASSOCIATING",
"FOUR_WAY_HANDSHAKE", "GROUP_HANDSHAKE", "COMPLETED",
"DORMANT", "UNINITIALIZED"];
var driverEventMap = { STOPPED: "driverstopped", STARTED: "driverstarted", HANGED: "driverhung" };
// handle events sent to us by the event worker
function handleEvent(event) {
debug("Event coming in: " + event);
if (event.indexOf("CTRL-EVENT-") !== 0) {
debug("Got weird event, possibly not doing anything.");
if (event.indexOf("WPA:") == 0 &&
event.indexOf("pre-shared key may be incorrect") != -1) {
notify("passwordmaybeincorrect");
}
return true;
}
var eventData = event.substr(0, event.indexOf(" ") + 1);
if (eventData.indexOf("CTRL-EVENT-STATE-CHANGE") === 0) {
// Parse the event data
var fields = {};
var tokens = eventData.split(" ");
for (var n = 0; n < tokens.length; ++n) {
var kv = tokens[n].split("=");
if (kv.length === 2)
fields[kv[0]] = kv[1];
}
if (!("state" in fields))
return true;
fields.state = supplicantStatesMap[fields.state];
notify("statechange", fields);
return true;
}
if (eventData.indexOf("CTRL-EVENT-DRIVER-STATE") === 0) {
var handlerName = driverEventMap[eventData];
if (handlerName)
notify(handlerName);
return true;
}
if (eventData.indexOf("CTRL-EVENT-TERMINATING") === 0) {
// If the monitor socket is closed, we have already stopped the
// supplicant and we can stop waiting for more events and
// simply exit here (we don't have to notify).
if (eventData.indexOf("connection closed") !== -1)
return false;
// As long we haven't seen too many recv errors yet, we
// will keep going for a bit longer
if (eventData.indexOf("recv error") !== -1 && ++recvErrors < 10)
return true;
notify("supplicantlost");
return false;
}
if (eventData.indexOf("CTRL-EVENT-DISCONNECTED") === 0) {
notify("statechange", { state: "DISCONNECTED" });
return true;
}
if (eventData.indexOf("CTRL-EVENT-CONNECTED") === 0) {
// Format: CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]
var bssid = eventData.split(" ")[4];
var id = eventData.substr(eventData.indexOf("id=")).split(" ")[0];
notify("statechange", { state: "CONNECTED", BSSID: bssid, id: id });
return true;
}
if (eventData.indexOf("CTRL-EVENT-SCAN-RESULTS") === 0) {
debug("Notifying of scn results available");
notify("scanresultsavailable");
return true;
}
// unknown event
return true;
}
// Initial state
var airplaneMode = false;
// Public interface of the wifi service
manager.setWifiEnabled = function(enable, callback) {
var targetState = enable ? "ENABLED" : "DISABLED";
if (enable == targetState)
return true;
if (enable && airplaneMode)
return false;
if (enable) {
loadDriver(function (ok) {
(ok === 0) ? startSupplicant(callback) : callback(-1);
});
} else {
stopSupplicant(function (ok) {
(ok === 0) ? unloadDriver(callback) : callback(-1);
});
}
}
manager.disconnect = disconnectCommand;
manager.reconnect = reconnectCommand;
manager.reassociate = reassociateCommand;
var networkConfigurationFields = ["ssid", "bssid", "psk", "wep_key0", "wep_key1", "wep_key2", "wep_key3",
"wep_tx_keyidx", "priority", "key_mgmt", "scan_ssid"];
manager.getNetworkConfiguration = function(config, callback) {
var netId = config.netId;
var done = 0;
for (var n = 0; n < networkConfigurationFields; ++n) {
var fieldName = networkConfigurationFields[n];
getNetworkVariableCommand(netId, fieldName, function(value) {
config[fieldName] = value;
if (++done == networkConfigurationFields.length)
callback(config);
});
}
}
manager.setNetworkConfiguration = function(config, callback) {
var netId = config.netId;
var done = 0;
var errors = 0;
for (var n = 0; n < networkConfigurationFields.length; ++n) {
var fieldName = networkConfigurationFields[n];
if (!(fieldName in config)) {
++done;
} else {
setNetworkVariableCommand(netId, fieldName, config[fieldName], function(ok) {
if (!ok)
++errors;
if (++done == networkConfigurationFields.length)
callback(errors == 0);
});
}
}
// If config didn't contain any of the fields we want, don't lose the error callback
if (done == networkConfigurationFields.length)
callback(false);
}
manager.getConfiguredNetworks = function(callback) {
listNetworksCommand(function (reply) {
var networks = {};
var done = 0;
var errors = 0;
var lines = reply.split("\n");
for (var n = 1; n < lines.length; ++n) {
var result = lines[n].split("\t");
var netId = result[0];
var config = networks[netId] = { netId: netId };
switch (result[3]) {
case "[CURRENT]":
config.status = "CURRENT";
break;
case "[DISABLED]":
config.status = "DISABLED";
break;
default:
config.status = "ENABLED";
break;
}
manager.getNetworkConfiguration(config, function (ok) {
if (!ok)
++errors;
if (++done == lines.length - 1) {
if (errors) {
// If an error occured, delete the new netId
removeNetworkCommand(netId, function() {
callback(null);
});
} else {
callback(networks);
}
}
});
}
});
}
manager.addNetwork = function(config, callback) {
addNetworkCommand(function (netId) {
config.netId = netId;
manager.setNetworkConfiguration(config, callback);
});
}
manager.updateNetwork = function(config, callback) {
manager.setNetworkConfiguration(config, callback);
}
manager.removeNetwork = function(netId, callback) {
removeNetworkCommand(netId, callback);
}
function ipToString(n) {
return String((n & (0xff << 24)) >> 24) + "." +
((n & (0xff << 16)) >> 16) + "." +
((n & (0xff << 8)) >> 8) + "." +
((n & (0xff << 0)) >> 0);
}
manager.enableNetwork = function(netId, disableOthers, callback) {
getProperty("wifi.interface", "tiwlan0", function (ifname) {
if (!ifname) {
callback(false);
return;
}
enableInterface(ifname, function (ok) {
if (!ok) {
callback(false);
return;
}
enableNetworkCommand(netId, disableOthers, function (ok) {
if (!ok) {
disableInterface(ifname, function () {
callback(false);
});
return;
}
runDhcp(ifname, function (data) {
debug("After running dhcp, got data: " + uneval(data));
if (!data) {
disableInterface(ifname, function() {
callback(false);
});
return;
}
setProperty("net.dns1", ipToString(data.dns1), function(ok) {
if (!ok) {
callback(false);
return;
}
getProperty("net.dnschange", "0", function(value) {
if (value === null) {
callback(false);
return;
}
setProperty("net.dnschange", String(Number(value) + 1), function(ok) {
callback(ok);
});
});
});
});
});
});
});
}
manager.disableNetwork = function(netId, callback) {
disableNetworkCommand(netId, callback);
}
manager.getMacAddress = getMacAddressCommand;
manager.getScanResults = scanResultsCommand;
return manager;
})();
function nsWifiWorker() {
WifiManager.onsupplicantconnection = function() {
debug("Connected to supplicant");
WifiManager.getMacAddress(function (mac) {
debug("Got mac: " + mac);
});
}
WifiManager.onsupplicantlost = function() {
debug("Couldn't connect to supplicant");
}
var networks = Object.create(null);
WifiManager.onscanresultsavailable = function() {
debug("Scan results are available! Asking for them.");
if (networks["Mozilla Guest"])
return;
WifiManager.getScanResults(function(r) {
let lines = r.split("\n");
// NB: Skip the header line.
let added = !("Mozilla Guest" in networks);
for (let i = 1; i < lines.length; ++i) {
// bssid / frequency / signal level / flags / ssid
var match = /([\S]+)\s+([\S]+)\s+([\S]+)\s+(\[[\S]+\])?\s+(.*)/.exec(lines[i])
if (match)
networks[match[5]] = match[1];
else
debug("Match didn't find anything for: " + lines[i]);
}
if (("Mozilla Guest" in networks) && added) {
debug("Mozilla Guest exists in networks, trying to connect!");
var config = Object.create(null);
config["ssid"] = '"Mozilla Guest"';
//config["bssid"] = '"' + networks["Mozilla Guest"] + '"';
config["key_mgmt"] = "NONE";
config["scan_ssid"] = 1;
WifiManager.addNetwork(config, function (ok) {
if (ok) {
WifiManager.enableNetwork(config.netId, false, function (ok) {
if (ok)
debug("Enabled the network!");
else
debug("Failed to enable the network :(");
});
} else {
debug("Failed to add the network :(");
}
});
}
});
}
WifiManager.setWifiEnabled(true, function (ok) {
if (ok === 0)
WifiManager.start();
else
debug("Couldn't start Wifi");
});
debug("Wifi starting");
}
nsWifiWorker.prototype = {
classID: WIFIWORKER_CID,
classInfo: XPCOMUtils.generateCI({classID: WIFIWORKER_CID,
contractID: WIFIWORKER_CONTRACTID,
classDescription: "WifiWorker",
interfaces: [Ci.nsIRadioWorker,
Ci.nsIWifi]}),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioWorker,
Ci.nsIWifi]),
setWifiEnabled: function(enable) {
WifiManager.setWifiEnabled(enable, function (ok) {
debug(ok);
});
},
// This is a bit ugly, but works. In particular, this depends on the fact
// that RadioManager never actually tries to get the worker from us.
get worker() { throw "Not implemented"; },
shutdown: function() {
this.setWifiEnabled(false);
}
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([nsWifiWorker]);
let debug;
if (DEBUG) {
debug = function (s) {
dump("-*- nsWifiWorker component: " + s + "\n");
};
} else {
debug = function (s) {};
}

View File

@ -0,0 +1 @@
component {a14e8977-d259-433a-a88d-58dd44657e5b} nsWifiWorker.js

View File

@ -167,7 +167,7 @@ NS_IMETHODIMP mozPersonalDictionary::Load()
// This is not threadsafe, and only safe if the consumer does not
// modify the list.
static PLDHashOperator
AddHostToStringArray(nsUniCharEntry *aEntry, void *aArg)
AddHostToStringArray(nsUnicharPtrHashKey *aEntry, void *aArg)
{
static_cast<nsTArray<nsString>*>(aArg)->AppendElement(nsDependentString(aEntry->GetKey()));
return PL_DHASH_NEXT;

View File

@ -48,6 +48,7 @@
#include "nsTHashtable.h"
#include "nsCRT.h"
#include "nsCycleCollectionParticipant.h"
#include "nsHashKeys.h"
#define MOZ_PERSONALDICTIONARY_CONTRACTID "@mozilla.org/spellchecker/personaldictionary;1"
#define MOZ_PERSONALDICTIONARY_CID \
@ -55,39 +56,7 @@
0X7EF52EAF, 0XB7E1, 0X462B, \
{ 0X87, 0XE2, 0X5D, 0X1D, 0XBA, 0XCA, 0X90, 0X48 } }
class nsUniCharEntry : public PLDHashEntryHdr
{
public:
// Hash methods
typedef const PRUnichar* KeyType;
typedef const PRUnichar* KeyTypePointer;
nsUniCharEntry(const PRUnichar* aKey) : mKey(nsCRT::strdup(aKey)) {}
nsUniCharEntry(const nsUniCharEntry& toCopy)
{
NS_NOTREACHED("ALLOW_MEMMOVE is set, so copy ctor shouldn't be called");
}
~nsUniCharEntry()
{
if (mKey)
nsCRT::free(mKey);
}
KeyType GetKey() const { return mKey; }
bool KeyEquals(KeyTypePointer aKey) const { return !nsCRT::strcmp(mKey, aKey); }
static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) { return nsCRT::HashCode(aKey); }
enum { ALLOW_MEMMOVE = true };
private:
PRUnichar *mKey;
};
class mozPersonalDictionary : public mozIPersonalDictionary,
class mozPersonalDictionary : public mozIPersonalDictionary,
public nsIObserver,
public nsSupportsWeakReference
{
@ -104,8 +73,8 @@ public:
protected:
bool mDirty; /* has the dictionary been modified */
nsTHashtable<nsUniCharEntry> mDictionaryTable;
nsTHashtable<nsUniCharEntry> mIgnoreTable;
nsTHashtable<nsUnicharPtrHashKey> mDictionaryTable;
nsTHashtable<nsUnicharPtrHashKey> mIgnoreTable;
nsCOMPtr<nsIUnicodeEncoder> mEncoder; /*Encoder to use to compare with spellchecker word */
};

View File

@ -0,0 +1,40 @@
diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
--- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp
@@ -337,16 +337,17 @@ NS_GFX_(void) ScaleYCbCrToRGB32(const ui
source_dx_uv >> kFractionBits);
}
}
else {
ScaleYUVToRGB32Row_C(y_ptr, u_ptr, v_ptr,
dest_pixel, width, source_dx);
}
#else
+ (void)source_dx_uv;
ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
dest_pixel, width, source_dx);
#endif
}
}
// MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
if (has_mmx)
EMMS();
diff --git a/gfx/ycbcr/yuv_row.h b/gfx/ycbcr/yuv_row.h
--- a/gfx/ycbcr/yuv_row.h
+++ b/gfx/ycbcr/yuv_row.h
@@ -129,14 +129,14 @@ extern SIMD_ALIGNED(int16 kCoefficientsR
#if defined(ARCH_CPU_X86) && !defined(ARCH_CPU_X86_64)
#if defined(_MSC_VER)
#define EMMS() __asm emms
#pragma warning(disable: 4799)
#else
#define EMMS() asm("emms")
#endif
#else
-#define EMMS()
+#define EMMS() ((void)0)
#endif
} // extern "C"
#endif // MEDIA_BASE_YUV_ROW_H_

View File

@ -25,3 +25,5 @@ convert.patch contains the following changes:
win64.patch: SSE2 optimization for Microsoft Visual C++ x64 version
TypeFromSize.patch: Bug 656185 - Add a method to detect YUVType from plane sizes.
QuellGccWarnings.patch: Bug 711895 - Avoid some GCC compilation warnings.

View File

@ -9,3 +9,4 @@ cp $1/media/base/yuv_row_posix.cc yuv_row_c.cpp
patch -p3 <convert.patch
patch -p3 <win64.patch
patch -p3 <TypeFromSize.patch
patch -p3 <QuellGccWarnings.patch

View File

@ -342,6 +342,7 @@ NS_GFX_(void) ScaleYCbCrToRGB32(const uint8* y_buf,
dest_pixel, width, source_dx);
}
#else
(void)source_dx_uv;
ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
dest_pixel, width, source_dx);
#endif

View File

@ -134,7 +134,7 @@ extern SIMD_ALIGNED(int16 kCoefficientsRgbY[768][4]);
#define EMMS() asm("emms")
#endif
#else
#define EMMS()
#define EMMS() ((void)0)
#endif
} // extern "C"

View File

@ -1806,14 +1806,20 @@ if test "$GNU_CC"; then
_MOZ_RTTI_FLAGS_ON=-frtti
_MOZ_RTTI_FLAGS_OFF=-fno-rtti
# Turn on GNU specific features
# -Wall - turn on all warnings
# -pedantic - make compiler warn about non-ANSI stuff, and
# be a little bit stricter
# Warnings slamm took out for now (these were giving more noise than help):
# -Wbad-function-cast - warns when casting a function to a new return type
# -Wshadow - removed because it generates more noise than help --pete
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -W -Wno-unused -Wpointer-arith"
# Turn on GNU-specific warnings:
# -Wall - turn on a lot of warnings
# -pedantic - this is turned on below
# -Wpointer-arith - enabled with -pedantic, but good to have even if not
# -Wdeclaration-after-statement - MSVC doesn't like these
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
#
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement -Wempty-body"
# Turn off the following warnings that -Wall/-pedantic turn on:
# -Woverlength-strings - we exceed the minimum maximum length all the time
#
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wno-overlength-strings"
if test -z "$INTEL_CC" -a -z "$CLANG_CC"; then
# Don't use -Wcast-align with ICC or clang
case "$CPU_ARCH" in
@ -1829,12 +1835,26 @@ if test "$GNU_CC"; then
dnl Turn pedantic on but disable the warnings for long long
_PEDANTIC=1
if test -z "$INTEL_CC"; then
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -W"
fi
_DEFINES_CFLAGS='-include $(DEPTH)/js-confdefs.h -DMOZILLA_CLIENT'
_USE_CPP_INCLUDE_FLAG=1
AC_CACHE_CHECK(whether the compiler supports -Wtype-limits,
ac_cc_has_wtype_limits,
[
AC_LANG_SAVE
AC_LANG_C
_SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wtype-limits"
AC_TRY_COMPILE([],
[return(0);],
ac_cc_has_wtype_limits="yes",
ac_cc_has_wtype_limits="no")
CFLAGS="$_SAVE_CFLAGS"
AC_LANG_RESTORE
])
if test "$ac_cc_has_wtype_limits" = "yes"; then
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wtype-limits"
fi
elif test "$SOLARIS_SUNPRO_CC"; then
DSO_CFLAGS=''
if test "$CPU_ARCH" = "sparc"; then
@ -1860,8 +1880,21 @@ else
fi
if test "$GNU_CXX"; then
# Turn on GNU specific features
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor"
# Turn on GNU-specific warnings:
# -Wall - turn on a lot of warnings
# -pedantic - this is turned on below
# -Wpointer-arith - enabled with -pedantic, but good to have even if not
# -Woverloaded-virtual - ???
# -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
#
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual -Wempty-body"
# Turn off the following warnings that -Wall/-pedantic turn on:
# -Woverlength-strings - we exceed the minimum maximum length all the time
# -Wctor-dtor-privacy - ???
#
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-overlength-strings -Wno-ctor-dtor-privacy"
if test -z "$INTEL_CXX" -a -z "$CLANG_CXX"; then
# Don't use -Wcast-align with ICC or clang
case "$CPU_ARCH" in
@ -1962,6 +1995,24 @@ if test "$GNU_CXX"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=return-type"
fi
AC_CACHE_CHECK(whether the compiler supports -Wtype-limits,
ac_has_wtype_limits,
[
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
_SAVE_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -Wtype-limits"
AC_TRY_COMPILE([],
[return(0);],
ac_has_wtype_limits="yes",
ac_has_wtype_limits="no")
CXXFLAGS="$_SAVE_CXXFLAGS"
AC_LANG_RESTORE
])
if test "$ac_has_wtype_limits" = "yes"; then
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wtype-limits"
fi
else
_DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_JS_CONFDEFS_H_ $(ACDEFINES)'
fi

View File

@ -7334,8 +7334,10 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
ok = EmitUnary(cx, bce, pn);
break;
case PNK_INC:
case PNK_DEC:
case PNK_PREINCREMENT:
case PNK_PREDECREMENT:
case PNK_POSTINCREMENT:
case PNK_POSTDECREMENT:
ok = EmitIncOrDec(cx, bce, pn);
break;

View File

@ -41,6 +41,8 @@
#ifndef ParseMaps_h__
#define ParseMaps_h__
#include "mozilla/Attributes.h"
#include "ds/InlineMap.h"
#include "js/HashTable.h"
#include "js/Vector.h"
@ -267,8 +269,8 @@ class AtomDecls
JSContext *cx;
AtomDOHMap *map;
AtomDecls(const AtomDecls &other);
void operator=(const AtomDecls &other);
AtomDecls(const AtomDecls &other) MOZ_DELETE;
void operator=(const AtomDecls &other) MOZ_DELETE;
AtomDeclNode *allocNode(Definition *defn);

View File

@ -75,8 +75,10 @@ enum ParseNodeKind {
PNK_STAR,
PNK_DIV,
PNK_MOD,
PNK_INC,
PNK_DEC,
PNK_PREINCREMENT,
PNK_POSTINCREMENT,
PNK_PREDECREMENT,
PNK_POSTDECREMENT,
PNK_DOT,
PNK_LB,
PNK_RB,
@ -347,8 +349,10 @@ enum ParseNodeKind {
* PNK_VOID,
* PNK_NOT,
* PNK_BITNOT
* PNK_INC, unary pn_kid: MEMBER expr
* PNK_DEC
* PNK_PREINCREMENT, unary pn_kid: MEMBER expr
* PNK_POSTINCREMENT,
* PNK_PREDECREMENT,
* PNK_POSTDECREMENT
* PNK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
* pn_count: 1 + N (where N is number of args)
* ctor is a MEMBER expr

View File

@ -4780,7 +4780,7 @@ Parser::assignExpr()
return ParseNode::newBinaryOrAppend(kind, op, lhs, rhs, tc);
}
static ParseNode *
static bool
SetLvalKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, ParseNode *kid,
const char *name)
{
@ -4795,25 +4795,24 @@ SetLvalKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, Parse
!kid->isKind(PNK_LB))
{
ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_BAD_OPERAND, name);
return NULL;
return false;
}
if (!CheckStrictAssignment(cx, tc, kid))
return NULL;
return false;
pn->pn_kid = kid;
return kid;
return true;
}
static const char incop_name_str[][10] = {"increment", "decrement"};
static JSBool
SetIncOpKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, ParseNode *kid,
TokenKind tt, JSBool preorder)
TokenKind tt, bool preorder)
{
JSOp op;
kid = SetLvalKid(cx, ts, tc, pn, kid, incop_name_str[tt == TOK_DEC]);
if (!kid)
return JS_FALSE;
if (!SetLvalKid(cx, ts, tc, pn, kid, incop_name_str[tt == TOK_DEC]))
return false;
switch (kid->getKind()) {
case PNK_NAME:
op = (tt == TOK_INC)
@ -4885,13 +4884,13 @@ Parser::unaryExpr()
case TOK_INC:
case TOK_DEC:
pn = UnaryNode::create((tt == TOK_INC) ? PNK_INC : PNK_DEC, tc);
pn = UnaryNode::create((tt == TOK_INC) ? PNK_PREINCREMENT : PNK_PREDECREMENT, tc);
if (!pn)
return NULL;
pn2 = memberExpr(JS_TRUE);
if (!pn2)
return NULL;
if (!SetIncOpKid(context, &tokenStream, tc, pn, pn2, tt, JS_TRUE))
if (!SetIncOpKid(context, &tokenStream, tc, pn, pn2, tt, true))
return NULL;
pn->pn_pos.end = pn2->pn_pos.end;
break;
@ -4954,11 +4953,11 @@ Parser::unaryExpr()
if (tokenStream.onCurrentLine(pn->pn_pos)) {
tt = tokenStream.peekTokenSameLine(TSF_OPERAND);
if (tt == TOK_INC || tt == TOK_DEC) {
(void) tokenStream.getToken();
pn2 = UnaryNode::create((tt == TOK_INC) ? PNK_INC : PNK_DEC, tc);
tokenStream.consumeKnownToken(tt);
pn2 = UnaryNode::create((tt == TOK_INC) ? PNK_POSTINCREMENT : PNK_POSTDECREMENT, tc);
if (!pn2)
return NULL;
if (!SetIncOpKid(context, &tokenStream, tc, pn2, pn, tt, JS_FALSE))
if (!SetIncOpKid(context, &tokenStream, tc, pn2, pn, tt, false))
return NULL;
pn2->pn_pos.begin = pn->pn_pos.begin;
pn = pn2;
@ -6821,13 +6820,22 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
pn2 = ParseNode::newBinaryOrAppend(PNK_COLON, op, pn3, pn2, tc);
goto skip;
}
case TOK_STRING:
case TOK_STRING: {
atom = tokenStream.currentToken().atom();
pn3 = NullaryNode::create(PNK_STRING, tc);
if (!pn3)
return NULL;
pn3->pn_atom = atom;
uint32_t index;
if (atom->isIndex(&index)) {
pn3 = NullaryNode::create(PNK_NUMBER, tc);
if (!pn3)
return NULL;
pn3->pn_dval = index;
} else {
pn3 = NullaryNode::create(PNK_STRING, tc);
if (!pn3)
return NULL;
pn3->pn_atom = atom;
}
break;
}
case TOK_RC:
goto end_obj_init;
default:

View File

@ -104,6 +104,13 @@ HeapValue::init(const Value &v)
post();
}
inline void
HeapValue::init(JSCompartment *comp, const Value &v)
{
value = v;
post(comp);
}
inline void
HeapValue::writeBarrierPre(const Value &value)
{

View File

@ -302,6 +302,7 @@ class HeapValue
inline ~HeapValue();
inline void init(const Value &v);
inline void init(JSCompartment *comp, const Value &v);
inline HeapValue &operator=(const Value &v);
inline HeapValue &operator=(const HeapValue &v);

View File

@ -404,11 +404,24 @@ DoGetElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *hole, Value *
return true;
}
template<typename IndexType>
static void
AssertGreaterThanZero(IndexType index)
{
JS_ASSERT(index >= 0);
}
template<>
void
AssertGreaterThanZero(jsuint index)
{
}
template<typename IndexType>
static JSBool
GetElement(JSContext *cx, JSObject *obj, IndexType index, JSBool *hole, Value *vp)
{
JS_ASSERT(index >= 0);
AssertGreaterThanZero(index);
if (obj->isDenseArray() && index < obj->getDenseArrayInitializedLength() &&
!(*vp = obj->getDenseArrayElement(uint32_t(index))).isMagic(JS_ARRAY_HOLE)) {
*hole = JS_FALSE;

View File

@ -38,11 +38,13 @@
*
* ***** END LICENSE BLOCK ***** */
/* JS execution context. */
#ifndef jscntxt_h___
#define jscntxt_h___
/*
* JS execution context.
*/
#include "mozilla/Attributes.h"
#include <string.h>
#include "jsfriendapi.h"
@ -1406,10 +1408,9 @@ class AutoGCRooter {
OBJVECTOR = -16 /* js::AutoObjectVector */
};
private:
/* No copy or assignment semantics. */
AutoGCRooter(AutoGCRooter &ida);
void operator=(AutoGCRooter &ida);
private:
AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
void operator=(AutoGCRooter &ida) MOZ_DELETE;
};
/* FIXME(bug 332648): Move this into a public header. */
@ -1618,9 +1619,8 @@ class AutoIdArray : private AutoGCRooter {
JSIdArray * idArray;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
/* No copy or assignment semantics. */
AutoIdArray(AutoIdArray &ida);
void operator=(AutoIdArray &ida);
AutoIdArray(AutoIdArray &ida) MOZ_DELETE;
void operator=(AutoIdArray &ida) MOZ_DELETE;
};
/* The auto-root for enumeration object and its state. */
@ -1797,7 +1797,8 @@ class AutoReleasePtr {
void *ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
AutoReleasePtr operator=(const AutoReleasePtr &other);
AutoReleasePtr(const AutoReleasePtr &other) MOZ_DELETE;
AutoReleasePtr operator=(const AutoReleasePtr &other) MOZ_DELETE;
public:
explicit AutoReleasePtr(JSContext *cx, void *ptr
@ -1817,7 +1818,8 @@ class AutoReleaseNullablePtr {
void *ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other);
AutoReleaseNullablePtr(const AutoReleaseNullablePtr &other) MOZ_DELETE;
AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other) MOZ_DELETE;
public:
explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr

View File

@ -256,7 +256,7 @@ CopyErrorReport(JSContext *cx, JSErrorReport *report)
return copy;
}
static jsval *
static HeapValue *
GetStackTraceValueBuffer(JSExnPrivate *priv)
{
/*
@ -267,7 +267,7 @@ GetStackTraceValueBuffer(JSExnPrivate *priv)
*/
JS_STATIC_ASSERT(sizeof(JSStackTraceElem) % sizeof(jsval) == 0);
return (jsval *)(priv->stackElems + priv->stackDepth);
return reinterpret_cast<HeapValue *>(priv->stackElems + priv->stackDepth);
}
struct SuppressErrorsGuard
@ -359,7 +359,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
size_t nbytes = offsetof(JSExnPrivate, stackElems) +
frames.length() * sizeof(JSStackTraceElem) +
values.length() * sizeof(Value);
values.length() * sizeof(HeapValue);
JSExnPrivate *priv = (JSExnPrivate *)cx->malloc_(nbytes);
if (!priv)
@ -391,11 +391,12 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
priv->exnType = exnType;
JSStackTraceElem *framesDest = priv->stackElems;
Value *valuesDest = reinterpret_cast<Value *>(framesDest + frames.length());
HeapValue *valuesDest = reinterpret_cast<HeapValue *>(framesDest + frames.length());
JS_ASSERT(valuesDest == GetStackTraceValueBuffer(priv));
PodCopy(framesDest, frames.begin(), frames.length());
PodCopy(valuesDest, values.begin(), values.length());
for (size_t i = 0; i < values.length(); ++i)
valuesDest[i].init(cx->compartment, values[i]);
SetExnPrivate(cx, exnObject, priv);
return true;
@ -414,7 +415,7 @@ exn_trace(JSTracer *trc, JSObject *obj)
JSExnPrivate *priv;
JSStackTraceElem *elem;
size_t vcount, i;
jsval *vp, v;
HeapValue *vp;
priv = GetExnPrivate(obj);
if (priv) {
@ -433,9 +434,7 @@ exn_trace(JSTracer *trc, JSObject *obj)
}
vp = GetStackTraceValueBuffer(priv);
for (i = 0; i != vcount; ++i, ++vp) {
/* This value is read-only, so it's okay for it to be Unbarriered. */
v = *vp;
MarkValueUnbarriered(trc, v, "stack trace argument");
MarkValue(trc, *vp, "stack trace argument");
}
}
}
@ -605,7 +604,7 @@ StackTraceToString(JSContext *cx, JSExnPrivate *priv)
jschar *stackbuf;
size_t stacklen, stackmax;
JSStackTraceElem *elem, *endElem;
jsval *values;
HeapValue *values;
size_t i;
JSString *str;
const char *cp;

View File

@ -1735,7 +1735,7 @@ JSFunction::initBoundFunction(JSContext *cx, const Value &thisArg,
setSlot(JSSLOT_BOUND_FUNCTION_THIS, thisArg);
setSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT, PrivateUint32Value(argslen));
copySlotRange(BOUND_FUNCTION_RESERVED_SLOTS, args, argslen, false);
initSlotRange(BOUND_FUNCTION_RESERVED_SLOTS, args, argslen);
return true;
}

View File

@ -38,9 +38,12 @@
*
* ***** END LICENSE BLOCK ***** */
/* JS Mark-and-Sweep Garbage Collector. */
#include "mozilla/Attributes.h"
#include "mozilla/Util.h"
/*
* JS Mark-and-Sweep Garbage Collector.
*
* This GC allocates fixed-sized things with sizes up to GC_NBYTES_MAX (see
* jsgc.h). It allocates from a special GC arena pool with each arena allocated
* using malloc. It uses an ideally parallel array of flag bytes to hold the
@ -51,8 +54,6 @@
#include <math.h>
#include <string.h> /* for memset used when DEBUG */
#include "mozilla/Util.h"
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h"
@ -473,42 +474,16 @@ ChunkPool::get(JSRuntime *rt)
/* Must be called either during the GC or with the GC lock taken. */
inline void
ChunkPool::put(JSRuntime *rt, Chunk *chunk)
ChunkPool::put(Chunk *chunk)
{
JS_ASSERT(this == &rt->gcChunkPool);
size_t initialAge = 0;
#ifdef JS_THREADSAFE
/*
* When we have not yet started the background finalization, we must keep
* empty chunks until we are done with all the sweeping and finalization
* that cannot be done in the background even if shouldShrink() is true.
* This way we can safely call IsAboutToBeFinalized and Cell::isMarked for
* finalized GC things in empty chunks. So we only release the chunk if we
* are called from the background thread.
*/
if (rt->gcHelperThread.sweeping()) {
if (rt->gcHelperThread.shouldShrink()) {
Chunk::release(rt, chunk);
return;
}
/*
* Set the age to one as we expire chunks early during the background
* sweep so this chunk already survived one GC cycle.
*/
initialAge = 1;
}
#endif
chunk->info.age = initialAge;
chunk->info.age = 0;
chunk->info.next = emptyChunkListHead;
emptyChunkListHead = chunk;
emptyCount++;
}
/* Must be called either during the GC or with the GC lock taken. */
void
Chunk *
ChunkPool::expire(JSRuntime *rt, bool releaseAll)
{
JS_ASSERT(this == &rt->gcChunkPool);
@ -519,6 +494,7 @@ ChunkPool::expire(JSRuntime *rt, bool releaseAll)
* without emptying the list, the older chunks will stay at the tail
* and are more likely to reach the max age.
*/
Chunk *freeList = NULL;
for (Chunk **chunkp = &emptyChunkListHead; *chunkp; ) {
JS_ASSERT(emptyCount);
Chunk *chunk = *chunkp;
@ -528,7 +504,9 @@ ChunkPool::expire(JSRuntime *rt, bool releaseAll)
if (releaseAll || chunk->info.age == MAX_EMPTY_CHUNK_AGE) {
*chunkp = chunk->info.next;
--emptyCount;
Chunk::release(rt, chunk);
chunk->prepareToBeFreed(rt);
chunk->info.next = freeList;
freeList = chunk;
} else {
/* Keep the chunk but increase its age. */
++chunk->info.age;
@ -536,6 +514,7 @@ ChunkPool::expire(JSRuntime *rt, bool releaseAll)
}
}
JS_ASSERT_IF(releaseAll, !emptyCount);
return freeList;
}
JS_FRIEND_API(int64_t)
@ -570,12 +549,36 @@ Chunk::allocate(JSRuntime *rt)
Chunk::release(JSRuntime *rt, Chunk *chunk)
{
JS_ASSERT(chunk);
JS_ASSERT(rt->gcNumArenasFreeCommitted >= chunk->info.numArenasFreeCommitted);
rt->gcNumArenasFreeCommitted -= chunk->info.numArenasFreeCommitted;
rt->gcStats.count(gcstats::STAT_DESTROY_CHUNK);
chunk->prepareToBeFreed(rt);
FreeChunk(chunk);
}
static void
FreeChunkList(Chunk *chunkListHead)
{
while (Chunk *chunk = chunkListHead) {
JS_ASSERT(!chunk->info.numArenasFreeCommitted);
chunkListHead = chunk->info.next;
FreeChunk(chunk);
}
}
inline void
Chunk::prepareToBeFreed(JSRuntime *rt)
{
JS_ASSERT(rt->gcNumArenasFreeCommitted >= info.numArenasFreeCommitted);
rt->gcNumArenasFreeCommitted -= info.numArenasFreeCommitted;
rt->gcStats.count(gcstats::STAT_DESTROY_CHUNK);
#ifdef DEBUG
/*
* Let FreeChunkList detect a missing prepareToBeFreed call before it
* frees chunk.
*/
info.numArenasFreeCommitted = 0;
#endif
}
void
Chunk::init()
{
@ -723,6 +726,17 @@ Chunk::allocateArena(JSCompartment *comp, AllocKind thingKind)
return aheader;
}
inline void
Chunk::addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader)
{
JS_ASSERT(!aheader->allocated());
aheader->next = info.freeArenasHead;
info.freeArenasHead = aheader;
++info.numArenasFreeCommitted;
++info.numArenasFree;
++rt->gcNumArenasFreeCommitted;
}
void
Chunk::releaseArena(ArenaHeader *aheader)
{
@ -749,11 +763,7 @@ Chunk::releaseArena(ArenaHeader *aheader)
JS_ATOMIC_ADD(&comp->gcBytes, -int32_t(ArenaSize));
aheader->setAsNotAllocated();
aheader->next = info.freeArenasHead;
info.freeArenasHead = aheader;
++info.numArenasFreeCommitted;
++info.numArenasFree;
++rt->gcNumArenasFreeCommitted;
addArenaToFreeList(rt, aheader);
if (info.numArenasFree == 1) {
JS_ASSERT(!info.prevp);
@ -764,7 +774,7 @@ Chunk::releaseArena(ArenaHeader *aheader)
} else {
rt->gcChunkSet.remove(this);
removeFromAvailableList();
rt->gcChunkPool.put(rt, this);
rt->gcChunkPool.put(this);
}
}
@ -1172,7 +1182,7 @@ js_FinishGC(JSRuntime *rt)
* Finish the pool after the background thread stops in case it was doing
* the background sweeping.
*/
rt->gcChunkPool.expire(rt, true);
FreeChunkList(rt->gcChunkPool.expire(rt, true));
#ifdef DEBUG
if (!rt->gcRootsHash.empty())
@ -1332,7 +1342,7 @@ JSRuntime::setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind)
void
JSRuntime::reduceGCTriggerBytes(uint32_t amount) {
JS_ASSERT(amount > 0);
JS_ASSERT(gcTriggerBytes - amount >= 0);
JS_ASSERT(gcTriggerBytes >= amount);
if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * GC_HEAP_GROWTH_FACTOR)
return;
gcTriggerBytes -= amount;
@ -1351,7 +1361,7 @@ JSCompartment::setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind)
void
JSCompartment::reduceGCTriggerBytes(uint32_t amount) {
JS_ASSERT(amount > 0);
JS_ASSERT(gcTriggerBytes - amount >= 0);
JS_ASSERT(gcTriggerBytes >= amount);
if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * GC_HEAP_GROWTH_FACTOR)
return;
gcTriggerBytes -= amount;
@ -2195,12 +2205,99 @@ MaybeGC(JSContext *cx)
}
}
} /* namespace js */
static void
DecommitArenasFromAvailableList(JSRuntime *rt, Chunk **availableListHeadp)
{
Chunk *chunk = *availableListHeadp;
if (!chunk)
return;
/*
* Decommit is expensive so we avoid holding the GC lock while calling it.
*
* We decommit from the tail of the list to minimize interference with the
* main thread that may start to allocate things at this point.
*/
JS_ASSERT(chunk->info.prevp == availableListHeadp);
while (Chunk *next = chunk->info.next) {
JS_ASSERT(next->info.prevp == &chunk->info.next);
chunk = next;
}
for (;;) {
while (chunk->info.numArenasFreeCommitted != 0) {
/*
* The arena that is been decommitted outside the GC lock must not
* be available for allocations either via the free list or via
* the decommittedArenas bitmap. For that we just fetch the arena
* from the free list before the decommit and then mark it as free
* and decommitted when we retake the GC lock.
*
* We also must make sure that the aheader is not accessed again
* after we decommit the arena.
*/
ArenaHeader *aheader = chunk->fetchNextFreeArena(rt);
size_t arenaIndex = Chunk::arenaIndex(aheader->arenaAddress());
bool ok;
{
AutoUnlockGC unlock(rt);
ok = DecommitMemory(aheader->getArena(), ArenaSize);
}
if (ok) {
++chunk->info.numArenasFree;
chunk->decommittedArenas.set(arenaIndex);
} else {
chunk->addArenaToFreeList(rt, aheader);
}
if (rt->gcChunkAllocationSinceLastGC) {
/*
* The allocator thread has started to get new chunks. We should stop
* to avoid decommitting arenas in just allocated chunks.
*/
return;
}
}
/*
* prevp becomes null when the allocator thread consumed all chunks from
* the available list.
*/
JS_ASSERT_IF(chunk->info.prevp, *chunk->info.prevp == chunk);
if (chunk->info.prevp == availableListHeadp || !chunk->info.prevp)
break;
/*
* prevp exists and is not the list head. It must point to the next
* field of the previous chunk.
*/
chunk = chunk->getPrevious();
}
}
static void
DecommitArenas(JSRuntime *rt)
{
DecommitArenasFromAvailableList(rt, &rt->gcSystemAvailableChunkListHead);
DecommitArenasFromAvailableList(rt, &rt->gcUserAvailableChunkListHead);
}
/* Must be called with the GC lock taken. */
static void
ExpireChunksAndArenas(JSRuntime *rt, bool shouldShrink)
{
if (Chunk *toFree = rt->gcChunkPool.expire(rt, shouldShrink)) {
AutoUnlockGC unlock(rt);
FreeChunkList(toFree);
}
if (shouldShrink)
DecommitArenas(rt);
}
#ifdef JS_THREADSAFE
namespace js {
bool
GCHelperThread::init()
{
@ -2286,7 +2383,7 @@ GCHelperThread::threadLoop()
break;
JS_ASSERT(chunk->info.numArenasFreeCommitted == ArenasPerChunk);
rt->gcNumArenasFreeCommitted += ArenasPerChunk;
rt->gcChunkPool.put(rt, chunk);
rt->gcChunkPool.put(chunk);
} while (state == ALLOCATING && rt->gcChunkPool.wantBackgroundAllocation(rt));
if (state == ALLOCATING)
state = IDLE;
@ -2375,42 +2472,40 @@ GCHelperThread::doSweep()
{
JS_ASSERT(context);
/*
* Expire the chunks released during the GC so they will be available to
* the rest of the system immediately.
*/
rt->gcChunkPool.expire(rt, shouldShrink());
{
AutoUnlockGC unlock(rt);
AutoUnlockGC unlock(rt);
/*
* We must finalize in the insert order, see comments in
* finalizeObjects.
*/
for (ArenaHeader **i = finalizeVector.begin(); i != finalizeVector.end(); ++i)
ArenaLists::backgroundFinalize(context, *i);
finalizeVector.resize(0);
/*
* We must finalize in the insert order, see comments in
* finalizeObjects.
*/
for (ArenaHeader **i = finalizeVector.begin(); i != finalizeVector.end(); ++i)
ArenaLists::backgroundFinalize(context, *i);
finalizeVector.resize(0);
context = NULL;
context = NULL;
if (freeCursor) {
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
freeElementsAndArray(array, freeCursor);
freeCursor = freeCursorEnd = NULL;
} else {
JS_ASSERT(!freeCursorEnd);
if (freeCursor) {
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
freeElementsAndArray(array, freeCursor);
freeCursor = freeCursorEnd = NULL;
} else {
JS_ASSERT(!freeCursorEnd);
}
for (void ***iter = freeVector.begin(); iter != freeVector.end(); ++iter) {
void **array = *iter;
freeElementsAndArray(array, array + FREE_ARRAY_LENGTH);
}
freeVector.resize(0);
}
for (void ***iter = freeVector.begin(); iter != freeVector.end(); ++iter) {
void **array = *iter;
freeElementsAndArray(array, array + FREE_ARRAY_LENGTH);
}
freeVector.resize(0);
ExpireChunksAndArenas(rt, shouldShrink());
}
} /* namespace js */
#endif /* JS_THREADSAFE */
} /* namespace js */
static bool
ReleaseObservedTypes(JSContext *cx)
{
@ -2426,43 +2521,6 @@ ReleaseObservedTypes(JSContext *cx)
return releaseTypes;
}
static void
DecommitFreePages(JSContext *cx)
{
JSRuntime *rt = cx->runtime;
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
Chunk *chunk = r.front();
ArenaHeader *aheader = chunk->info.freeArenasHead;
/*
* In the non-failure case, the list will be gone at the end of
* the loop. In the case where we fail, we relink all failed
* decommits into a new list on freeArenasHead.
*/
chunk->info.freeArenasHead = NULL;
while (aheader) {
/* Store aside everything we will need after decommit. */
ArenaHeader *next = aheader->next;
bool success = DecommitMemory(aheader, ArenaSize);
if (!success) {
aheader->next = chunk->info.freeArenasHead;
chunk->info.freeArenasHead = aheader;
continue;
}
size_t arenaIndex = Chunk::arenaIndex(aheader->arenaAddress());
chunk->decommittedArenas.set(arenaIndex);
--chunk->info.numArenasFreeCommitted;
--rt->gcNumArenasFreeCommitted;
aheader = next;
}
}
}
static void
SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
{
@ -2656,11 +2714,8 @@ SweepPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind)
* use IsAboutToBeFinalized().
* This is done on the GCHelperThread if JS_THREADSAFE is defined.
*/
rt->gcChunkPool.expire(rt, gckind == GC_SHRINK);
ExpireChunksAndArenas(rt, gckind == GC_SHRINK);
#endif
if (gckind == GC_SHRINK)
DecommitFreePages(cx);
}
{
@ -2782,9 +2837,8 @@ class AutoGCSession {
private:
JSContext *context;
/* Disable copy constructor or assignments */
AutoGCSession(const AutoGCSession&);
void operator=(const AutoGCSession&);
AutoGCSession(const AutoGCSession&) MOZ_DELETE;
void operator=(const AutoGCSession&) MOZ_DELETE;
};
/*

View File

@ -598,23 +598,23 @@ struct ChunkInfo {
*
* For the mark bitmap, we know that each arena will use a fixed number of full
* bytes: ArenaBitmapBytes. The full size of the header data is this number
* multiplied by the eventual number of arenas we have in the header. We,
* multiplied by the eventual number of arenas we have in the header. We,
* conceptually, distribute this header data among the individual arenas and do
* not include it in the header. This way we do not have to worry about its
* not include it in the header. This way we do not have to worry about its
* variable size: it gets attached to the variable number we are computing.
*
* For the decommitted arena bitmap, we only have 1 bit per arena, so this
* technique will not work. Instead, we observe that we do not have enough
* header info to fill 8 full arenas: it is currently 4 on 64bit, less on
* header info to fill 8 full arenas: it is currently 4 on 64bit, less on
* 32bit. Thus, with current numbers, we need 64 bytes for decommittedArenas.
* This will not become 63 bytes unless we double the data required in the
* header. Therefore, we just compute the number of bytes required to track
* This will not become 63 bytes unless we double the data required in the
* header. Therefore, we just compute the number of bytes required to track
* every possible arena and do not worry about slop bits, since there are too
* few to usefully allocate.
*
* To actually compute the number of arenas we can allocate in a chunk, we
* divide the amount of available space less the header info (not including
* the mark bitmap which is distributed into the arena size) by the size of
* the mark bitmap which is distributed into the arena size) by the size of
* the arena (with the mark bitmap bytes it uses).
*/
const size_t BytesPerArenaWithHeader = ArenaSize + ArenaBitmapBytes;
@ -749,6 +749,21 @@ struct Chunk {
/* Must be called with the GC lock taken. */
static inline void release(JSRuntime *rt, Chunk *chunk);
static inline void releaseList(JSRuntime *rt, Chunk *chunkListHead);
/* Must be called with the GC lock taken. */
inline void prepareToBeFreed(JSRuntime *rt);
/*
* Assuming that the info.prevp points to the next field of the previous
* chunk in a doubly-linked list, get that chunk.
*/
Chunk *getPrevious() {
JS_ASSERT(info.prevp);
uintptr_t prevAddress = reinterpret_cast<uintptr_t>(info.prevp);
JS_ASSERT((prevAddress & ChunkMask) == offsetof(Chunk, info.next));
return reinterpret_cast<Chunk *>(prevAddress - offsetof(Chunk, info.next));
}
private:
inline void init();
@ -757,8 +772,11 @@ struct Chunk {
jsuint findDecommittedArenaOffset();
ArenaHeader* fetchNextDecommittedArena();
public:
/* Unlink and return the freeArenasHead. */
inline ArenaHeader* fetchNextFreeArena(JSRuntime *rt);
inline void addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader);
};
JS_STATIC_ASSERT(sizeof(Chunk) == ChunkSize);
@ -782,10 +800,13 @@ class ChunkPool {
inline Chunk *get(JSRuntime *rt);
/* Must be called either during the GC or with the GC lock taken. */
inline void put(JSRuntime *rt, Chunk *chunk);
inline void put(Chunk *chunk);
/* Must be called either during the GC or with the GC lock taken. */
void expire(JSRuntime *rt, bool releaseAll);
/*
* Return the list of chunks that can be released outside the GC lock.
* Must be called either during the GC or with the GC lock taken.
*/
Chunk *expire(JSRuntime *rt, bool releaseAll);
/* Must be called either during the GC or with the GC lock taken. */
JS_FRIEND_API(int64_t) countCleanDecommittedArenas(JSRuntime *rt);
@ -1720,7 +1741,7 @@ struct GCMarker : public JSTracer {
void drainMarkStack();
inline void processMarkStackTop();
void pushObject(JSObject *obj) {
pushTaggedPtr(ObjectTag, obj);
}

View File

@ -2085,6 +2085,29 @@ types::UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc)
return false;
}
bool
types::ArrayPrototypeHasIndexedProperty(JSContext *cx, JSScript *script)
{
if (!cx->typeInferenceEnabled() || !script->hasGlobal())
return true;
JSObject *proto;
if (!js_GetClassPrototype(cx, NULL, JSProto_Array, &proto, NULL))
return true;
while (proto) {
TypeObject *type = proto->getType(cx);
if (type->unknownProperties())
return true;
TypeSet *indexTypes = type->getProperty(cx, JSID_VOID, false);
if (!indexTypes || indexTypes->isOwnProperty(cx, type, true) || indexTypes->knownNonEmpty(cx))
return true;
proto = proto->getProto();
}
return false;
}
bool
TypeCompartment::growPendingArray(JSContext *cx)
{

View File

@ -911,6 +911,13 @@ MarkArgumentsCreated(JSContext *cx, JSScript *script);
bool
UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc);
/*
* Whether Array.prototype, or an object on its proto chain, has an
* indexed property.
*/
bool
ArrayPrototypeHasIndexedProperty(JSContext *cx, JSScript *script);
/*
* Type information about a callsite. this is separated from the bytecode
* information itself so we can handle higher order functions not called

View File

@ -3620,7 +3620,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
if (normalUnwind) {
uintN slot = JSSLOT_BLOCK_FIRST_FREE_SLOT;
depth += fp->numFixed();
obj->copySlotRange(slot, fp->slots() + depth, count, true);
obj->copySlotRange(slot, fp->slots() + depth, count);
}
/* We must clear the private slot even with errors. */
@ -4037,7 +4037,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
a->shape_ = reserved.newashape;
a->slots = reserved.newaslots;
a->copySlotRange(0, reserved.bvals.begin(), bcap, false);
a->initSlotRange(0, reserved.bvals.begin(), bcap);
if (a->hasPrivate())
a->setPrivate(bpriv);
@ -4047,7 +4047,7 @@ JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &
b->shape_ = reserved.newbshape;
b->slots = reserved.newbslots;
b->copySlotRange(0, reserved.avals.begin(), acap, false);
b->initSlotRange(0, reserved.avals.begin(), acap);
if (b->hasPrivate())
b->setPrivate(apriv);
@ -4524,27 +4524,57 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
}
void
JSObject::copySlotRange(size_t start, const Value *vector, size_t length, bool valid)
JSObject::getSlotRange(size_t start, size_t length,
HeapValue **fixedStart, HeapValue **fixedEnd,
HeapValue **slotsStart, HeapValue **slotsEnd)
{
if (valid)
prepareSlotRangeForOverwrite(start, start + length);
JS_ASSERT(!isDenseArray());
JS_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
size_t fixed = numFixedSlots();
if (start < fixed) {
if (start + length < fixed) {
memcpy(fixedSlots() + start, vector, length * sizeof(Value));
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + length];
*slotsStart = *slotsEnd = NULL;
} else {
size_t localCopy = fixed - start;
memcpy(fixedSlots() + start, vector, localCopy * sizeof(Value));
memcpy(slots, vector + localCopy, (length - localCopy) * sizeof(Value));
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + localCopy];
*slotsStart = &slots[0];
*slotsEnd = &slots[length - localCopy];
}
} else {
memcpy(slots + start - fixed, vector, length * sizeof(Value));
*fixedStart = *fixedEnd = NULL;
*slotsStart = &slots[start - fixed];
*slotsEnd = &slots[start - fixed + length];
}
}
void
JSObject::initSlotRange(size_t start, const Value *vector, size_t length)
{
JSCompartment *comp = compartment();
HeapValue *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
for (HeapValue *vp = fixedStart; vp != fixedEnd; vp++)
vp->init(comp, *vector++);
for (HeapValue *vp = slotsStart; vp != slotsEnd; vp++)
vp->init(comp, *vector++);
}
void
JSObject::copySlotRange(size_t start, const Value *vector, size_t length)
{
JSCompartment *comp = compartment();
HeapValue *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
for (HeapValue *vp = fixedStart; vp != fixedEnd; vp++)
vp->set(comp, *vector++);
for (HeapValue *vp = slotsStart; vp != slotsEnd; vp++)
vp->set(comp, *vector++);
}
inline void
JSObject::invalidateSlotRange(size_t start, size_t length)
{

View File

@ -639,6 +639,14 @@ struct JSObject : js::gc::Cell
private:
inline js::HeapValue* fixedSlots() const;
/*
* Get internal pointers to the range of values starting at start and
* running for length.
*/
void getSlotRange(size_t start, size_t length,
js::HeapValue **fixedStart, js::HeapValue **fixedEnd,
js::HeapValue **slotsStart, js::HeapValue **slotsEnd);
public:
/* Accessors for properties. */
@ -690,7 +698,6 @@ struct JSObject : js::gc::Cell
inline bool updateSlotsForSpan(JSContext *cx, size_t oldSpan, size_t newSpan);
public:
/*
* Trigger the write barrier on a range of slots that will no longer be
* reachable.
@ -699,12 +706,16 @@ struct JSObject : js::gc::Cell
inline void prepareElementRangeForOverwrite(size_t start, size_t end);
/*
* Copy a flat array of slots to this object at a start slot. Caller must
* ensure there are enough slots in this object. If |valid|, then the slots
* being overwritten hold valid data and must be invalidated for the write
* barrier.
* Initialize a flat array of slots to this object at a start slot. The
* caller must ensure that are enough slots.
*/
void copySlotRange(size_t start, const js::Value *vector, size_t length, bool valid);
void initSlotRange(size_t start, const js::Value *vector, size_t length);
/*
* Copy a flat array of slots to this object at a start slot. Caller must
* ensure there are enough slots in this object.
*/
void copySlotRange(size_t start, const js::Value *vector, size_t length);
inline uint32_t slotSpan() const;

View File

@ -634,16 +634,18 @@ inline void
JSObject::copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count)
{
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
JSCompartment *comp = compartment();
for (unsigned i = 0; i < count; ++i)
elements[dstStart + i] = src[i];
elements[dstStart + i].set(comp, src[i]);
}
inline void
JSObject::initDenseArrayElements(uintN dstStart, const js::Value *src, uintN count)
{
JS_ASSERT(dstStart + count <= getDenseArrayCapacity());
JSCompartment *comp = compartment();
for (unsigned i = 0; i < count; ++i)
elements[dstStart + i].init(src[i]);
elements[dstStart + i].init(comp, src[i]);
}
inline void

View File

@ -41,6 +41,7 @@
#ifndef jsonparser_h___
#define jsonparser_h___
#include "mozilla/Attributes.h"
#include "mozilla/RangedPtr.h"
#include "jscntxt.h"
@ -51,6 +52,9 @@
*/
class JSONParser
{
JSONParser(const JSONParser &other) MOZ_DELETE;
void operator=(const JSONParser &other) MOZ_DELETE;
public:
enum ErrorHandling { RaiseError, NoError };
enum ParsingMode { StrictJSON, LegacyJSON };

View File

@ -2432,15 +2432,22 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
return leftAssociate(pn, dst);
}
case PNK_INC:
case PNK_DEC:
case PNK_PREINCREMENT:
case PNK_PREDECREMENT:
{
bool incr = pn->isKind(PNK_INC);
bool prefix = pn->getOp() >= JSOP_INCNAME && pn->getOp() <= JSOP_DECELEM;
bool inc = pn->isKind(PNK_PREINCREMENT);
Value expr;
return expression(pn->pn_kid, &expr) &&
builder.updateExpression(expr, incr, prefix, &pn->pn_pos, dst);
builder.updateExpression(expr, inc, true, &pn->pn_pos, dst);
}
case PNK_POSTINCREMENT:
case PNK_POSTDECREMENT:
{
bool inc = pn->isKind(PNK_POSTINCREMENT);
Value expr;
return expression(pn->pn_kid, &expr) &&
builder.updateExpression(expr, inc, false, &pn->pn_pos, dst);
}
case PNK_ASSIGN:

View File

@ -48,6 +48,9 @@
* of rooting things that might lose their newborn root due to subsequent GC
* allocations in the same native method.
*/
#include "mozilla/Attributes.h"
#include <stdlib.h>
#include <string.h>
#include "jstypes.h"
@ -1358,8 +1361,8 @@ class RegExpPair
*/
class RegExpGuard
{
RegExpGuard(const RegExpGuard &);
void operator=(const RegExpGuard &);
RegExpGuard(const RegExpGuard &) MOZ_DELETE;
void operator=(const RegExpGuard &) MOZ_DELETE;
JSContext *cx;
RegExpPair rep;

View File

@ -40,6 +40,8 @@
#ifndef jsstrinlines_h___
#define jsstrinlines_h___
#include "mozilla/Attributes.h"
#include "jsatom.h"
#include "jsstr.h"
@ -76,6 +78,9 @@ class StringBuffer
JSContext *context() const { return cb.allocPolicy().context(); }
jschar *extractWellSized();
StringBuffer(const StringBuffer &other) MOZ_DELETE;
void operator=(const StringBuffer &other) MOZ_DELETE;
public:
explicit inline StringBuffer(JSContext *cx);
bool reserve(size_t len);
@ -243,6 +248,9 @@ class RopeBuilder {
JSContext *cx;
JSString *res;
RopeBuilder(const RopeBuilder &other) MOZ_DELETE;
void operator=(const RopeBuilder &other) MOZ_DELETE;
public:
RopeBuilder(JSContext *cx)
: cx(cx), res(cx->runtime->emptyString)

View File

@ -1687,9 +1687,7 @@ class TypedArrayTemplate
{
JS_ASSERT(tarray);
JS_ASSERT(0 <= begin);
JS_ASSERT(begin <= getLength(tarray));
JS_ASSERT(0 <= end);
JS_ASSERT(end <= getLength(tarray));
JSObject *bufobj = getBuffer(tarray);

View File

@ -44,6 +44,8 @@
#ifndef jsutil_h___
#define jsutil_h___
#include "mozilla/Attributes.h"
#include "js/Utility.h"
/* Forward declarations. */
@ -223,8 +225,8 @@ class AutoRefCount
JSContext *const cx;
RefCountable *obj;
AutoRefCount(const AutoRefCount &);
void operator=(const AutoRefCount &);
AutoRefCount(const AutoRefCount &other) MOZ_DELETE;
void operator=(const AutoRefCount &other) MOZ_DELETE;
public:
explicit AutoRefCount(JSContext *cx)

View File

@ -7610,29 +7610,6 @@ mjit::Compiler::pushedSingleton(unsigned pushed)
return types->getSingleton(cx);
}
bool
mjit::Compiler::arrayPrototypeHasIndexedProperty()
{
if (!cx->typeInferenceEnabled() || !globalObj)
return true;
JSObject *proto;
if (!js_GetClassPrototype(cx, NULL, JSProto_Array, &proto, NULL))
return true;
while (proto) {
types::TypeObject *type = proto->getType(cx);
if (type->unknownProperties())
return true;
types::TypeSet *indexTypes = type->getProperty(cx, JSID_VOID, false);
if (!indexTypes || indexTypes->isOwnProperty(cx, type, true) || indexTypes->knownNonEmpty(cx))
return true;
proto = proto->getProto();
}
return false;
}
/*
* Barriers overview.
*

View File

@ -486,8 +486,6 @@ private:
return callSites[index].inlinepc;
}
bool arrayPrototypeHasIndexedProperty();
bool activeFrameHasMultipleExits() {
ActiveFrame *na = a;
while (na->parent) {

View File

@ -881,7 +881,7 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew)
*/
if (!thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY |
types::OBJECT_FLAG_ITERATED) &&
!arrayPrototypeHasIndexedProperty()) {
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) {
bool packed = !thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
return compileArrayPopShift(thisValue, packed, native == js::array_pop);
}
@ -931,7 +931,7 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew)
* generated by TypeConstraintCall during inference.
*/
if (!thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
!arrayPrototypeHasIndexedProperty()) {
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) {
return compileArrayPush(thisValue, arg);
}
}

View File

@ -1521,7 +1521,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
types::TypeSet *types = analysis->poppedTypes(PC, 2);
if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
!arrayPrototypeHasIndexedProperty()) {
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) {
// Inline dense array path.
jsop_setelem_dense();
return true;
@ -2113,7 +2113,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
!arrayPrototypeHasIndexedProperty()) {
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) {
// Inline dense array path.
bool packed = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
jsop_getelem_dense(packed);

View File

@ -1125,8 +1125,10 @@ FrameState::frameSlot(ActiveFrame *a, const FrameEntry *fe) const
}
inline JSC::MacroAssembler::Address
FrameState::addressForInlineReturn() const
FrameState::addressForInlineReturn()
{
if (a->callee_->isTracked())
discardFe(a->callee_);
return addressOf(a->callee_);
}

View File

@ -877,7 +877,7 @@ class FrameState
Address addressForDataRemat(const FrameEntry *fe) const;
// Inside an inline frame, the address for the return value in the caller.
Address addressForInlineReturn() const;
Address addressForInlineReturn();
inline StateRemat dataRematInfo(const FrameEntry *fe) const;

View File

@ -1715,7 +1715,7 @@ LoopState::definiteArrayAccess(const SSAValue &obj, const SSAValue &index)
if (objTypes->hasObjectFlags(cx, OBJECT_FLAG_NON_DENSE_ARRAY))
return false;
if (cc.arrayPrototypeHasIndexedProperty())
if (ArrayPrototypeHasIndexedProperty(cx, outerScript))
return false;
uint32_t objSlot;

View File

@ -2333,16 +2333,9 @@ DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
static JSBool
DumpStats(JSContext *cx, uintN argc, jsval *vp)
{
uintN i;
JSString *str;
jsid id;
JSObject *obj2;
JSProperty *prop;
Value value;
jsval *argv = JS_ARGV(cx, vp);
for (i = 0; i < argc; i++) {
str = JS_ValueToString(cx, argv[i]);
for (uintN i = 0; i < argc; i++) {
JSString *str = JS_ValueToString(cx, argv[i]);
if (!str)
return JS_FALSE;
argv[i] = STRING_TO_JSVAL(str);
@ -2354,24 +2347,10 @@ DumpStats(JSContext *cx, uintN argc, jsval *vp)
} else if (JS_FlatStringEqualsAscii(flatStr, "global")) {
DumpScope(cx, cx->globalObject, stdout);
} else {
if (!JS_ValueToId(cx, STRING_TO_JSVAL(str), &id))
return JS_FALSE;
JSObject *obj;
if (!js_FindProperty(cx, id, false, &obj, &obj2, &prop))
return JS_FALSE;
if (prop) {
if (!obj->getGeneric(cx, id, &value))
return JS_FALSE;
}
if (!prop || !value.isObjectOrNull()) {
fputs("js: invalid stats argument ", gErrFile);
JS_FileEscapedString(gErrFile, str, 0);
putc('\n', gErrFile);
continue;
}
obj = value.toObjectOrNull();
if (obj)
DumpScope(cx, obj, stdout);
fputs("js: invalid stats argument ", gErrFile);
JS_FileEscapedString(gErrFile, str, 0);
putc('\n', gErrFile);
continue;
}
}
JS_SET_RVAL(cx, vp, JSVAL_VOID);
@ -4117,7 +4096,7 @@ static const char *const shell_help_messages[] = {
" Interface to JS_DumpHeap with output sent to file",
"dumpObject() Dump an internal representation of an object",
"notes([fun]) Show source notes for functions",
"stats([string ...]) Dump 'arena', 'atom', 'global' stats",
"stats([string ...]) Dump 'atom' or 'global' stats",
"findReferences(target)\n"
" Walk the entire heap, looking for references to |target|, and return a\n"
" \"references object\" describing what we found.\n"

View File

@ -99,16 +99,14 @@ namespace workers {
template <class T, class AllocPolicy>
class Queue {
private:
typedef Vector<T, 4, AllocPolicy> Vec;
Vec v1;
Vec v2;
Vec *front;
Vec *back;
// Queue is not copyable.
Queue(const Queue &);
Queue & operator=(const Queue &);
Queue(const Queue &) MOZ_DELETE;
Queue & operator=(const Queue &) MOZ_DELETE;
public:
Queue() : front(&v1), back(&v2) {}

View File

@ -45,9 +45,9 @@ skip script regress-330569.js # Yarr doesn't bail on complex regexps.
script regress-333541.js
skip script regress-335700.js # bug xxx - reftest hang, BigO
skip-if(!xulRuntime.shell||Android) slow script regress-336409-1.js # no results reported.
skip-if(!xulRuntime.shell&&((Android||(isDebugBuild&&xulRuntime.OS=="Linux")||xulRuntime.XPCOMABI.match(/x86_64/)))) silentfail script regress-336409-2.js # can fail silently due to out of memory, bug 615011 - timeouts on slow debug Linux
skip-if(!xulRuntime.shell||Android) silentfail script regress-336410-1.js # can fail silently due to out of memory
skip-if(!xulRuntime.shell&&((isDebugBuild&&xulRuntime.OS=="Linux")||Android||xulRuntime.XPCOMABI.match(/x86_64/)||xulRuntime.OS=="WINNT")) silentfail script regress-336410-2.js # can fail silently due to out of memory, bug 621348 - timeouts on slow debug Linux
skip-if(!xulRuntime.shell&&((Android||(isDebugBuild&&xulRuntime.OS=="Linux")||xulRuntime.XPCOMABI.match(/x86_64/)))) silentfail slow script regress-336409-2.js # can fail silently due to out of memory, bug 615011 - timeouts on slow debug Linux
skip-if(!xulRuntime.shell||Android) silentfail slow script regress-336410-1.js # can fail silently due to out of memory
skip-if(!xulRuntime.shell&&((isDebugBuild&&xulRuntime.OS=="Linux")||Android||xulRuntime.XPCOMABI.match(/x86_64/)||xulRuntime.OS=="WINNT")) silentfail slow script regress-336410-2.js # can fail silently due to out of memory, bug 621348 - timeouts on slow debug Linux
script regress-338804-01.js
script regress-338804-02.js
script regress-338804-03.js
@ -55,7 +55,7 @@ script regress-339685.js
script regress-341956-01.js
script regress-341956-02.js
script regress-341956-03.js
skip-if(!xulRuntime.shell&&(Android||xulRuntime.OS=="WINNT"||xulRuntime.OS=="Linux")) silentfail script regress-342960.js # bug 528464
skip-if(!xulRuntime.shell&&(Android||xulRuntime.OS=="WINNT"||xulRuntime.OS=="Linux")) silentfail slow script regress-342960.js # bug 528464
skip script regress-345967.js # slow
script regress-346494-01.js
script regress-346494.js

View File

@ -41,6 +41,8 @@
#ifndef BooleanObject_h___
#define BooleanObject_h___
#include "mozilla/Attributes.h"
#include "jsbool.h"
namespace js {
@ -80,8 +82,8 @@ class BooleanObject : public ::JSObject
::js_InitBooleanClass(JSContext *cx, JSObject *global);
private:
BooleanObject();
BooleanObject &operator=(const BooleanObject &bo);
BooleanObject() MOZ_DELETE;
BooleanObject &operator=(const BooleanObject &bo) MOZ_DELETE;
};
} // namespace js

View File

@ -165,8 +165,8 @@ inline void
CallObject::copyValues(uintN nargs, Value *argv, uintN nvars, Value *slots)
{
JS_ASSERT(slotInRange(RESERVED_SLOTS + nargs + nvars, SENTINEL_ALLOWED));
copySlotRange(RESERVED_SLOTS, argv, nargs, true);
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars, true);
copySlotRange(RESERVED_SLOTS, argv, nargs);
copySlotRange(RESERVED_SLOTS + nargs, slots, nvars);
}
inline js::HeapValueArray

View File

@ -41,6 +41,8 @@
#ifndef GlobalObject_h___
#define GlobalObject_h___
#include "mozilla/Attributes.h"
#include "jsarray.h"
#include "jsbool.h"
#include "jsfun.h"
@ -90,6 +92,9 @@ class Debugger;
* again if its property is deleted and readded).
*/
class GlobalObject : public ::JSObject {
GlobalObject(const GlobalObject &other) MOZ_DELETE;
void operator=(const GlobalObject &other) MOZ_DELETE;
/*
* Count of slots to store built-in constructors, prototypes, and initial
* visible properties for the constructors.

View File

@ -41,6 +41,8 @@
#ifndef NumberObject_h___
#define NumberObject_h___
#include "mozilla/Attributes.h"
#include "jsnum.h"
namespace js {
@ -80,8 +82,8 @@ class NumberObject : public ::JSObject
::js_InitNumberClass(JSContext *cx, JSObject *global);
private:
NumberObject();
NumberObject &operator=(const NumberObject &so);
NumberObject() MOZ_DELETE;
NumberObject &operator=(const NumberObject &so) MOZ_DELETE;
};
} // namespace js

View File

@ -41,6 +41,8 @@
#ifndef RegExpObject_h__
#define RegExpObject_h__
#include "mozilla/Attributes.h"
#include <stddef.h>
#include "jsobj.h"
@ -200,8 +202,8 @@ class RegExpObject : public ::JSObject
*/
Shape *assignInitialShape(JSContext *cx);
RegExpObject();
RegExpObject &operator=(const RegExpObject &reo);
RegExpObject() MOZ_DELETE;
RegExpObject &operator=(const RegExpObject &reo) MOZ_DELETE;
}; /* class RegExpObject */
/* Either builds a new RegExpObject or re-initializes an existing one. */

View File

@ -41,6 +41,8 @@
#ifndef StringObject_h___
#define StringObject_h___
#include "mozilla/Attributes.h"
#include "jsobj.h"
#include "jsstr.h"
@ -95,8 +97,8 @@ class StringObject : public ::JSObject
Shape *assignInitialShape(JSContext *cx);
private:
StringObject();
StringObject &operator=(const StringObject &so);
StringObject() MOZ_DELETE;
StringObject &operator=(const StringObject &so) MOZ_DELETE;
};
} // namespace js

View File

@ -73,7 +73,7 @@
* to *_retval unless they want to return PR_FALSE.
*/
[uuid(9cadb17b-9990-461a-8e01-cf50aeffc2c5)]
[uuid(a40ce52e-2d8c-400f-9af2-f8784a656070)]
interface nsIXPCScriptable : nsISupports
{
/* bitflags used for 'flags' (only 32 bits available!) */
@ -191,14 +191,6 @@ interface nsIXPCScriptable : nsISupports
in JSContextPtr cx, in JSObjectPtr obj);
void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto);
/**
* Notify that we're about to create the prototype object for this class,
* and ask what prototype we should use for that.
*/
void preCreatePrototype(in JSContextPtr cx,
in JSObjectPtr globalObj,
out JSObjectPtr protoProtoObj);
};
%{ C++

View File

@ -965,10 +965,20 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile,
// See bug 384168.
*aGlobal = global;
if (!JS_ExecuteScriptVersion(cx, global, script, NULL, JSVERSION_LATEST)) {
uint32 oldopts = JS_GetOptions(cx);
JS_SetOptions(cx, oldopts |
(exception ? JSOPTION_DONT_REPORT_UNCAUGHT : 0));
bool ok = JS_ExecuteScriptVersion(cx, global, script, NULL, JSVERSION_LATEST);
JS_SetOptions(cx, oldopts);
if (!ok) {
#ifdef DEBUG_shaver_off
fprintf(stderr, "mJCL: failed to execute %s\n", nativePath.get());
#endif
if (exception) {
JS_GetPendingException(cx, exception);
JS_ClearPendingException(cx);
}
*aGlobal = nsnull;
return NS_ERROR_FAILURE;
}

View File

@ -228,11 +228,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext *cx, JSObject *pr
{return NS_OK;}
#endif
#ifndef XPC_MAP_WANT_PRE_CREATE_PROTOTYPE
NS_IMETHODIMP XPC_MAP_CLASSNAME::PreCreatePrototype(JSContext *cx, JSObject *global, JSObject **protoProto)
{*protoProto = nsnull; return NS_OK;}
#endif
/**************************************************************/
#undef XPC_MAP_CLASSNAME
@ -318,10 +313,6 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::PreCreatePrototype(JSContext *cx, JSObject *glo
#undef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
#endif
#ifdef XPC_MAP_WANT_PRE_CREATE_PROTOTYPE
#undef XPC_MAP_WANT_PRE_CREATE_PROTOTYPE
#endif
#ifdef XPC_MAP_FLAGS
#undef XPC_MAP_FLAGS
#endif

View File

@ -123,22 +123,10 @@ XPCWrappedNativeProto::Init(XPCCallContext& ccx,
JSObject *parent = mScope->GetGlobalJSObject();
JSObject *protoProto = nsnull;
if (callback) {
nsresult rv = callback->PreCreatePrototype(ccx, parent, &protoProto);
if (NS_FAILED(rv)) {
mJSProtoObject = nsnull;
XPCThrower::Throw(rv, ccx);
return false;
}
}
if (!protoProto) {
protoProto = mScope->GetPrototypeJSObject();
}
mJSProtoObject =
xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(jsclazz),
protoProto, true, parent);
mScope->GetPrototypeJSObject(),
true, parent);
JSBool ok = mJSProtoObject && JS_SetPrivate(ccx, mJSProtoObject, this);

View File

@ -0,0 +1 @@
Components.utils.import("resource://test/syntax_error.jsm");

View File

@ -0,0 +1,10 @@
function run_test()
{
try {
Components.utils.import("resource://test/importer.jsm");
do_check_true(false, "import should not succeed.");
} catch (x) {
do_check_neq(x.fileName.indexOf("syntax_error.jsm"), -1);
do_check_eq(x.lineNumber, 1);
}
}

View File

@ -14,6 +14,7 @@ tail =
[test_bug_442086.js]
[test_file.js]
[test_import.js]
[test_import_fail.js]
[test_js_weak_references.js]
[test_reflect_parse.js]
[test_localeCompare.js]

View File

@ -4590,6 +4590,9 @@ nsLayoutUtils::IsContainerForFontSizeInflation(const nsIFrame *aFrame)
* them, so they and their anonymous content should also not be a
* container.
*
* However, because we can't reliably compute sizes across XUL during
* reflow, any XUL frame with a XUL parent is always a container.
*
* There are contexts where it would be nice if some blocks didn't
* count as a container, so that, for example, an indented quotation
* didn't end up with a smaller font size. However, it's hard to
@ -4597,9 +4600,12 @@ nsLayoutUtils::IsContainerForFontSizeInflation(const nsIFrame *aFrame)
* thing to count as a container, so we don't try, and blocks are
* always containers.
*/
bool isInline = aFrame->GetStyleDisplay()->mDisplay ==
NS_STYLE_DISPLAY_INLINE ||
aFrame->GetContent()->IsInNativeAnonymousSubtree();
bool isInline = (aFrame->GetStyleDisplay()->mDisplay ==
NS_STYLE_DISPLAY_INLINE ||
(aFrame->GetContent() &&
aFrame->GetContent()->IsInNativeAnonymousSubtree())) &&
!(aFrame->IsBoxFrame() && aFrame->GetParent() &&
aFrame->GetParent()->IsBoxFrame());
NS_ASSERTION(!aFrame->IsFrameOfType(nsIFrame::eLineParticipant) || isInline,
"line participants must not be containers");
NS_ASSERTION(aFrame->GetType() != nsGkAtoms::bulletFrame || isInline,
@ -4628,10 +4634,26 @@ nsLayoutUtils::InflationMinFontSizeFor(const nsHTMLReflowState &aReflowState)
#ifdef DEBUG
{
const nsHTMLReflowState *rs = &aReflowState;
const nsIFrame *f = aReflowState.frame;
nsIFrame *f = aReflowState.frame;
for (; rs; rs = rs->parentReflowState, f = f->GetParent()) {
NS_ABORT_IF_FALSE(rs->frame == f,
"reflow state parentage must match frame parentage");
nsIScrollableFrame *sf;
NS_ABORT_IF_FALSE(rs->parentReflowState ||
IsContainerForFontSizeInflation(f) ||
// OK if NS_FRAME_IN_REFLOW is not set on
// (non-null) parent, since its ancestors have a
// real size. (Do we set NS_FRAME_IN_REFLOW
// correctly for xul?)
!(f->GetParent()->GetStateBits() &
NS_FRAME_IN_REFLOW) ||
// ugly exception, but ok because the
// child is a container
(f->GetType() == nsGkAtoms::scrollFrame &&
(sf = do_QueryFrame(f)) &&
(IsContainerForFontSizeInflation(
sf->GetScrolledFrame()))),
"must hit container at top of reflow state chain");
}
}
#endif

View File

@ -5818,7 +5818,28 @@ PresShell::HandleEvent(nsIFrame *aFrame,
return NS_OK;
if (presShell != this) {
return presShell->HandleEvent(presShell->GetRootFrame(), aEvent, true, aEventStatus);
nsIFrame* frame = presShell->GetRootFrame();
if (!frame) {
if (aEvent->message == NS_QUERY_TEXT_CONTENT ||
NS_IS_CONTENT_COMMAND_EVENT(aEvent)) {
return NS_OK;
}
nsIView* view = presShell->GetViewManager()->GetRootView();
while (view && !view->GetFrame()) {
view = view->GetParent();
}
if (view) {
frame = view->GetFrame();
}
}
if (!frame)
return NS_OK;
nsCOMPtr<nsIPresShell> shell = frame->PresContext()->GetPresShell();
return shell->HandleEvent(frame, aEvent, true, aEventStatus);
}
}
}

View File

@ -381,6 +381,7 @@ _BROWSER_FILES = \
_INFLATION_REFTEST_FILES = \
$(shell find $(srcdir)/font-inflation/ -name '*.html' -o -name '*.xhtml') \
$(srcdir)/../../reftests/webm-video/black140x100.webm \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,2 @@
<!DOCTYPE HTML>
<video src="black140x100.webm"></video>

View File

@ -46,6 +46,7 @@ var gTests = [
"== css-transform-1.html css-transform-1-ref.html",
"== css-transform-2.html css-transform-2-ref.html",
"== container-with-clamping.html container-with-clamping-ref.html",
"!= video-1.html about:blank", // crashtest
];
// Maintain a reference count of how many things we're waiting for until

View File

@ -71,11 +71,11 @@ private:
nsRect mRects[2];
public:
nsRect& Overflow(size_t aIndex) {
NS_ASSERTION(0 <= aIndex && aIndex < 2, "index out of range");
NS_ASSERTION(aIndex < 2, "index out of range");
return mRects[aIndex];
}
const nsRect& Overflow(size_t aIndex) const {
NS_ASSERTION(0 <= aIndex && aIndex < 2, "index out of range");
NS_ASSERTION(aIndex < 2, "index out of range");
return mRects[aIndex];
}

View File

@ -0,0 +1,12 @@
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
div {
}
</style>
</head>
<body>
<div>Hello world 123</div>
</body>
</html>

View File

@ -0,0 +1,17 @@
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
@font-face {
font-family: foo;
src: url(../fonts/DejaVuSansMono.woff);
}
div {
font-family: foo;
}
</style>
</head>
<body>
<div>Hello world 123</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
div {
font-family: sans-serif;
}
</style>
</head>
<body>
<div>Hello world 123</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
div {
font-family: serif;
}
</style>
</head>
<body>
<div>Hello world 123</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
div {
font-size: 16px;
}
</style>
</head>
<body>
<div>Hello world 123</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
div {
font-size: 24px;
}
</style>
</head>
<body>
<div>Hello world 123</div>
</body>
</html>

View File

@ -106,3 +106,26 @@ require-or(unrecognizedCondition&&true,skip) script scripttest-fail.html
require-or(unrecognizedCondition,fails) script scripttest-fail.html
require-or(true,fails) script scripttest-pass.html
require-or(true&&true,fails) script scripttest-pass.html
# tests for pref(...) syntax in manifest, including "fails" examples with incorrect prefs
# a boolean pref
pref(gfx.downloadable_fonts.enabled,true) HTTP(..) != font-download.html font-default.html
pref(gfx.downloadable_fonts.enabled,false) HTTP(..) == font-download.html font-default.html
fails pref(gfx.downloadable_fonts.enabled,0) HTTP(..) == font-download.html font-default.html
fails pref(gfx.downloadable_fonts.enabled,"foo") HTTP(..) == font-download.html font-default.html
# a non-existent pref
fails pref(not.a.real.pref.name,1) == font-download.html font-default.html
# an integer pref
pref(font.size.variable.x-western,16) == font-size-16.html font-default.html
pref(font.size.variable.x-western,16) != font-size-24.html font-default.html
pref(font.size.variable.x-western,24) == font-size-24.html font-default.html
pref(font.size.variable.x-western,24) != font-size-16.html font-default.html
fails pref(font.size.variable.x-western,false) == font-size-16.html font-default.html
fails pref(font.size.variable.x-western,"foo") == font-size-16.html font-default.html
# a string pref
pref(font.default.x-western,"serif") == font-serif.html font-default.html
pref(font.default.x-western,"serif") != font-sans-serif.html font-default.html
pref(font.default.x-western,"sans-serif") == font-sans-serif.html font-default.html
pref(font.default.x-western,"sans-serif") != font-serif.html font-default.html
fails pref(font.default.x-western,true) == font-serif.html font-default.html
fails pref(font.default.x-western,0) == font-serif.html font-default.html

View File

@ -52,7 +52,7 @@ must be one of the following:
2. A test item
<failure-type>* [<http>] <type> <url> <url_ref>
<failure-type>* <preference>* [<http>] <type> <url> <url_ref>
where
@ -146,7 +146,22 @@ must be one of the following:
fails-if(winWidget) == test reference
asserts-if(cocoaWidget,2) load crashtest
b. <http>, if present, is one of the strings (sans quotes) "HTTP" or
b. <pref-setting> (optional) is a string of the form
pref(<name>,<value>)
where <name> is the name of a preference setting, as seen in
about:config, and <value> is the value to which this preference should
be set. <value> may be a boolean (true/false), an integer, or a
quoted string *without spaces*, according to the type of the preference.
The preference will be set to the specified value prior to rendering
the test and reference canvases, and will be restored afterwards so
that following tests are not affected. Note that this feature is only
useful for "live" preferences that take effect immediately, without
requiring a browser restart.
c. <http>, if present, is one of the strings (sans quotes) "HTTP" or
"HTTP(..)" or "HTTP(../..)" or "HTTP(../../..)", etc. , indicating that
the test should be run over an HTTP server because it requires certain
HTTP headers or a particular HTTP status. (Don't use this if your test
@ -205,7 +220,7 @@ must be one of the following:
on request/response in handleRequest, see the nsIHttpRe(quest|sponse)
definitions in <netwerk/test/httpserver/nsIHttpServer.idl>.
c. <type> is one of the following:
d. <type> is one of the following:
== The test passes if the images of the two renderings are the
SAME.
@ -233,10 +248,10 @@ must be one of the following:
url_ref must be omitted. The test may be marked as fails or
random. (Used to test the JavaScript Engine.)
d. <url> is either a relative file path or an absolute URL for the
e. <url> is either a relative file path or an absolute URL for the
test page
e. <url_ref> is either a relative file path or an absolute URL for
f. <url_ref> is either a relative file path or an absolute URL for
the reference page
The only difference between <url> and <url_ref> is that results of

View File

@ -150,6 +150,13 @@ const EXPECTED_FAIL = 1;
const EXPECTED_RANDOM = 2;
const EXPECTED_DEATH = 3; // test must be skipped to avoid e.g. crash/hang
// types of preference value we might want to set for a specific test
const PREF_BOOLEAN = 0;
const PREF_STRING = 1;
const PREF_INTEGER = 2;
var gPrefsToRestore = [];
const gProtocolRE = /^\w+:/;
var HTTP_SERVER_PORT = 4444;
@ -681,8 +688,9 @@ function ReadManifest(aURL, inherited_status)
var maxAsserts = 0;
var needs_focus = false;
var slow = false;
var prefSettings = [];
while (items[0].match(/^(fails|needs-focus|random|skip|asserts|slow|require-or|silentfail)/)) {
while (items[0].match(/^(fails|needs-focus|random|skip|asserts|slow|require-or|silentfail|pref)/)) {
var item = items.shift();
var stat;
var cond;
@ -744,6 +752,24 @@ function ReadManifest(aURL, inherited_status)
} else if (item == "silentfail") {
cond = false;
allow_silent_fail = true;
} else if ((m = item.match(/^pref\((.+?),(.*)\)$/))) {
cond = false;
var prefName = m[1];
var prefVal = Components.utils.evalInSandbox("(" + m[2] + ")", sandbox);
var prefType;
var valType = typeof(prefVal);
if (valType == "boolean") {
prefType = PREF_BOOLEAN;
} else if (valType == "string") {
prefType = PREF_STRING;
} else if (valType == "number" && (parseInt(prefVal) == prefVal)) {
prefType = PREF_INTEGER;
} else {
throw "Error in pref value in manifest file " + aURL.spec + " line " + lineNo;
}
prefSettings.push( { name: prefName,
type: prefType,
value: prefVal } );
} else {
throw "Error 1 in manifest file " + aURL.spec + " line " + lineNo;
}
@ -822,6 +848,7 @@ function ReadManifest(aURL, inherited_status)
maxAsserts: maxAsserts,
needsFocus: needs_focus,
slow: slow,
prefSettings: prefSettings,
url1: testURI,
url2: null } );
} else if (items[0] == TYPE_SCRIPT) {
@ -844,6 +871,7 @@ function ReadManifest(aURL, inherited_status)
maxAsserts: maxAsserts,
needsFocus: needs_focus,
slow: slow,
prefSettings: prefSettings,
url1: testURI,
url2: null } );
} else if (items[0] == TYPE_REFTEST_EQUAL || items[0] == TYPE_REFTEST_NOTEQUAL) {
@ -869,6 +897,7 @@ function ReadManifest(aURL, inherited_status)
maxAsserts: maxAsserts,
needsFocus: needs_focus,
slow: slow,
prefSettings: prefSettings,
url1: testURI,
url2: refURI } );
} else {
@ -897,7 +926,8 @@ function BuildUseCounts()
var url = gURLs[i];
if (url.expected != EXPECTED_DEATH &&
(url.type == TYPE_REFTEST_EQUAL ||
url.type == TYPE_REFTEST_NOTEQUAL)) {
url.type == TYPE_REFTEST_NOTEQUAL) &&
url.prefSettings.length == 0) {
AddURIUseCount(gURLs[i].url1);
AddURIUseCount(gURLs[i].url2);
}
@ -968,6 +998,8 @@ function StartCurrentTest()
{
gTestLog = [];
RestoreChangedPreferences();
// make sure we don't run tests that are expected to kill the browser
while (gURLs.length > 0) {
var test = gURLs[0];
@ -983,6 +1015,77 @@ function StartCurrentTest()
++gTestResults.Slow;
gDumpLog("REFTEST TEST-KNOWN-SLOW | " + test.url1.spec + " | (SLOW)\n");
gURLs.shift();
} else if (gURLs[0].prefSettings.length > 0) {
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch2);
var badPref = undefined;
try {
gURLs[0].prefSettings.forEach(function(ps) {
var oldVal;
if (ps.type == PREF_BOOLEAN) {
try {
oldVal = prefs.getBoolPref(ps.name);
} catch (e) {
badPref = "boolean preference '" + ps.name + "'";
throw "bad pref";
}
} else if (ps.type == PREF_STRING) {
try {
oldVal = prefs.getCharPref(ps.name);
} catch (e) {
badPref = "string preference '" + ps.name + "'";
throw "bad pref";
}
} else if (ps.type == PREF_INTEGER) {
try {
oldVal = prefs.getIntPref(ps.name);
} catch (e) {
badPref = "integer preference '" + ps.name + "'";
throw "bad pref";
}
} else {
throw "internal error - unknown preference type";
}
if (oldVal != ps.value) {
gPrefsToRestore.push( { name: ps.name,
type: ps.type,
value: oldVal } );
var value = ps.value;
if (ps.type == PREF_BOOLEAN) {
prefs.setBoolPref(ps.name, value);
} else if (ps.type == PREF_STRING) {
prefs.setCharPref(ps.name, value);
value = '"' + value + '"';
} else if (ps.type == PREF_INTEGER) {
prefs.setIntPref(ps.name, value);
}
gDumpLog("SET PREFERENCE pref(" + ps.name + "," + value + ")\n");
}
});
} catch (e) {
if (e == "bad pref") {
if (test.expected == EXPECTED_FAIL) {
gDumpLog("REFTEST TEST-KNOWN-FAIL | " + test.url1.spec +
" | (SKIPPED; " + badPref + " not known or wrong type)\n");
++gTestResults.Skip;
} else {
gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + test.url1.spec +
" | " + badPref + " not known or wrong type\n");
++gTestResults.UnexpectedFail;
}
} else {
throw e;
}
}
if (badPref != undefined) {
// undo anything we changed
RestoreChangedPreferences();
// skip the test that had a bad preference
gURLs.shift();
} else {
break;
}
} else {
break;
}
@ -1004,7 +1107,8 @@ function StartCurrentURI(aState)
gState = aState;
gCurrentURL = gURLs[0]["url" + aState].spec;
if (gURICanvases[gCurrentURL] &&
if (gURLs[0].prefSettings.length == 0 &&
gURICanvases[gCurrentURL] &&
(gURLs[0].type == TYPE_REFTEST_EQUAL ||
gURLs[0].type == TYPE_REFTEST_NOTEQUAL) &&
gURLs[0].maxAsserts == 0) {
@ -1264,7 +1368,8 @@ function RecordResult(testRunTime, errorMsg, scriptResults)
return;
}
if (gURICanvases[gCurrentURL]) {
if (gURLs[0].prefSettings.length == 0 &&
gURICanvases[gCurrentURL]) {
gCurrentCanvas = gURICanvases[gCurrentURL];
}
if (gCurrentCanvas == null) {
@ -1343,8 +1448,10 @@ function RecordResult(testRunTime, errorMsg, scriptResults)
FlushTestLog();
}
UpdateCanvasCache(gURLs[0].url1, gCanvas1);
UpdateCanvasCache(gURLs[0].url2, gCanvas2);
if (gURLs[0].prefSettings.length == 0) {
UpdateCanvasCache(gURLs[0].url1, gCanvas1);
UpdateCanvasCache(gURLs[0].url2, gCanvas2);
}
CleanUpCrashDumpFiles();
FinishTestItem();
@ -1474,6 +1581,27 @@ function ResetRenderingState()
// We would want to clear any viewconfig here, if we add support for it
}
function RestoreChangedPreferences()
{
if (gPrefsToRestore.length > 0) {
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch2);
gPrefsToRestore.forEach(function(ps) {
var value = ps.value;
if (ps.type == PREF_BOOLEAN) {
prefs.setBoolPref(ps.name, value);
} else if (ps.type == PREF_STRING) {
prefs.setCharPref(ps.name, value);
value = '"' + value + '"';
} else if (ps.type == PREF_INTEGER) {
prefs.setIntPref(ps.name, value);
}
gDumpLog("RESTORE PREFERENCE pref(" + ps.name + "," + value + ")\n");
});
gPrefsToRestore = [];
}
}
function RegisterMessageListenersAndLoadContentScript()
{
gBrowserMessageManager.addMessageListener(

View File

@ -154,6 +154,7 @@
@BINPATH@/components/dom_base.xpt
#ifdef MOZ_B2G_RIL
@BINPATH@/components/dom_telephony.xpt
@BINPATH@/components/dom_wifi.xpt
@BINPATH@/components/dom_system_b2g.xpt
#endif
@BINPATH@/components/dom_battery.xpt
@ -398,6 +399,8 @@
@BINPATH@/components/nsTelephonyWorker.js
@BINPATH@/components/Telephony.manifest
@BINPATH@/components/Telephony.js
@BINPATH@/components/nsWifiWorker.js
@BINPATH@/components/nsWifiWorker.manifest
#endif
#ifdef XP_MACOSX
@BINPATH@/components/libalerts_s.dylib

View File

@ -104,10 +104,12 @@ test_asyncNULLFallback()
"SELECT NULL"
), getter_AddRefs(stmt));
nsRefPtr<Spinner> asyncSpin(new Spinner());
nsCOMPtr<mozIStoragePendingStatement> pendingStmt;
do_check_true(NS_SUCCEEDED(stmt->ExecuteAsync(asyncSpin, getter_AddRefs(pendingStmt))));
do_check_true(NS_SUCCEEDED(stmt->ExecuteAsync(nsnull, getter_AddRefs(pendingStmt))));
do_check_true(pendingStmt);
stmt->Finalize();
nsRefPtr<Spinner> asyncSpin(new Spinner());
db->AsyncClose(asyncSpin);
asyncSpin->SpinUntilCompleted();
}

Some files were not shown because too many files have changed in this diff Show More