mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and mozilla-inbound
This commit is contained in:
commit
442a1b085f
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
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
|
@ -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:
|
||||
|
@ -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
|
||||
|
294
js/src/jsgc.cpp
294
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())
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
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
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -334,7 +334,16 @@ function _execute_test() {
|
||||
// possible that this will mask an NS_ERROR_ABORT that happens after a
|
||||
// do_check failure though.
|
||||
if (!_quit || e != Components.results.NS_ERROR_ABORT) {
|
||||
msg = "TEST-UNEXPECTED-FAIL | (xpcshell/head.js) | " + e;
|
||||
msg = "TEST-UNEXPECTED-FAIL | ";
|
||||
if ('fileName' in e) {
|
||||
msg += e.fileName;
|
||||
if ('lineNumber' in e) {
|
||||
msg += ":" + e.lineNumber;
|
||||
}
|
||||
} else {
|
||||
msg += "xpcshell/head.js";
|
||||
}
|
||||
msg += " | " + e;
|
||||
if (e.stack) {
|
||||
_dump(msg + " - See following stack:\n");
|
||||
_dump_exception_stack(e.stack);
|
||||
|
@ -74,7 +74,7 @@ function run_test()
|
||||
do_check_eq(1180493839859230, stmt.getInt64(3));
|
||||
do_check_eq(1180493839859230, stmt.getInt64(4));
|
||||
do_check_eq(1, stmt.getInt32(5));
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ function run_test()
|
||||
|
||||
// Check that the column exists (statement should not throw)
|
||||
stmt = dbConn.createStatement("SELECT referrer FROM moz_downloads");
|
||||
stmt.finalize();
|
||||
|
||||
// now we check the entries
|
||||
stmt = dbConn.createStatement(
|
||||
@ -70,7 +71,7 @@ function run_test()
|
||||
do_check_eq(1180493839859230, stmt.getInt64(4));
|
||||
do_check_eq(1, stmt.getInt32(5));
|
||||
do_check_true(stmt.getIsNull(6));
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ function run_test()
|
||||
|
||||
// Check that the column exists (statement should not throw)
|
||||
stmt = dbConn.createStatement("SELECT entityID FROM moz_downloads");
|
||||
stmt.finalize();
|
||||
|
||||
// now we check the entries
|
||||
stmt = dbConn.createStatement(
|
||||
@ -72,7 +73,7 @@ function run_test()
|
||||
do_check_eq(1, stmt.getInt32(5));
|
||||
do_check_eq("http://www.mozilla.com/en-US/products/download.html?product=firefox-2.0.0.6&os=osx&lang=en-US",stmt.getUTF8String(6));
|
||||
do_check_true(stmt.getIsNull(7));
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ function run_test()
|
||||
do_check_eq("http://www.mozilla.com/en-US/products/download.html?product=firefox-2.0.0.6&os=osx&lang=en-US",stmt.getUTF8String(6));
|
||||
do_check_true(stmt.getIsNull(7));
|
||||
do_check_true(stmt.getIsNull(8));
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ function run_test()
|
||||
do_check_true(stmt.getIsNull(8));
|
||||
do_check_eq(0, stmt.getInt64(9));
|
||||
do_check_eq(-1, stmt.getInt64(10));
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ do_load_httpd_js();
|
||||
do_get_profile();
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var downloadUtils = { };
|
||||
XPCOMUtils.defineLazyServiceGetter(downloadUtils,
|
||||
@ -188,3 +189,7 @@ XPCOMUtils.defineLazyGetter(this, "Services", function() {
|
||||
|
||||
// Disable alert service notifications
|
||||
Services.prefs.setBoolPref("browser.download.manager.showAlertOnComplete", false);
|
||||
|
||||
do_register_cleanup(function() {
|
||||
Services.obs.notifyObservers(null, "quit-application", null);
|
||||
});
|
||||
|
@ -81,6 +81,7 @@ function add_download_to_db(aStartTimeInRange, aEndTimeInRange, aState)
|
||||
stmt.params.endTime = aEndTimeInRange ? END_TIME - 1 : END_TIME + 1;
|
||||
stmt.params.state = aState;
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
return id++;
|
||||
}
|
||||
@ -108,6 +109,7 @@ function check_existence(aIDs, aExpected)
|
||||
checkFunc(stmt.executeStep());
|
||||
stmt.reset();
|
||||
}
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -137,7 +137,6 @@ FormHistory.prototype = {
|
||||
this.messageManager.addMessageListener("FormHistory:FormSubmitEntries", this);
|
||||
|
||||
// Add observers
|
||||
Services.obs.addObserver(this, "profile-change-teardown", true);
|
||||
Services.obs.addObserver(this, "profile-before-change", true);
|
||||
Services.obs.addObserver(this, "idle-daily", true);
|
||||
Services.obs.addObserver(this, "formhistory-expire-now", true);
|
||||
@ -403,10 +402,7 @@ FormHistory.prototype = {
|
||||
this.expireOldEntries();
|
||||
break;
|
||||
case "profile-before-change":
|
||||
// FIXME (bug 696486): close the connection in here.
|
||||
break;
|
||||
case "profile-change-teardown":
|
||||
this._dbFinalize();
|
||||
this._dbClose();
|
||||
break;
|
||||
default:
|
||||
this.log("Oops! Unexpected notification: " + topic);
|
||||
@ -869,15 +865,22 @@ FormHistory.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* _dbFinalize
|
||||
* _dbClose
|
||||
*
|
||||
* Finalize all statements to allow closing the connection correctly.
|
||||
* Finalize all statements and close the connection.
|
||||
*/
|
||||
_dbFinalize : function FH__dbFinalize() {
|
||||
_dbClose : function FH__dbClose() {
|
||||
for each (let stmt in this.dbStmts) {
|
||||
stmt.finalize();
|
||||
}
|
||||
this.dbStmts = {};
|
||||
if (this.dbConnection !== undefined) {
|
||||
try {
|
||||
this.dbConnection.close();
|
||||
} catch (e) {
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
@ -895,16 +898,7 @@ FormHistory.prototype = {
|
||||
let backupFile = this.dbFile.leafName + ".corrupt";
|
||||
storage.backupDatabaseFile(this.dbFile, backupFile);
|
||||
|
||||
this._dbFinalize();
|
||||
|
||||
if (this.dbConnection !== undefined) {
|
||||
try {
|
||||
this.dbConnection.close();
|
||||
} catch (e) {
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
}
|
||||
|
||||
this._dbClose();
|
||||
this.dbFile.remove(false);
|
||||
}
|
||||
};
|
||||
|
@ -153,6 +153,10 @@ function run_test()
|
||||
do_check_eq(gDownloadLastDir.file.path, dir3.path);
|
||||
|
||||
// cleanup
|
||||
Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService)
|
||||
.notifyObservers(null, "quit-application", null);
|
||||
|
||||
prefsService.clearUserPref("browser.privatebrowsing.keep_current_session");
|
||||
[dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
|
||||
}
|
||||
|
@ -352,11 +352,12 @@ INNER_MAKE_PACKAGE = \
|
||||
$(ZIPALIGN) -f -v 4 $(_ABS_DIST)/gecko.apk $(PACKAGE)
|
||||
INNER_UNMAKE_PACKAGE = \
|
||||
mkdir $(MOZ_PKG_DIR) && \
|
||||
cd $(MOZ_PKG_DIR) && \
|
||||
pushd $(MOZ_PKG_DIR) && \
|
||||
$(UNZIP) $(UNPACKAGE) && \
|
||||
mv lib/$(ABI_DIR)/libmozutils.so . && \
|
||||
mv lib/$(ABI_DIR)/*plugin-container* $(MOZ_CHILD_PROCESS_NAME) && \
|
||||
rm -rf lib/$(ABI_DIR)
|
||||
rm -rf lib/$(ABI_DIR) && \
|
||||
popd
|
||||
endif
|
||||
ifeq ($(MOZ_PKG_FORMAT),DMG)
|
||||
ifndef _APPNAME
|
||||
|
@ -111,7 +111,7 @@ ah_crap_handler(int signum)
|
||||
signum);
|
||||
|
||||
printf("Stack:\n");
|
||||
NS_StackWalk(PrintStackFrame, 2, nsnull);
|
||||
NS_StackWalk(PrintStackFrame, 2, nsnull, 0);
|
||||
|
||||
printf("Sleeping for %d seconds.\n",_gdb_sleep_duration);
|
||||
printf("Type 'gdb %s %d' to attach your debugger to this thread.\n",
|
||||
|
@ -962,7 +962,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort)
|
||||
/* Walk the stack, even if stacks_enabled is false. We do this to
|
||||
check if we must set immediate_abort. */
|
||||
info->entries = 0;
|
||||
rv = NS_StackWalk(stack_callback, skip, info);
|
||||
rv = NS_StackWalk(stack_callback, skip, info, 0);
|
||||
*immediate_abort = rv == NS_ERROR_UNEXPECTED;
|
||||
if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) {
|
||||
t->suppress_tracing--;
|
||||
@ -997,7 +997,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort)
|
||||
/* skip == 0 means |backtrace| should show up, so don't use skip + 1 */
|
||||
/* NB: this call is repeated below if the buffer is too small */
|
||||
info->entries = 0;
|
||||
rv = NS_StackWalk(stack_callback, skip, info);
|
||||
rv = NS_StackWalk(stack_callback, skip, info, 0);
|
||||
*immediate_abort = rv == NS_ERROR_UNEXPECTED;
|
||||
if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) {
|
||||
t->suppress_tracing--;
|
||||
@ -1021,7 +1021,7 @@ backtrace(tm_thread *t, int skip, int *immediate_abort)
|
||||
|
||||
/* and call NS_StackWalk again */
|
||||
info->entries = 0;
|
||||
NS_StackWalk(stack_callback, skip, info);
|
||||
NS_StackWalk(stack_callback, skip, info, 0);
|
||||
|
||||
/* same stack */
|
||||
PR_ASSERT(info->entries * 2 == new_stack_buffer_size);
|
||||
|
@ -133,7 +133,7 @@ my_malloc_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
|
||||
// stack shows up as having two pthread_cond_wait$UNIX2003 frames.
|
||||
const char *name = OnSnowLeopardOrLater() ? "new_sem_from_pool" :
|
||||
"pthread_cond_wait$UNIX2003";
|
||||
NS_StackWalk(stack_callback, 0, const_cast<char*>(name));
|
||||
NS_StackWalk(stack_callback, 0, const_cast<char*>(name), 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -802,7 +802,7 @@ WalkStackThread(void* aData)
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure)
|
||||
void *aClosure, uintptr_t aThread)
|
||||
{
|
||||
MOZ_ASSERT(gCriticalAddress.mInit);
|
||||
HANDLE myProcess, myThread;
|
||||
@ -812,6 +812,13 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
if (!EnsureImageHlpInitialized())
|
||||
return false;
|
||||
|
||||
HANDLE targetThread;
|
||||
if (aThread) {
|
||||
targetThread = reinterpret_cast<HANDLE> (aThread);
|
||||
} else {
|
||||
targetThread = ::GetCurrentThread();
|
||||
}
|
||||
|
||||
// Have to duplicate handle to get a real handle.
|
||||
if (!::DuplicateHandle(::GetCurrentProcess(),
|
||||
::GetCurrentProcess(),
|
||||
@ -822,7 +829,7 @@ NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!::DuplicateHandle(::GetCurrentProcess(),
|
||||
::GetCurrentThread(),
|
||||
targetThread,
|
||||
::GetCurrentProcess(),
|
||||
&myThread,
|
||||
THREAD_ALL_ACCESS, FALSE, 0)) {
|
||||
@ -1481,9 +1488,10 @@ cs_operate(int (*operate_func)(void *, void *), void * usrarg)
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure)
|
||||
void *aClosure, uintptr_t aThread)
|
||||
{
|
||||
MOZ_ASSERT(gCriticalAddress.mInit);
|
||||
MOZ_ASSERT(!aThread);
|
||||
struct my_user_args args;
|
||||
|
||||
if (!initialized)
|
||||
@ -1561,9 +1569,10 @@ extern void *__libc_stack_end; // from ld-linux.so
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure)
|
||||
void *aClosure, uintptr_t aThread)
|
||||
{
|
||||
MOZ_ASSERT(gCriticalAddress.mInit);
|
||||
MOZ_ASSERT(!aThread);
|
||||
// Stack walking code courtesy Kipp's "leaky".
|
||||
|
||||
// Get the frame pointer
|
||||
@ -1639,9 +1648,10 @@ unwind_callback (struct _Unwind_Context *context, void *closure)
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure)
|
||||
void *aClosure, uintptr_t aThread)
|
||||
{
|
||||
MOZ_ASSERT(gCriticalAddress.mInit);
|
||||
MOZ_ASSERT(!aThread);
|
||||
unwind_info info;
|
||||
info.callback = aCallback;
|
||||
info.skip = aSkipFrames + 1;
|
||||
@ -1717,9 +1727,10 @@ NS_FormatCodeAddressDetails(void *aPC, const nsCodeAddressDetails *aDetails,
|
||||
|
||||
EXPORT_XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure)
|
||||
void *aClosure, uintptr_t aThread)
|
||||
{
|
||||
MOZ_ASSERT(gCriticalAddress.mInit);
|
||||
MOZ_ASSERT(!aThread);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
/* WARNING: This file is intended to be included from C or C++ files. */
|
||||
|
||||
#include "nscore.h"
|
||||
#include <mozilla/StdInt.h>
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
|
||||
@ -58,6 +59,10 @@ typedef void
|
||||
* the first callback will be for the caller of
|
||||
* NS_StackWalk.
|
||||
* @param aClosure Caller-supplied data passed through to aCallback.
|
||||
* @param aThread The thread for which the stack is to be retrieved.
|
||||
* Passing null causes us to walk the stack of the
|
||||
* current thread. On Windows, this is a thread HANDLE.
|
||||
* It is currently not supported on any other platform.
|
||||
*
|
||||
* Returns NS_ERROR_NOT_IMPLEMENTED on platforms where it is
|
||||
* unimplemented.
|
||||
@ -70,7 +75,7 @@ typedef void
|
||||
*/
|
||||
XPCOM_API(nsresult)
|
||||
NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
|
||||
void *aClosure);
|
||||
void *aClosure, uintptr_t aThread);
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
|
@ -883,7 +883,7 @@ static void PrintStackFrame(void *aPC, void *aClosure)
|
||||
void
|
||||
nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
|
||||
{
|
||||
NS_StackWalk(PrintStackFrame, 2, aStream);
|
||||
NS_StackWalk(PrintStackFrame, 2, aStream, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user