mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Merge last green PGO build from mozilla-inbound to mozilla-central
This commit is contained in:
commit
532fd7b9d2
@ -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
|
||||
|
@ -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] {
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
81
configure.in
81
configure.in
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -84,7 +84,10 @@ DIRS += \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL #{
|
||||
DIRS += telephony
|
||||
DIRS += \
|
||||
telephony \
|
||||
wifi \
|
||||
$(NULL)
|
||||
endif #}
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -152,6 +152,7 @@ _TEST_FILES = \
|
||||
devicemotion_outer.html \
|
||||
devicemotion_inner.html \
|
||||
test_bug698061.html \
|
||||
test_bug707749.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
34
dom/tests/mochitest/bugs/test_bug707749.html
Normal file
34
dom/tests/mochitest/bugs/test_bug707749.html
Normal 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>
|
||||
|
@ -45,6 +45,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
bug507902-frame.html \
|
||||
test_bug507902.html \
|
||||
$(NULL)
|
||||
|
||||
|
30
dom/tests/mochitest/orientation/bug507902-frame.html
Normal file
30
dom/tests/mochitest/orientation/bug507902-frame.html
Normal 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>
|
||||
|
@ -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
70
dom/wifi/Makefile.in
Normal 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
13
dom/wifi/libcutils.js
Normal 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)
|
||||
};
|
||||
})();
|
36
dom/wifi/libhardware_legacy.js
Normal file
36
dom/wifi/libhardware_legacy.js
Normal 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
30
dom/wifi/libnetutils.js
Normal 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)
|
||||
};
|
||||
})();
|
94
dom/wifi/network_worker.js
Normal file
94
dom/wifi/network_worker.js
Normal 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
42
dom/wifi/nsIWifi.idl
Normal 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
40
dom/wifi/nsWifiWorker.h
Normal 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
853
dom/wifi/nsWifiWorker.js
Normal 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) {};
|
||||
}
|
1
dom/wifi/nsWifiWorker.manifest
Normal file
1
dom/wifi/nsWifiWorker.manifest
Normal file
@ -0,0 +1 @@
|
||||
component {a14e8977-d259-433a-a88d-58dd44657e5b} nsWifiWorker.js
|
@ -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;
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
40
gfx/ycbcr/QuellGccWarnings.patch
Normal file
40
gfx/ycbcr/QuellGccWarnings.patch
Normal 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_
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
298
js/src/jsgc.cpp
298
js/src/jsgc.cpp
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 };
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -486,8 +486,6 @@ private:
|
||||
return callSites[index].inlinepc;
|
||||
}
|
||||
|
||||
bool arrayPrototypeHasIndexedProperty();
|
||||
|
||||
bool activeFrameHasMultipleExits() {
|
||||
ActiveFrame *na = a;
|
||||
while (na->parent) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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_);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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) {}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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++
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
1
js/xpconnect/tests/unit/importer.jsm
Normal file
1
js/xpconnect/tests/unit/importer.jsm
Normal file
@ -0,0 +1 @@
|
||||
Components.utils.import("resource://test/syntax_error.jsm");
|
10
js/xpconnect/tests/unit/test_import_fail.js
Normal file
10
js/xpconnect/tests/unit/test_import_fail.js
Normal 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);
|
||||
}
|
||||
}
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
2
layout/base/tests/font-inflation/video-1.html
Normal file
2
layout/base/tests/font-inflation/video-1.html
Normal file
@ -0,0 +1,2 @@
|
||||
<!DOCTYPE HTML>
|
||||
<video src="black140x100.webm"></video>
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
12
layout/reftests/reftest-sanity/font-default.html
Normal file
12
layout/reftests/reftest-sanity/font-default.html
Normal 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>
|
17
layout/reftests/reftest-sanity/font-download.html
Normal file
17
layout/reftests/reftest-sanity/font-download.html
Normal 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>
|
13
layout/reftests/reftest-sanity/font-sans-serif.html
Normal file
13
layout/reftests/reftest-sanity/font-sans-serif.html
Normal 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>
|
13
layout/reftests/reftest-sanity/font-serif.html
Normal file
13
layout/reftests/reftest-sanity/font-serif.html
Normal 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>
|
13
layout/reftests/reftest-sanity/font-size-16.html
Normal file
13
layout/reftests/reftest-sanity/font-size-16.html
Normal 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>
|
13
layout/reftests/reftest-sanity/font-size-24.html
Normal file
13
layout/reftests/reftest-sanity/font-size-24.html
Normal 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>
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user