Merge the last PGO-green inbound changeset to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-11-20 21:43:34 -05:00
commit 6f9e3aa729
218 changed files with 8285 additions and 1791 deletions

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsAccDocManager.h"
#include "DocManager.h"
#include "Accessible-inl.h"
#include "ApplicationAccessible.h"
@ -33,14 +33,14 @@
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager
// DocManager
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager public
// DocManager public
DocAccessible*
nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
DocManager::GetDocAccessible(nsIDocument* aDocument)
{
if (!aDocument)
return nullptr;
@ -56,7 +56,7 @@ nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
}
Accessible*
nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
DocManager::FindAccessibleInCache(nsINode* aNode) const
{
nsSearchAccessibleInCacheArg arg;
arg.mNode = aNode;
@ -69,7 +69,7 @@ nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
#ifdef DEBUG
bool
nsAccDocManager::IsProcessingRefreshDriverNotification() const
DocManager::IsProcessingRefreshDriverNotification() const
{
bool isDocRefreshing = false;
mDocAccessibleCache.EnumerateRead(SearchIfDocIsRefreshing,
@ -81,10 +81,10 @@ nsAccDocManager::IsProcessingRefreshDriverNotification() const
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager protected
// DocManager protected
bool
nsAccDocManager::Init()
DocManager::Init()
{
mDocAccessibleCache.Init(4);
@ -101,7 +101,7 @@ nsAccDocManager::Init()
}
void
nsAccDocManager::Shutdown()
DocManager::Shutdown()
{
nsCOMPtr<nsIWebProgress> progress =
do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
@ -115,7 +115,7 @@ nsAccDocManager::Shutdown()
////////////////////////////////////////////////////////////////////////////////
// nsISupports
NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager,
NS_IMPL_THREADSAFE_ISUPPORTS3(DocManager,
nsIWebProgressListener,
nsIDOMEventListener,
nsISupportsWeakReference)
@ -124,9 +124,9 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsAccDocManager,
// nsIWebProgressListener
NS_IMETHODIMP
nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, uint32_t aStateFlags,
nsresult aStatus)
DocManager::OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, uint32_t aStateFlags,
nsresult aStatus)
{
NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
@ -203,39 +203,39 @@ nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress,
}
NS_IMETHODIMP
nsAccDocManager::OnProgressChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
DocManager::OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsAccDocManager::OnLocationChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsIURI *aLocation,
uint32_t aFlags)
DocManager::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, nsIURI* aLocation,
uint32_t aFlags)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsAccDocManager::OnStatusChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsresult aStatus,
const PRUnichar *aMessage)
DocManager::OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, nsresult aStatus,
const PRUnichar* aMessage)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
nsAccDocManager::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
uint32_t aState)
DocManager::OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aState)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
@ -245,7 +245,7 @@ nsAccDocManager::OnSecurityChange(nsIWebProgress *aWebProgress,
// nsIDOMEventListener
NS_IMETHODIMP
nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent)
DocManager::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString type;
aEvent->GetType(type);
@ -303,11 +303,11 @@ nsAccDocManager::HandleEvent(nsIDOMEvent *aEvent)
}
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager private
// DocManager private
void
nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
uint32_t aLoadEventType)
DocManager::HandleDOMDocumentLoad(nsIDocument* aDocument,
uint32_t aLoadEventType)
{
// Document accessible can be created before we were notified the DOM document
// was loaded completely. However if it's not created yet then create it.
@ -322,8 +322,8 @@ nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
}
void
nsAccDocManager::AddListeners(nsIDocument *aDocument,
bool aAddDOMContentLoadedListener)
DocManager::AddListeners(nsIDocument* aDocument,
bool aAddDOMContentLoadedListener)
{
nsPIDOMWindow *window = aDocument->GetWindow();
nsIDOMEventTarget *target = window->GetChromeEventHandler();
@ -347,7 +347,7 @@ nsAccDocManager::AddListeners(nsIDocument *aDocument,
}
DocAccessible*
nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
{
// Ignore temporary, hiding, resource documents and documents without
// docshell.
@ -419,12 +419,12 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
}
////////////////////////////////////////////////////////////////////////////////
// nsAccDocManager static
// DocManager static
PLDHashOperator
nsAccDocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
DocAccessible* aDocAccessible,
void* aUserArg)
DocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
DocAccessible* aDocAccessible,
void* aUserArg)
{
NS_ASSERTION(aDocAccessible,
"No doc accessible for the object in doc accessible cache!");
@ -434,7 +434,7 @@ nsAccDocManager::GetFirstEntryInDocCache(const nsIDocument* aKey,
}
void
nsAccDocManager::ClearDocCache()
DocManager::ClearDocCache()
{
DocAccessible* docAcc = nullptr;
while (mDocAccessibleCache.EnumerateRead(GetFirstEntryInDocCache, static_cast<void*>(&docAcc))) {
@ -444,9 +444,9 @@ nsAccDocManager::ClearDocCache()
}
PLDHashOperator
nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
DocAccessible* aDocAccessible,
void* aUserArg)
DocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
DocAccessible* aDocAccessible,
void* aUserArg)
{
NS_ASSERTION(aDocAccessible,
"No doc accessible for the object in doc accessible cache!");
@ -464,9 +464,9 @@ nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
#ifdef DEBUG
PLDHashOperator
nsAccDocManager::SearchIfDocIsRefreshing(const nsIDocument* aKey,
DocAccessible* aDocAccessible,
void* aUserArg)
DocManager::SearchIfDocIsRefreshing(const nsIDocument* aKey,
DocAccessible* aDocAccessible,
void* aUserArg)
{
NS_ASSERTION(aDocAccessible,
"No doc accessible for the object in doc accessible cache!");

View File

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsAccDocManager_h_
#define nsAccDocManager_h_
#ifndef mozilla_a11_DocManager_h_
#define mozilla_a11_DocManager_h_
#include "nsIDocument.h"
#include "nsIDOMEventListener.h"
@ -19,21 +19,15 @@ namespace a11y {
class Accessible;
class DocAccessible;
} // namespace a11y
} // namespace mozilla
/**
* Manage the document accessible life cycle.
*/
class nsAccDocManager : public nsIWebProgressListener,
public nsIDOMEventListener,
public nsSupportsWeakReference
class DocManager : public nsIWebProgressListener,
public nsIDOMEventListener,
public nsSupportsWeakReference
{
public:
typedef mozilla::a11y::Accessible Accessible;
typedef mozilla::a11y::DocAccessible DocAccessible;
virtual ~nsAccDocManager() { }
virtual ~DocManager() { }
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBPROGRESSLISTENER
@ -86,7 +80,7 @@ public:
#endif
protected:
nsAccDocManager() { }
DocManager() { }
/**
* Initialize the manager.
@ -99,8 +93,8 @@ protected:
void Shutdown();
private:
nsAccDocManager(const nsAccDocManager&);
nsAccDocManager& operator =(const nsAccDocManager&);
DocManager(const DocManager&);
DocManager& operator =(const DocManager&);
private:
/**
@ -160,4 +154,7 @@ private:
DocAccessibleHashtable mDocAccessibleCache;
};
#endif // nsAccDocManager_h_
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11_DocManager_h_

View File

@ -21,9 +21,9 @@ CPPSRCS = \
AccIterator.cpp \
Filters.cpp \
ARIAStateMap.cpp \
DocManager.cpp \
FocusManager.cpp \
NotificationController.cpp \
nsAccDocManager.cpp \
nsAccessNode.cpp \
nsARIAMap.cpp \
nsCoreUtils.cpp \
@ -48,7 +48,6 @@ endif
EXPORTS = \
AccEvent.h \
nsAccDocManager.h \
nsAccessibilityService.h \
nsAccessNode.h \
$(NULL)
@ -56,6 +55,7 @@ EXPORTS = \
EXPORTS_NAMESPACES = mozilla/a11y
EXPORTS_mozilla/a11y = \
DocManager.h \
FocusManager.h \
AccTypes.h \
States.h \

View File

@ -125,7 +125,7 @@ ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
bool nsAccessibilityService::gIsShutdown = true;
nsAccessibilityService::nsAccessibilityService() :
nsAccDocManager(), FocusManager()
DocManager(), FocusManager()
{
}
@ -139,7 +139,7 @@ nsAccessibilityService::~nsAccessibilityService()
// nsISupports
NS_IMPL_ISUPPORTS_INHERITED3(nsAccessibilityService,
nsAccDocManager,
DocManager,
nsIAccessibilityService,
nsIAccessibleRetrieval,
nsIObserver)
@ -621,7 +621,7 @@ nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
// caches. If we don't find it, and the given node is itself a document, check
// our cache of document accessibles (document cache). Note usually shutdown
// document accessibles are not stored in the document cache, however an
// "unofficially" shutdown document (i.e. not from nsAccDocManager) can still
// "unofficially" shutdown document (i.e. not from DocManager) can still
// exist in the document cache.
Accessible* accessible = FindAccessibleInCache(node);
if (!accessible) {
@ -975,7 +975,7 @@ bool
nsAccessibilityService::Init()
{
// Initialize accessible document manager.
if (!nsAccDocManager::Init())
if (!DocManager::Init())
return false;
// Add observers.
@ -1026,7 +1026,7 @@ nsAccessibilityService::Shutdown()
}
// Stop accessible document loader.
nsAccDocManager::Shutdown();
DocManager::Shutdown();
// Application is going to be closed, shutdown accessibility and mark
// accessibility service as shutdown to prevent calls of its methods.

View File

@ -8,8 +8,7 @@
#include "nsIAccessibilityService.h"
#include "nsAccDocManager.h"
#include "mozilla/a11y/DocManager.h"
#include "mozilla/a11y/FocusManager.h"
#include "nsIObserver.h"
@ -64,12 +63,15 @@ bool ShouldA11yBeEnabled();
} // namespace a11y
} // namespace mozilla
class nsAccessibilityService : public nsAccDocManager,
class nsAccessibilityService : public mozilla::a11y::DocManager,
public mozilla::a11y::FocusManager,
public nsIAccessibilityService,
public nsIObserver
{
public:
typedef mozilla::a11y::Accessible Accessible;
typedef mozilla::a11y::DocAccessible DocAccessible;
virtual ~nsAccessibilityService();
NS_DECL_ISUPPORTS_INHERITED

View File

@ -96,7 +96,7 @@ DocAccessible::
if (!mDocument)
return;
// nsAccDocManager creates document accessible when scrollable frame is
// DocManager creates document accessible when scrollable frame is
// available already, it should be safe time to add scroll listener.
AddScrollListener();

View File

@ -24,7 +24,6 @@
#include "nsIWeakReference.h"
#include "nsIDocShellTreeNode.h"
class nsAccDocManager;
class nsAccessiblePivot;
class nsIScrollableView;
@ -34,6 +33,7 @@ const uint32_t kDefaultCacheSize = 256;
namespace mozilla {
namespace a11y {
class DocManager;
class NotificationController;
class RelatedAccIterator;
template<class Class, class Arg>
@ -319,7 +319,7 @@ protected:
void NotifyOfLoad(uint32_t aLoadEventType);
void NotifyOfLoading(bool aIsReloading);
friend class ::nsAccDocManager;
friend class DocManager;
/**
* Perform initial update (create accessible tree).

View File

@ -135,13 +135,13 @@ OuterDocAccessible::Shutdown()
void
OuterDocAccessible::InvalidateChildren()
{
// Do not invalidate children because nsAccDocManager is responsible for
// Do not invalidate children because DocManager is responsible for
// document accessible lifetime when DOM document is created or destroyed. If
// DOM document isn't destroyed but its presshell is destroyed (for example,
// when DOM node of outerdoc accessible is hidden), then outerdoc accessible
// notifies nsAccDocManager about this. If presshell is created for existing
// notifies DocManager about this. If presshell is created for existing
// DOM document (for example when DOM node of outerdoc accessible is shown)
// then allow nsAccDocManager to handle this case since the document
// then allow DocManager to handle this case since the document
// accessible is created and appended as a child when it's requested.
SetChildrenFlag(eChildrenUninitialized);

View File

@ -50,10 +50,7 @@ var gSimpleTraversalRoles =
Ci.nsIAccessibleRole.ROLE_LINK,
Ci.nsIAccessibleRole.ROLE_PAGETAB,
Ci.nsIAccessibleRole.ROLE_GRAPHIC,
// XXX: Find a better solution for ROLE_STATICTEXT.
// It allows to filter list bullets but at the same time it
// filters CSS generated content too as an unwanted side effect.
// Ci.nsIAccessibleRole.ROLE_STATICTEXT,
Ci.nsIAccessibleRole.ROLE_STATICTEXT,
Ci.nsIAccessibleRole.ROLE_TEXT_LEAF,
Ci.nsIAccessibleRole.ROLE_PUSHBUTTON,
Ci.nsIAccessibleRole.ROLE_CHECKBUTTON,
@ -95,6 +92,16 @@ this.TraversalRules = {
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
else
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
case Ci.nsIAccessibleRole.ROLE_STATICTEXT:
{
let parent = aAccessible.parent;
// Ignore prefix static text in list items. They are typically bullets or numbers.
if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
parent.role == Ci.nsIAccessibleRole.ROLE_LISTITEM)
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
}
default:
// Ignore the subtree, if there is one. So that we don't land on
// the same content that was already presented by its parent.

View File

@ -584,6 +584,9 @@ pref("network.activity.blipIntervalMilliseconds", 250);
pref("jsloader.reuseGlobal", true);
// Enable font inflation for browser tab content.
pref("font.size.inflation.minTwips", 120);
// Enable freeing dirty pages when minimizing memory; this reduces memory
// consumption when applications are sent to the background.
pref("memory.free_dirty_pages", true);

View File

@ -1,6 +1,6 @@
[
{
"clang_version": "r167750"
"clang_version": "r168304"
},
{
"size": 47,
@ -9,8 +9,8 @@
"filename": "setup.sh"
},
{
"size": 56161789,
"digest": "43a35be63f9ea1c73a1b22532b5484b131f0c25bdb6a2f39e31c968b6c3477f6640450cc8dab8e17df80f20e367b8cbc0a74986a4eefd7ac9b9adf2b0859e55e",
"size": 56144782,
"digest": "7e7dd6775d71d074cced8407fac82dc5e161a9034927bd059c84fc06da161da39d32bbd95ac9b6efdf550370fa351361bc476f0b327387dc8d503dc446a776d6",
"algorithm": "sha512",
"filename": "clang.tar.bz2"
}

View File

@ -18,6 +18,8 @@ MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
MOZ_SAFE_BROWSING=
MOZ_SERVICES_COMMON=1
MOZ_SERVICES_HEALTHREPORT=1
MOZ_SERVICES_METRICS=1
MOZ_WEBSMS_BACKEND=1
MOZ_DISABLE_DOMCRYPTO=1

View File

@ -483,6 +483,10 @@
@BINPATH@/components/WeaveCrypto.manifest
@BINPATH@/components/WeaveCrypto.js
#endif
#ifdef MOZ_SERVICES_HEALTHREPORT
@BINPATH@/components/HealthReportComponents.manifest
@BINPATH@/components/HealthReportService.js
#endif
@BINPATH@/components/TelemetryPing.js
@BINPATH@/components/TelemetryPing.manifest
@BINPATH@/components/Webapps.js
@ -574,6 +578,9 @@
#ifdef MOZ_SERVICES_SYNC
@BINPATH@/@PREF_DIR@/services-sync.js
#endif
#ifdef MOZ_SERVICES_HEALTHREPORT
@BINPATH@/@PREF_DIR@/healthreport-prefs.js
#endif
@BINPATH@/greprefs.js
@BINPATH@/defaults/autoconfig/platform.js
@BINPATH@/defaults/autoconfig/prefcalls.js

View File

@ -3536,15 +3536,18 @@ function OpenBrowserWindow(options)
var wintype = document.documentElement.getAttribute('windowtype');
var extraFeatures = "";
var forcePrivate = false;
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
if (typeof options == "object" &&
"private" in options &&
options.private) {
forcePrivate = typeof options == "object" && "private" in options && options.private;
#else
forcePrivate = gPrivateBrowsingUI.privateBrowsingEnabled;
#endif
if (forcePrivate) {
extraFeatures = ",private";
// Force the new window to load about:privatebrowsing instead of the default home page
defaultArgs = "about:privatebrowsing";
}
#endif
// if and only if the current window is a browser window and it has a document with a character
// set, then extract the current charset menu setting from the current document and use it to

View File

@ -25,11 +25,15 @@ MOCHITEST_BROWSER_FILES = \
browser_privatebrowsing_geoprompt_page.html \
browser_privatebrowsing_lastpbcontextexited.js \
browser_privatebrowsing_localStorage.js \
browser_privatebrowsing_localStorage_before_after.js \
browser_privatebrowsing_localStorage_before_after_page.html \
browser_privatebrowsing_localStorage_before_after_page2.html \
browser_privatebrowsing_localStorage_page1.html \
browser_privatebrowsing_localStorage_page2.html \
browser_privatebrowsing_opendir.js \
browser_privatebrowsing_openlocation.js \
browser_privatebrowsing_openLocationLastURL.js \
browser_privatebrowsing_placestitle.js \
browser_privatebrowsing_popupblocker.js \
browser_privatebrowsing_protocolhandler.js \
browser_privatebrowsing_protocolhandler_page.html \
@ -39,6 +43,7 @@ MOCHITEST_BROWSER_FILES = \
browser_privatebrowsing_windowtitle_page.html \
browser_privatebrowsing_zoomrestore.js \
popup.html \
title.sjs \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,66 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// Ensure that a storage instance used by both private and public sessions at different times does not
// allow any data to leak due to cached values.
// Step 1: Load browser_privatebrowsing_localStorage_before_after_page.html in a private tab, causing a storage
// item to exist. Close the tab.
// Step 2: Load the same page in a non-private tab, ensuring that the storage instance reports only one item
// existing.
function test() {
// initialization
waitForExplicitFinish();
let windowsToClose = [];
let testURI = "about:blank";
let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/perwindow/';
function doTest(aIsPrivateMode, aWindow, aCallback) {
aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
if (aIsPrivateMode) {
// do something when aIsPrivateMode is true
is(aWindow.gBrowser.contentWindow.document.title, '1', "localStorage should contain 1 item");
} else {
// do something when aIsPrivateMode is false
is(aWindow.gBrowser.contentWindow.document.title, 'null|0', 'localStorage should contain 0 items');
}
aCallback();
}, true);
aWindow.gBrowser.selectedBrowser.loadURI(testURI);
}
function testOnWindow(aOptions, aCallback) {
whenNewWindowLoaded(aOptions, function(aWin) {
windowsToClose.push(aWin);
// execute should only be called when need, like when you are opening
// web pages on the test. If calling executeSoon() is not necesary, then
// call whenNewWindowLoaded() instead of testOnWindow() on your test.
executeSoon(function() aCallback(aWin));
});
};
// this function is called after calling finish() on the test.
registerCleanupFunction(function() {
windowsToClose.forEach(function(aWin) {
aWin.close();
});
});
// test first when on private mode
testOnWindow({private: true}, function(aWin) {
testURI = prefix + 'browser_privatebrowsing_localStorage_before_after_page.html';
doTest(true, aWin, function() {
// then test when not on private mode
testOnWindow({}, function(aWin) {
testURI = prefix + 'browser_privatebrowsing_localStorage_before_after_page2.html';
doTest(false, aWin, finish);
});
});
});
}

View File

@ -0,0 +1,11 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
localStorage.clear();
localStorage.setItem('zzztest', 'zzzvalue');
document.title = localStorage.length;
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
document.title = localStorage.getItem('zzztest', 'zzzvalue') + '|' + localStorage.length;
localStorage.clear();
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,109 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This test makes sure that the title of existing history entries does not
// change inside a private window.
function test() {
waitForExplicitFinish();
const TEST_URL = "http://mochi.test:8888/browser/browser/components/" +
"privatebrowsing/test/browser/perwindow/title.sjs";
let cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
function waitForCleanup(aCallback) {
// delete all cookies
cm.removeAll();
// delete all history items
Services.obs.addObserver(function observeCH(aSubject, aTopic, aData) {
Services.obs.removeObserver(observeCH, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
aCallback();
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
PlacesUtils.bhistory.removeAllPages();
}
let testNumber = 0;
let historyObserver = {
onTitleChanged: function(aURI, aPageTitle) {
if (aURI.spec != TEST_URL)
return;
switch (++testNumber) {
case 1:
// The first time that the page is loaded
is(aPageTitle, "No Cookie",
"The page should be loaded without any cookie for the first time");
openTestPage(selectedWin);
break;
case 2:
// The second time that the page is loaded
is(aPageTitle, "Cookie",
"The page should be loaded with a cookie for the second time");
waitForCleanup(function () {
openTestPage(selectedWin);
});
break;
case 3:
// After clean up
is(aPageTitle, "No Cookie",
"The page should be loaded without any cookie again");
testOnWindow(true, function(win) {
whenPageLoad(win, function() {
waitForCleanup(finish);
});
});
break;
default:
// Checks that opening the page in a private window should not fire a
// title change.
ok(false, "Title changed. Unexpected pass: " + testNumber);
}
},
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onVisit: function () {},
onBeforeDeleteURI: function () {},
onDeleteURI: function () {},
onClearHistory: function () {},
onPageChanged: function () {},
onDeleteVisits: function() {},
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
};
PlacesUtils.history.addObserver(historyObserver, false);
let selectedWin = null;
let windowsToClose = [];
registerCleanupFunction(function() {
PlacesUtils.history.removeObserver(historyObserver);
windowsToClose.forEach(function(win) {
win.close();
});
});
function openTestPage(aWin) {
aWin.gBrowser.selectedTab = aWin.gBrowser.addTab(TEST_URL);
}
function whenPageLoad(aWin, aCallback) {
aWin.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
aWin.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
aCallback();
}, true);
aWin.gBrowser.selectedBrowser.loadURI(TEST_URL);
}
function testOnWindow(aPrivate, aCallback) {
whenNewWindowLoaded({ private: aPrivate }, function(win) {
selectedWin = win;
windowsToClose.push(win);
executeSoon(function() { aCallback(win) });
});
}
waitForCleanup(function() {
testOnWindow(false, function(win) {
openTestPage(win);
});
});
}

View File

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This provides the tests with a page with different titles based on whether
// a cookie is present or not.
function handleRequest(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/html", false);
var cookie = "name=value";
var title = "No Cookie";
if (request.hasHeader("Cookie") && request.getHeader("Cookie") == cookie)
title = "Cookie";
else
response.setHeader("Set-Cookie", cookie, false);
response.write("<html><head><title>");
response.write(title);
response.write("</title><body>test page</body></html>");
}

View File

@ -1,6 +1,6 @@
[
{
"clang_version": "r167750"
"clang_version": "r168304"
},
{
"size": 47,
@ -9,8 +9,8 @@
"filename": "setup.sh"
},
{
"size": 62553019,
"digest": "31dd1ef281d0508bda0c470a29f244f062f42a4c521664dd1833f0f760c4d0cc0a222a8ba23063ad4cf50b678c2ee057519bd480e4a4f6804c3c7fb40f841a92",
"size": 62536221,
"digest": "a8381234d896ba2eeeef287b948f9d8ffc73bf4d4608ce74002eb666f1ac06d00047fd09b1b8f241c7160561b5dc7a40faf7f8bec94bb7939b9b77ba76af5967",
"algorithm": "sha512",
"filename": "clang.tar.bz2"
}

View File

@ -1,6 +1,6 @@
[
{
"clang_version": "r167750"
"clang_version": "r168304"
},
{
"size": 47,
@ -9,8 +9,8 @@
"filename": "setup.sh"
},
{
"size": 62858526,
"digest": "3c8280e001420eea4c352b05dfffda317ecb9c3be1eb23bda5cb16efebd4fe1b38f752b644acf33c6d34858ae01aa026cbb4c6f319fd6ee8d372517922063ad8",
"size": 62877504,
"digest": "837884b29c176e652b81e9cdaaeda34cf0bf41b7fe17a7f84ed30269ad7daedc9d72ba0d188b8f1551456f307f2dd72583daf99539e62403c0f2b5a83735658e",
"algorithm": "sha512",
"filename": "clang.tar.bz2"
}

View File

@ -1,6 +1,6 @@
[
{
"clang_version": "r167750"
"clang_version": "r168304"
},
{
"size": 47,
@ -9,8 +9,8 @@
"filename": "setup.sh"
},
{
"size": 56161789,
"digest": "43a35be63f9ea1c73a1b22532b5484b131f0c25bdb6a2f39e31c968b6c3477f6640450cc8dab8e17df80f20e367b8cbc0a74986a4eefd7ac9b9adf2b0859e55e",
"size": 56144782,
"digest": "7e7dd6775d71d074cced8407fac82dc5e161a9034927bd059c84fc06da161da39d32bbd95ac9b6efdf550370fa351361bc476f0b327387dc8d503dc446a776d6",
"algorithm": "sha512",
"filename": "clang.tar.bz2"
}

View File

@ -1,6 +1,6 @@
[
{
"clang_version": "r167750"
"clang_version": "r168304"
},
{
"size": 47,
@ -9,8 +9,8 @@
"filename": "setup.sh"
},
{
"size": 56161789,
"digest": "43a35be63f9ea1c73a1b22532b5484b131f0c25bdb6a2f39e31c968b6c3477f6640450cc8dab8e17df80f20e367b8cbc0a74986a4eefd7ac9b9adf2b0859e55e",
"size": 56144782,
"digest": "7e7dd6775d71d074cced8407fac82dc5e161a9034927bd059c84fc06da161da39d32bbd95ac9b6efdf550370fa351361bc476f0b327387dc8d503dc446a776d6",
"algorithm": "sha512",
"filename": "clang.tar.bz2"
}

View File

@ -21,6 +21,7 @@ MOZ_SAFE_BROWSING=1
MOZ_SERVICES_AITC=1
MOZ_SERVICES_COMMON=1
MOZ_SERVICES_CRYPTO=1
MOZ_SERVICES_METRICS=1
MOZ_SERVICES_NOTIFICATIONS=1
MOZ_SERVICES_SYNC=1
MOZ_APP_VERSION=$FIREFOX_VERSION

View File

@ -463,6 +463,10 @@
@BINPATH@/components/AitcComponents.manifest
@BINPATH@/components/Aitc.js
#endif
#ifdef MOZ_SERVICES_HEALTHREPORT
@BINPATH@/components/HealthReportComponents.manifest
@BINPATH@/components/HealthReportService.js
#endif
#ifdef MOZ_SERVICES_NOTIFICATIONS
@BINPATH@/components/NotificationsComponents.manifest
#endif
@ -570,6 +574,9 @@
#ifdef MOZ_SERVICES_SYNC
@BINPATH@/@PREF_DIR@/services-sync.js
#endif
#ifdef MOZ_SERVICES_HEALTHREPORT
@BINPATH@/@PREF_DIR@/healthreport-prefs.js
#endif
@BINPATH@/greprefs.js
@BINPATH@/defaults/autoconfig/platform.js
@BINPATH@/defaults/autoconfig/prefcalls.js

View File

@ -978,27 +978,32 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
def checkForZombies(self, processLog):
""" Look for hung processes """
if not os.path.exists(processLog):
self.log.info('INFO | automation.py | PID log not found: %s', processLog)
else:
self.log.info('INFO | automation.py | Reading PID log: %s', processLog)
processList = []
pidRE = re.compile(r'launched child process (\d+)$')
processLogFD = open(processLog)
for line in processLogFD:
self.log.info(line.rstrip())
m = pidRE.search(line)
if m:
processList.append(int(m.group(1)))
processLogFD.close()
self.log.info('Automation Error: PID log not found: %s', processLog)
# Whilst no hung process was found, the run should still display as a failure
return True
for processPID in processList:
self.log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID)
if self.isPidAlive(processPID):
self.log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID)
self.killPid(processPID)
foundZombie = False
self.log.info('INFO | automation.py | Reading PID log: %s', processLog)
processList = []
pidRE = re.compile(r'launched child process (\d+)$')
processLogFD = open(processLog)
for line in processLogFD:
self.log.info(line.rstrip())
m = pidRE.search(line)
if m:
processList.append(int(m.group(1)))
processLogFD.close()
for processPID in processList:
self.log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID)
if self.isPidAlive(processPID):
foundZombie = True
self.log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID)
self.killPid(processPID)
return foundZombie
def checkForCrashes(self, profileDir, symbolsPath):
automationutils.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath, self.lastTestSeen)
return automationutils.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath, self.lastTestSeen)
def runApp(self, testURL, env, app, profileDir, extraArgs,
runSSLTunnel = False, utilityPath = None,
@ -1065,8 +1070,12 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
# Do a final check for zombie child processes.
self.checkForZombies(processLog)
self.checkForCrashes(profileDir, symbolsPath)
zombieProcesses = self.checkForZombies(processLog)
crashed = self.checkForCrashes(profileDir, symbolsPath)
if crashed or zombieProcesses:
status = 1
if os.path.exists(processLog):
os.unlink(processLog)

View File

@ -146,7 +146,6 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None):
if len(dumps) == 0:
return False
foundCrash = False
removeSymbolsPath = False
# If our symbols are at a remote URL, download them now
@ -198,12 +197,11 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None):
extra = os.path.splitext(d)[0] + ".extra"
if os.path.exists(extra):
os.remove(extra)
foundCrash = True
finally:
if removeSymbolsPath:
shutil.rmtree(symbolsPath)
return foundCrash
return True
def getFullPath(directory, path):
"Get an absolute path relative to 'directory'."

View File

@ -99,11 +99,12 @@ class B2GRemoteAutomation(Automation):
# is in place.
dumpDir = tempfile.mkdtemp()
self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
crashed = automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
try:
shutil.rmtree(dumpDir)
except:
print "WARNING: unable to remove directory: %s" % (dumpDir)
return crashed
def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
# add b2g specific prefs

View File

@ -85,21 +85,22 @@ class RemoteAutomation(Automation):
def checkForCrashes(self, directory, symbolsPath):
remoteCrashDir = self._remoteProfile + '/minidumps/'
if self._devicemanager.dirExists(remoteCrashDir):
dumpDir = tempfile.mkdtemp()
self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
automationutils.checkForCrashes(dumpDir, symbolsPath,
self.lastTestSeen)
try:
shutil.rmtree(dumpDir)
except:
print "WARNING: unable to remove directory: %s" % dumpDir
else:
if not self._devicemanager.dirExists(remoteCrashDir):
# As of this writing, the minidumps directory is automatically
# created when fennec (first) starts, so its lack of presence
# is a hint that something went wrong.
print "WARNING: No crash directory (%s) on remote " \
"device" % remoteCrashDir
print "Automation Error: No crash directory (%s) found on remote device" % remoteCrashDir
# Whilst no crash was found, the run should still display as a failure
return True
dumpDir = tempfile.mkdtemp()
self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
crashed = automationutils.checkForCrashes(dumpDir, symbolsPath,
self.lastTestSeen)
try:
shutil.rmtree(dumpDir)
except:
print "WARNING: unable to remove directory: %s" % dumpDir
return crashed
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
# If remote profile is specified, use that instead

View File

@ -3,7 +3,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
llvm_revision = "167750"
llvm_revision = "168304"
moz_version = "moz0"
##############################################

View File

@ -8214,6 +8214,18 @@ if test -n "$MOZ_SERVICES_CRYPTO"; then
AC_DEFINE(MOZ_SERVICES_CRYPTO)
fi
dnl Build Firefox Health Reporter Service
AC_SUBST(MOZ_SERVICES_HEALTHREPORT)
if test -n "$MOZ_SERVICES_HEALTHREPORT"; then
AC_DEFINE(MOZ_SERVICES_HEALTHREPORT)
fi
dnl Build Services metrics component
AC_SUBST(MOZ_SERVICES_METRICS)
if test -n "$MOZ_SERVICES_METRICS"; then
AC_DEFINE(MOZ_SERVICES_METRICS)
fi
dnl Build Notifications if required
AC_SUBST(MOZ_SERVICES_NOTIFICATIONS)
if test -n "$MOZ_SERVICES_NOTIFICATIONS"; then

View File

@ -375,6 +375,8 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
{
MOZ_ASSERT(mAssertNextInsertOrAppendIndex == -1,
"splitText failed to notify insert/append?");
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
nsINode* newRoot = nullptr;
@ -383,6 +385,35 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
uint32_t newStartOffset = 0;
uint32_t newEndOffset = 0;
if (aInfo->mDetails &&
aInfo->mDetails->mType == CharacterDataChangeInfo::Details::eSplit) {
// If the splitted text node is immediately before a range boundary point
// that refers to a child index (i.e. its parent is the boundary container)
// then we need to increment the corresponding offset to account for the new
// text node that will be inserted. If so, we need to prevent the next
// ContentInserted or ContentAppended for this range from incrementing it
// again (when the new text node is notified).
nsINode* parentNode = aContent->GetParentNode();
int32_t index = -1;
if (parentNode == mEndParent && mEndOffset > 0 &&
(index = parentNode->IndexOf(aContent)) + 1 == mEndOffset) {
++mEndOffset;
mEndOffsetWasIncremented = true;
}
if (parentNode == mStartParent && mStartOffset > 0 &&
(index != -1 ? index : parentNode->IndexOf(aContent)) + 1 == mStartOffset) {
++mStartOffset;
mStartOffsetWasIncremented = true;
}
#ifdef DEBUG
if (mStartOffsetWasIncremented || mEndOffsetWasIncremented) {
mAssertNextInsertOrAppendIndex =
(mStartOffsetWasIncremented ? mStartOffset : mEndOffset) - 1;
mAssertNextInsertOrAppendNode = aInfo->mDetails->mNextSibling;
}
#endif
}
// If the changed node contains our start boundary and the change starts
// before the boundary we'll need to adjust the offset.
if (aContent == mStartParent &&
@ -469,7 +500,27 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
newRoot = IsValidBoundary(newEndNode);
}
}
// When the removed text node's parent is one of our boundary nodes we may
// need to adjust the offset to account for the removed node. However,
// there will also be a ContentRemoved notification later so the only cases
// we need to handle here is when the removed node is the text node after
// the boundary. (The m*Offset > 0 check is an optimization - a boundary
// point before the first child is never affected by normalize().)
nsINode* parentNode = aContent->GetParentNode();
if (parentNode == mStartParent && mStartOffset > 0 &&
mStartOffset < parentNode->GetChildCount() &&
removed == parentNode->GetChildAt(mStartOffset)) {
newStartNode = aContent;
newStartOffset = aInfo->mChangeStart;
}
if (parentNode == mEndParent && mEndOffset > 0 &&
mEndOffset < parentNode->GetChildCount() &&
removed == parentNode->GetChildAt(mEndOffset)) {
newEndNode = aContent;
newEndOffset = aInfo->mChangeEnd;
}
}
if (newStartNode || newEndNode) {
if (!newStartNode) {
newStartNode = mStartParent;
@ -504,6 +555,17 @@ nsRange::ContentAppended(nsIDocument* aDocument,
child = child->GetNextSibling();
}
}
if (mStartOffsetWasIncremented || mEndOffsetWasIncremented) {
MOZ_ASSERT(mAssertNextInsertOrAppendIndex == aNewIndexInContainer);
MOZ_ASSERT(mAssertNextInsertOrAppendNode == aFirstNewContent);
MOZ_ASSERT(aFirstNewContent->IsNodeOfType(nsINode::eTEXT));
mStartOffsetWasIncremented = mEndOffsetWasIncremented = false;
#ifdef DEBUG
mAssertNextInsertOrAppendIndex = -1;
mAssertNextInsertOrAppendNode = nullptr;
#endif
}
}
void
@ -517,10 +579,12 @@ nsRange::ContentInserted(nsIDocument* aDocument,
nsINode* container = NODE_FROM(aContainer, aDocument);
// Adjust position if a sibling was inserted.
if (container == mStartParent && aIndexInContainer < mStartOffset) {
if (container == mStartParent && aIndexInContainer < mStartOffset &&
!mStartOffsetWasIncremented) {
++mStartOffset;
}
if (container == mEndParent && aIndexInContainer < mEndOffset) {
if (container == mEndParent && aIndexInContainer < mEndOffset &&
!mEndOffsetWasIncremented) {
++mEndOffset;
}
if (container->IsSelectionDescendant() &&
@ -528,6 +592,17 @@ nsRange::ContentInserted(nsIDocument* aDocument,
MarkDescendants(aChild);
aChild->SetDescendantOfCommonAncestorForRangeInSelection();
}
if (mStartOffsetWasIncremented || mEndOffsetWasIncremented) {
MOZ_ASSERT(mAssertNextInsertOrAppendIndex == aIndexInContainer);
MOZ_ASSERT(mAssertNextInsertOrAppendNode == aChild);
MOZ_ASSERT(aChild->IsNodeOfType(nsINode::eTEXT));
mStartOffsetWasIncremented = mEndOffsetWasIncremented = false;
#ifdef DEBUG
mAssertNextInsertOrAppendIndex = -1;
mAssertNextInsertOrAppendNode = nullptr;
#endif
}
}
void
@ -538,6 +613,9 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
nsIContent* aPreviousSibling)
{
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
MOZ_ASSERT(!mStartOffsetWasIncremented && !mEndOffsetWasIncremented &&
mAssertNextInsertOrAppendIndex == -1,
"splitText failed to notify insert/append?");
nsINode* container = NODE_FROM(aContainer, aDocument);
bool gravitateStart = false;
@ -581,6 +659,9 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
void
nsRange::ParentChainChanged(nsIContent *aContent)
{
MOZ_ASSERT(!mStartOffsetWasIncremented && !mEndOffsetWasIncremented &&
mAssertNextInsertOrAppendIndex == -1,
"splitText failed to notify insert/append?");
NS_ASSERTION(mRoot == aContent, "Wrong ParentChainChanged notification?");
nsINode* newRoot = IsValidBoundary(mStartParent);
NS_ASSERTION(newRoot, "No valid boundary or root found!");

View File

@ -30,6 +30,12 @@ public:
, mIsDetached(false)
, mMaySpanAnonymousSubtrees(false)
, mInSelection(false)
, mStartOffsetWasIncremented(false)
, mEndOffsetWasIncremented(false)
#ifdef DEBUG
, mAssertNextInsertOrAppendIndex(-1)
, mAssertNextInsertOrAppendNode(nullptr)
#endif
{}
virtual ~nsRange();
@ -229,6 +235,12 @@ protected:
bool mIsDetached;
bool mMaySpanAnonymousSubtrees;
bool mInSelection;
bool mStartOffsetWasIncremented;
bool mEndOffsetWasIncremented;
#ifdef DEBUG
int32_t mAssertNextInsertOrAppendIndex;
nsINode* mAssertNextInsertOrAppendNode;
#endif
};
#endif /* nsRange_h___ */

View File

@ -593,6 +593,8 @@ MOCHITEST_FILES_B = \
file_bug804395.jar \
test_bug804395.html \
test_bug809003.html \
test_textnode_split_in_selection.html \
test_textnode_normalize_in_selection.html \
$(NULL)
# OOP tests don't work on Windows (bug 763081) or native-fennec

View File

@ -0,0 +1,201 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=804784
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 804784</title>
<script type="application/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=804784">Mozilla Bug 804784</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 804784 **/
var sel = document.getSelection();
var flush = true;
var dry = true;
var run = "";
var empty_range;
var empty_first_text_range;
var empty_last_text_range;
var full_range;
function check(range, expected, test)
{
is(""+range, expected, test);
is(""+empty_range, "", "empty range test after: "+test);
is(""+empty_first_text_range, "", "empty first text range test after: "+test);
if (empty_last_text_range) is(""+empty_last_text_range, "", "empty last text range test after: "+test);
is(""+full_range, full_range.startContainer.textContent, "full range test after: "+test);
}
function newDiv()
{
var div = document.createElement('div');
for (var i = 0; i < arguments.length; ++i) {
div.appendChild(document.createTextNode(arguments[i]));
}
document.body.appendChild(div)
empty_range = document.createRange();
empty_range.setStart(div,0);
empty_range.setEnd(div,0);
var firstTextNode = div.childNodes[0];
var lastTextNode = div.childNodes[div.childNodes.length - 1];
empty_first_text_range = document.createRange();
empty_first_text_range.setStart(firstTextNode,0);
empty_first_text_range.setEnd(firstTextNode,0);
empty_last_text_range = null;
if (firstTextNode != lastTextNode) {
empty_last_text_range = document.createRange();
empty_last_text_range.setStart(lastTextNode,0);
empty_last_text_range.setEnd(lastTextNode,0);
}
full_range = document.createRange();
full_range.setStart(div,0);
full_range.setEnd(div,div.childNodes.length);
return div;
}
function selEnd(div,child,index,s)
{
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(start, index);
r.setEnd(div, div.childNodes.length);
if (!dry) div.normalize();
check(r,s,run+" selEnd "+child+","+index);
}
function selStart(div,child,index,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(div, 0);
r.setEnd(start, index);
if (!dry) div.normalize();
check(r,s,run+" selStart "+child+","+index);
}
function selMiddleStart(div,child,index,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(div, 1);
r.setEnd(start, index);
div.normalize();
check(r,s,run+" selMiddleStart "+child+","+index);
}
function selMiddleEnd(div,child,index,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(start, index);
r.setEnd(div, 2);
if (!dry) div.normalize();
check(r,s,run+" selMiddleEnd "+child+","+index);
}
function mergeBefore(div,child,index,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(div, 1);
r.setEnd(start, index);
if (!dry) div.normalize();
check(r,s,run+" mergeBefore "+child+","+index);
}
function runTests(s)
{
run = s+":";
selEnd(newDiv('111'), 0,0,'111');
selEnd(newDiv('111'), 0,1,'11');
selEnd(newDiv('111'), 0,2,'1');
selEnd(newDiv(''), 0,0,'');
selEnd(newDiv('',''), 1,0,'');
selEnd(newDiv('','',''), 1,0,'');
selEnd(newDiv('111','222'), 0,1,'11222');
selEnd(newDiv('111','222'), 0,2,'1222');
selEnd(newDiv('111','222'), 1,1,'22');
selEnd(newDiv('','222'), 1,2,'2');
selEnd(newDiv('111',''), 0,1,'11');
selEnd(newDiv('111','222'), 1,2,'2');
selEnd(newDiv('111','222','333'), 1,1,'22333');
selEnd(newDiv('111','222','333'), 1,2,'2333');
selEnd(newDiv('111','','333'), 0,2,'1333');
selEnd(newDiv('111','','333'), 1,0,'333');
selEnd(newDiv('111','','333'), 2,0,'333');
selStart(newDiv('111'), 0,0,'');
selStart(newDiv('111'), 0,1,'1');
selStart(newDiv('111'), 0,2,'11');
selStart(newDiv(''), 0,0,'');
selStart(newDiv('111','222'), 0,1,'1');
selStart(newDiv('111','222'), 0,2,'11');
selStart(newDiv('111','222'), 1,1,'1112');
selStart(newDiv('111','222'), 1,2,'11122');
selStart(newDiv('111',''), 1,0,'111');
selStart(newDiv('111',''), 0,2,'11');
selStart(newDiv('111','222','333'), 1,1,'1112');
selStart(newDiv('111','222','333'), 1,2,'11122');
selStart(newDiv('111','222','333'), 1,2,'11122');
selStart(newDiv('111','','333'), 1,0,'111');
selMiddleStart(newDiv('111','222','333'), 1,1,'2');
selMiddleStart(newDiv('111','222','333'), 1,2,'22');
selMiddleStart(newDiv('111','222','333'), 2,1,'2223');
selMiddleStart(newDiv('111','222','333'), 2,2,'22233');
selMiddleStart(newDiv('111','','333'), 2,2,'33');
selMiddleStart(newDiv('111','222',''), 2,0,'222');
selMiddleEnd(newDiv('111','222','333'), 0,1,'11222');
selMiddleEnd(newDiv('111','222','333'), 0,2,'1222');
selMiddleEnd(newDiv('111','222','333'), 1,1,'22');
selMiddleEnd(newDiv('111','222','333'), 1,2,'2');
selMiddleEnd(newDiv('111','','333'), 1,0,'');
selMiddleEnd(newDiv('','222','333'), 0,0,'222');
mergeBefore(newDiv('111','222'), 1,1,'2');
mergeBefore(newDiv('111','222','333'), 1,2,'22');
mergeBefore(newDiv('111','222','333'), 2,1,'2223');
mergeBefore(newDiv('111','222','333'), 2,2,'22233');
mergeBefore(newDiv('111','','333'), 2,0,'');
mergeBefore(newDiv('111','','333'), 2,2,'33');
}
function boom()
{
runTests("dry run"); // this is to verify the result strings without normalize()
dry = false;
flush = false;
runTests("no flush");
flush = true;
runTests("flush");
}
boom();
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,221 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=803924
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 803924</title>
<script type="application/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=803924">Mozilla Bug 803924</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 803924 **/
var sel = document.getSelection();
var flush = true;
var dry = true;
var run = "";
var empty_range;
var empty_first_text_range;
var empty_last_text_range;
var full_range;
function check(range, expected, test)
{
is(""+range, expected, test);
is(""+empty_range, "", "empty range test after: "+test);
is(""+empty_first_text_range, "", "empty first text range test after: "+test);
if (empty_last_text_range) is(""+empty_last_text_range, "", "empty last text range test after: "+test);
is(""+full_range, full_range.startContainer.textContent, "full range test after: "+test);
}
function newDiv()
{
var div = document.createElement('div');
for (var i = 0; i < arguments.length; ++i) {
div.appendChild(document.createTextNode(arguments[i]));
}
document.body.appendChild(div)
empty_range = document.createRange();
empty_range.setStart(div,0);
empty_range.setEnd(div,0);
var firstTextNode = div.childNodes[0];
var lastTextNode = div.childNodes[div.childNodes.length - 1];
empty_first_text_range = document.createRange();
empty_first_text_range.setStart(firstTextNode,0);
empty_first_text_range.setEnd(firstTextNode,0);
empty_last_text_range = null;
if (firstTextNode != lastTextNode) {
empty_last_text_range = document.createRange();
empty_last_text_range.setStart(lastTextNode,0);
empty_last_text_range.setEnd(lastTextNode,0);
}
full_range = document.createRange();
full_range.setStart(div,0);
full_range.setEnd(div,div.childNodes.length);
return div;
}
function selEnd(div,child,index,split,s)
{
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(start, index);
r.setEnd(div, div.childNodes.length);
if (!dry) start.splitText(split);
check(r,s,run+" selEnd "+child+","+index+","+split);
}
function selStart(div,child,index,split,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(div, 0);
r.setEnd(start, index);
if (!dry) start.splitText(split);
check(r,s,run+" selStart "+child+","+index+","+split);
}
function selMiddleStart(div,child,index,split,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(div, 1);
r.setEnd(start, index);
if (!dry) start.splitText(split);
check(r,s,run+" selMiddleStart "+child+","+index+","+split);
}
function selMiddleEnd(div,child,index,split,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(start, index);
r.setEnd(div, 2);
if (!dry) start.splitText(split);
check(r,s,run+" selMiddleEnd "+child+","+index+","+split);
}
function splitBefore(div,child,index,split,s)
{
if (flush) document.body.getClientRects();
var start = div.childNodes[child];
var r = document.createRange();
sel.addRange(r);
r.setStart(div, 1);
r.setEnd(start, index);
if (!dry) div.childNodes[0].splitText(split);
check(r,s,run+" splitBefore "+child+","+index+","+split);
}
function runTests(s)
{
run = s+":";
selEnd(newDiv('111'), 0,0,0,'111');
selEnd(newDiv('111'), 0,0,1,'111');
selEnd(newDiv('111'), 0,0,3,'111');
selEnd(newDiv(''), 0,0,0,'');
selEnd(newDiv('111'), 0,1,0,'11');
selEnd(newDiv('111'), 0,2,1,'1');
selEnd(newDiv('111'), 0,1,3,'11');
selEnd(newDiv('111','222'), 0,1,0,'11222');
selEnd(newDiv('111','222'), 0,2,1,'1222');
selEnd(newDiv('111','222'), 0,1,3,'11222');
selEnd(newDiv('111','222'), 1,1,0,'22');
selEnd(newDiv('111','222'), 1,2,1,'2');
selEnd(newDiv('','222'), 1,1,1,'22');
selEnd(newDiv('','222'), 0,0,0,'222');
selEnd(newDiv('111',''), 0,1,0,'11');
selEnd(newDiv('111','222'), 1,1,3,'22');
selEnd(newDiv('111','222','333'), 1,1,0,'22333');
selEnd(newDiv('111','222','333'), 1,2,1,'2333');
selEnd(newDiv('111','222','333'), 1,1,3,'22333');
selEnd(newDiv('111','222',''), 1,1,3,'22');
selEnd(newDiv('111','','333'), 0,1,3,'11333');
selStart(newDiv('111'), 0,0,0,'');
selStart(newDiv('111'), 0,0,1,'');
selStart(newDiv('111'), 0,0,3,'');
selStart(newDiv('111'), 0,1,0,'1');
selStart(newDiv('111'), 0,2,1,'11');
selStart(newDiv('111'), 0,1,3,'1');
selStart(newDiv(''), 0,0,0,'');
selStart(newDiv('111','222'), 0,1,0,'1');
selStart(newDiv('111','222'), 0,2,1,'11');
selStart(newDiv('111','222'), 0,1,3,'1');
selStart(newDiv('111','222'), 1,1,0,'1112');
selStart(newDiv('111','222'), 1,2,1,'11122');
selStart(newDiv('111','222'), 1,1,3,'1112');
selStart(newDiv('','222'), 1,1,2,'2');
selStart(newDiv('','222'), 0,0,0,'');
selStart(newDiv('111',''), 1,0,0,'111');
selStart(newDiv('111','222','333'), 1,1,0,'1112');
selStart(newDiv('111','222','333'), 1,2,1,'11122');
selStart(newDiv('111','222','333'), 1,1,3,'1112');
selStart(newDiv('111','','333'), 1,0,0,'111');
selStart(newDiv('111','222',''), 1,1,3,'1112');
selMiddleStart(newDiv('111','222','333'), 1,1,0,'2');
selMiddleStart(newDiv('111','222','333'), 1,2,1,'22');
selMiddleStart(newDiv('111','222','333'), 1,1,3,'2');
selMiddleStart(newDiv('111','222','333'), 2,1,0,'2223');
selMiddleStart(newDiv('111','222','333'), 2,2,1,'22233');
selMiddleStart(newDiv('111','222','333'), 2,1,3,'2223');
selMiddleStart(newDiv('111','','333'), 2,1,2,'3');
selMiddleStart(newDiv('111','','333'), 1,0,0,'');
selMiddleEnd(newDiv('111','222','333'), 0,1,0,'11222');
selMiddleEnd(newDiv('111','222','333'), 0,2,1,'1222');
selMiddleEnd(newDiv('111','222','333'), 0,1,3,'11222');
selMiddleEnd(newDiv('111','222','333'), 1,1,0,'22');
selMiddleEnd(newDiv('111','222','333'), 1,2,1,'2');
selMiddleEnd(newDiv('111','222','333'), 1,1,3,'22');
selMiddleEnd(newDiv('111','','333'), 0,1,2,'11');
selMiddleEnd(newDiv('111','','333'), 0,1,3,'11');
selMiddleEnd(newDiv('111','','333'), 1,0,0,'');
splitBefore(newDiv('111','222','333'), 1,1,0,'2');
splitBefore(newDiv('111','222','333'), 1,2,1,'22');
splitBefore(newDiv('111','222','333'), 1,1,3,'2');
splitBefore(newDiv('111','222','333'), 2,1,0,'2223');
splitBefore(newDiv('111','222','333'), 2,2,1,'22233');
splitBefore(newDiv('111','222','333'), 2,1,3,'2223');
splitBefore(newDiv('','222','333'), 1,1,0,'2');
splitBefore(newDiv('','','333'), 1,0,0,'');
splitBefore(newDiv('','222',''), 2,0,0,'222');
splitBefore(newDiv('111','','333'), 2,1,2,'3');
}
function boom()
{
runTests("dry run"); // this is to verify the result strings without splitText()
dry = false;
flush = false;
runTests("no flush");
flush = true;
runTests("flush");
}
boom();
</script>
</pre>
</body>
</html>

View File

@ -85,100 +85,5 @@ CoerceDouble(jsval v, double* d)
return true;
}
template<size_t N>
static bool
JSValToMatrixElts(JSContext* cx, const jsval& val,
double* (&elts)[N], nsresult* rv)
{
JSObject* obj;
uint32_t length;
if (JSVAL_IS_PRIMITIVE(val) ||
!(obj = JSVAL_TO_OBJECT(val)) ||
!JS_GetArrayLength(cx, obj, &length) ||
N != length) {
// Not an array-like thing or wrong size
*rv = NS_ERROR_INVALID_ARG;
return false;
}
for (uint32_t i = 0; i < N; ++i) {
jsval elt;
double d;
if (!JS_GetElement(cx, obj, i, &elt)) {
*rv = NS_ERROR_FAILURE;
return false;
}
if (!CoerceDouble(elt, &d)) {
*rv = NS_ERROR_INVALID_ARG;
return false;
}
if (!FloatValidate(d)) {
// This is weird, but it's the behavior of SetTransform()
*rv = NS_OK;
return false;
}
*elts[i] = d;
}
*rv = NS_OK;
return true;
}
bool
JSValToMatrix(JSContext* cx, const jsval& val, gfxMatrix* matrix, nsresult* rv)
{
double* elts[] = { &matrix->xx, &matrix->yx, &matrix->xy, &matrix->yy,
&matrix->x0, &matrix->y0 };
return JSValToMatrixElts(cx, val, elts, rv);
}
bool
JSValToMatrix(JSContext* cx, const jsval& val, Matrix* matrix, nsresult* rv)
{
gfxMatrix m;
if (!JSValToMatrix(cx, val, &m, rv))
return false;
*matrix = Matrix(Float(m.xx), Float(m.yx), Float(m.xy), Float(m.yy),
Float(m.x0), Float(m.y0));
return true;
}
template<size_t N>
static nsresult
MatrixEltsToJSVal(/*const*/ jsval (&elts)[N], JSContext* cx, jsval* val)
{
JSObject* obj = JS_NewArrayObject(cx, N, elts);
if (!obj) {
return NS_ERROR_OUT_OF_MEMORY;
}
*val = OBJECT_TO_JSVAL(obj);
return NS_OK;
}
nsresult
MatrixToJSVal(const gfxMatrix& matrix, JSContext* cx, jsval* val)
{
jsval elts[] = {
DOUBLE_TO_JSVAL(matrix.xx), DOUBLE_TO_JSVAL(matrix.yx),
DOUBLE_TO_JSVAL(matrix.xy), DOUBLE_TO_JSVAL(matrix.yy),
DOUBLE_TO_JSVAL(matrix.x0), DOUBLE_TO_JSVAL(matrix.y0)
};
return MatrixEltsToJSVal(elts, cx, val);
}
nsresult
MatrixToJSVal(const Matrix& matrix, JSContext* cx, jsval* val)
{
jsval elts[] = {
DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
};
return MatrixEltsToJSVal(elts, cx, val);
}
} // namespace CanvasUtils
} // namespace mozilla

View File

@ -49,18 +49,6 @@ void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
// succeeded.
bool CoerceDouble(jsval v, double* d);
// Return true iff the conversion succeeded, false otherwise. *rv is
// the value to return to script if this returns false.
bool JSValToMatrix(JSContext* cx, const jsval& val,
gfxMatrix* matrix, nsresult* rv);
bool JSValToMatrix(JSContext* cx, const jsval& val,
gfx::Matrix* matrix, nsresult* rv);
nsresult MatrixToJSVal(const gfxMatrix& matrix,
JSContext* cx, jsval* val);
nsresult MatrixToJSVal(const gfx::Matrix& matrix,
JSContext* cx, jsval* val);
/* Float validation stuff */
#define VALIDATE(_f) if (!NS_finite(_f)) return false

View File

@ -55,6 +55,7 @@ CPPSRCS += \
WebGLExtensionTextureFilterAnisotropic.cpp \
WebGLExtensionTextureFloat.cpp \
WebGLFramebuffer.cpp \
WebGLObjectModel.cpp \
WebGLProgram.cpp \
WebGLRenderbuffer.cpp \
WebGLShader.cpp \

View File

@ -3,11 +3,57 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLBuffer.h"
#include "WebGLContext.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
using namespace mozilla;
WebGLBuffer::WebGLBuffer(WebGLContext *context)
: WebGLContextBoundObject(context)
, mHasEverBeenBound(false)
, mByteLength(0)
, mTarget(LOCAL_GL_NONE)
{
SetIsDOMBinding();
mContext->MakeContextCurrent();
mContext->gl->fGenBuffers(1, &mGLName);
mContext->mBuffers.insertBack(this);
}
WebGLBuffer::~WebGLBuffer() {
DeleteOnce();
}
void
WebGLBuffer::Delete() {
mContext->MakeContextCurrent();
mContext->gl->fDeleteBuffers(1, &mGLName);
mByteLength = 0;
mCache = nullptr;
LinkedListElement<WebGLBuffer>::remove(); // remove from mContext->mBuffers
}
void
WebGLBuffer::SetTarget(GLenum target) {
mTarget = target;
if (!mCache && mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
mCache = new WebGLElementArrayCache;
}
bool
WebGLBuffer::ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes) {
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
return mCache->BufferData(ptr, buffer_size_in_bytes);
return true;
}
void
WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes) {
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
mCache->BufferSubData(pos, ptr, update_size_in_bytes);
}
JSObject*
WebGLBuffer::WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap) {
return dom::WebGLBufferBinding::Wrap(cx, scope, this, triedToWrap);

View File

@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef WEBGLBUFFER_H_
#define WEBGLBUFFER_H_
#include "WebGLElementArrayCache.h"
#include "WebGLObjectModel.h"
#include "nsWrapperCache.h"
#include "mozilla/LinkedList.h"
namespace mozilla {
class WebGLBuffer MOZ_FINAL
: public nsISupports
, public WebGLRefCountedObject<WebGLBuffer>
, public LinkedListElement<WebGLBuffer>
, public WebGLContextBoundObject
, public nsWrapperCache
{
public:
WebGLBuffer(WebGLContext *context);
~WebGLBuffer();
void Delete();
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
return aMallocSizeOf(this) + sizeOfCache;
}
bool HasEverBeenBound() { return mHasEverBeenBound; }
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
GLuint GLName() const { return mGLName; }
GLuint ByteLength() const { return mByteLength; }
GLenum Target() const { return mTarget; }
void SetByteLength(GLuint byteLength) { mByteLength = byteLength; }
void SetTarget(GLenum target);
bool ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes);
void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes);
bool Validate(WebGLenum type, uint32_t max_allowed, size_t first, size_t count) {
return mCache->Validate(type, max_allowed, first, count);
}
WebGLContext *GetParentObject() const {
return Context();
}
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLBuffer)
protected:
WebGLuint mGLName;
bool mHasEverBeenBound;
GLuint mByteLength;
GLenum mTarget;
nsAutoPtr<WebGLElementArrayCache> mCache;
};
}
#endif //WEBGLBUFFER_H_

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLObjectModel.h"
#include "WebGLExtensions.h"
#include "WebGLContextUtils.h"

View File

@ -6,6 +6,10 @@
#ifndef WEBGLCONTEXT_H_
#define WEBGLCONTEXT_H_
#include "WebGLElementArrayCache.h"
#include "WebGLObjectModel.h"
#include "WebGLBuffer.h"
#include <stdarg.h>
#include <vector>
@ -42,8 +46,6 @@
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingUtils.h"
#include "WebGLElementArrayCache.h"
/*
* Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
* https://bugzilla.mozilla.org/show_bug.cgi?id=686732
@ -62,30 +64,16 @@
#define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164
#define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164
// Manual reflection of WebIDL typedefs
typedef uint32_t WebGLenum;
typedef uint32_t WebGLbitfield;
typedef int32_t WebGLint;
typedef int32_t WebGLsizei;
typedef int64_t WebGLsizeiptr;
typedef int64_t WebGLintptr;
typedef uint32_t WebGLuint;
typedef float WebGLfloat;
typedef float WebGLclampf;
typedef bool WebGLboolean;
class nsIPropertyBag;
namespace mozilla {
class WebGLTexture;
class WebGLBuffer;
class WebGLProgram;
class WebGLShader;
class WebGLFramebuffer;
class WebGLRenderbuffer;
class WebGLUniformLocation;
class WebGLContext;
class WebGLRenderbuffer;
struct WebGLVertexAttribData;
class WebGLMemoryPressureObserver;
class WebGLRectangleObject;
@ -163,246 +151,6 @@ inline bool is_pot_assuming_nonnegative(WebGLsizei x)
return x && (x & (x-1)) == 0;
}
/* Each WebGL object class WebGLFoo wants to:
* - inherit WebGLRefCountedObject<WebGLFoo>
* - implement a Delete() method
* - have its destructor call DeleteOnce()
*
* This base class provides two features to WebGL object types:
* 1. support for OpenGL object reference counting
* 2. support for OpenGL deletion statuses
*
***** 1. OpenGL object reference counting *****
*
* WebGL objects such as WebGLTexture's really have two different refcounts:
* the XPCOM refcount, that is directly exposed to JavaScript, and the OpenGL
* refcount.
*
* For example, when in JavaScript one does: var newname = existingTexture;
* that increments the XPCOM refcount, but doesn't affect the OpenGL refcount.
* When one attaches the texture to a framebuffer object, that does increment
* its OpenGL refcount (and also its XPCOM refcount, to prevent the regular
* XPCOM refcounting mechanism from destroying objects prematurely).
*
* The actual OpenGL refcount is opaque to us (it's internal to the OpenGL
* implementation) but is affects the WebGL semantics that we have to implement:
* for example, a WebGLTexture that is attached to a WebGLFramebuffer must not
* be actually deleted, even if deleteTexture has been called on it, and even
* if JavaScript doesn't have references to it anymore. We can't just rely on
* OpenGL to keep alive the underlying OpenGL texture for us, for a variety of
* reasons, most importantly: we'd need to know when OpenGL objects are actually
* deleted, and OpenGL doesn't notify us about that, so we would have to query
* status very often with glIsXxx calls which isn't practical.
*
* This means that we have to keep track of the OpenGL refcount ourselves,
* in addition to the XPCOM refcount.
*
* This class implements such a refcount, see the mWebGLRefCnt
* member. In order to avoid name clashes (with regular XPCOM refcounting)
* in the derived class, we prefix members with 'WebGL', whence the names
* WebGLAddRef, WebGLRelease, etc.
*
* In practice, WebGLAddRef and WebGLRelease are only called from the
* WebGLRefPtr class.
*
***** 2. OpenGL deletion statuses *****
*
* In OpenGL, an object can go through 3 different deletion statuses during its
* lifetime, which correspond to the 3 enum values for DeletionStatus in this class:
* - the Default status, which it has from its creation to when the
* suitable glDeleteXxx function is called on it;
* - the DeleteRequested status, which is has from when the suitable glDeleteXxx
* function is called on it to when it is no longer referenced by other OpenGL
* objects. For example, a texture that is attached to a non-current FBO
* will enter that status when glDeleteTexture is called on it. For objects
* with that status, GL_DELETE_STATUS queries return true, but glIsXxx
* functions still return true.
* - the Deleted status, which is the status of objects on which the
* suitable glDeleteXxx function has been called, and that are not referenced
* by other OpenGL objects.
*
* This state is stored in the mDeletionStatus member of this class.
*
* When the GL refcount hits zero, if the status is DeleteRequested then we call
* the Delete() method on the derived class and the status becomes Deleted. This is
* what the MaybeDelete() function does.
*
* The DeleteOnce() function implemented here is a helper to ensure that we don't
* call Delete() twice on the same object. Since the derived class' destructor
* needs to call DeleteOnce() which calls Delete(), we can't allow either to be
* virtual. Strictly speaking, we could let them be virtual if the derived class
* were final, but that would be impossible to enforce and would lead to strange
* bugs if it were subclassed.
*
* This WebGLRefCountedObject class takes the Derived type
* as template parameter, as a means to allow DeleteOnce to call Delete()
* on the Derived class, without either method being virtual. This is a common
* C++ pattern known as the "curiously recursive template pattern (CRTP)".
*/
template<typename Derived>
class WebGLRefCountedObject
{
public:
enum DeletionStatus { Default, DeleteRequested, Deleted };
WebGLRefCountedObject()
: mDeletionStatus(Default)
{ }
~WebGLRefCountedObject() {
NS_ABORT_IF_FALSE(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
NS_ABORT_IF_FALSE(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
}
// called by WebGLRefPtr
void WebGLAddRef() {
++mWebGLRefCnt;
}
// called by WebGLRefPtr
void WebGLRelease() {
NS_ABORT_IF_FALSE(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
--mWebGLRefCnt;
MaybeDelete();
}
// this is the function that WebGL.deleteXxx() functions want to call
void RequestDelete() {
if (mDeletionStatus == Default)
mDeletionStatus = DeleteRequested;
MaybeDelete();
}
bool IsDeleted() const {
return mDeletionStatus == Deleted;
}
bool IsDeleteRequested() const {
return mDeletionStatus != Default;
}
void DeleteOnce() {
if (mDeletionStatus != Deleted) {
static_cast<Derived*>(this)->Delete();
mDeletionStatus = Deleted;
}
}
private:
void MaybeDelete() {
if (mWebGLRefCnt == 0 &&
mDeletionStatus == DeleteRequested)
{
DeleteOnce();
}
}
protected:
nsAutoRefCnt mWebGLRefCnt;
DeletionStatus mDeletionStatus;
};
/* This WebGLRefPtr class is meant to be used for references between WebGL objects.
* For example, a WebGLProgram holds WebGLRefPtr's to the WebGLShader's attached
* to it.
*
* Why the need for a separate refptr class? The only special thing that WebGLRefPtr
* does is that it increments and decrements the WebGL refcount of
* WebGLRefCountedObject's, in addition to incrementing and decrementing the
* usual XPCOM refcount.
*
* This means that by using a WebGLRefPtr instead of a nsRefPtr, you ensure that
* the WebGL refcount is incremented, which means that the object will be kept
* alive by this reference even if the matching webgl.deleteXxx() function is
* called on it.
*/
template<typename T>
class WebGLRefPtr
{
public:
WebGLRefPtr()
: mRawPtr(0)
{ }
WebGLRefPtr(const WebGLRefPtr<T>& aSmartPtr)
: mRawPtr(aSmartPtr.mRawPtr)
{
AddRefOnPtr(mRawPtr);
}
WebGLRefPtr(T *aRawPtr)
: mRawPtr(aRawPtr)
{
AddRefOnPtr(mRawPtr);
}
~WebGLRefPtr() {
ReleasePtr(mRawPtr);
}
WebGLRefPtr<T>&
operator=(const WebGLRefPtr<T>& rhs)
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
WebGLRefPtr<T>&
operator=(T* rhs)
{
assign_with_AddRef(rhs);
return *this;
}
T* get() const {
return static_cast<T*>(mRawPtr);
}
operator T*() const {
return get();
}
T* operator->() const {
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL WebGLRefPtr with operator->()!");
return get();
}
T& operator*() const {
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL WebGLRefPtr with operator*()!");
return *get();
}
private:
static void AddRefOnPtr(T* rawPtr) {
if (rawPtr) {
rawPtr->WebGLAddRef();
rawPtr->AddRef();
}
}
static void ReleasePtr(T* rawPtr) {
if (rawPtr) {
rawPtr->WebGLRelease(); // must be done first before Release(), as Release() might actually destroy the object
rawPtr->Release();
}
}
void assign_with_AddRef(T* rawPtr) {
AddRefOnPtr(rawPtr);
assign_assuming_AddRef(rawPtr);
}
void assign_assuming_AddRef(T* newPtr) {
T* oldPtr = mRawPtr;
mRawPtr = newPtr;
ReleasePtr(oldPtr);
}
protected:
T *mRawPtr;
};
// this class is a mixin for GL objects that have dimensions
// that we need to track.
class WebGLRectangleObject
@ -1463,29 +1211,6 @@ ToSupports(WebGLContext* context)
return static_cast<nsICanvasRenderingContextInternal*>(context);
}
// This class is a mixin for objects that are tied to a specific
// context (which is to say, all of them). They provide initialization
// as well as comparison with the current context.
class WebGLContextBoundObject
{
public:
WebGLContextBoundObject(WebGLContext *context) {
mContext = context;
mContextGeneration = context->Generation();
}
bool IsCompatibleWithContext(WebGLContext *other) {
return mContext == other &&
mContextGeneration == other->Generation();
}
WebGLContext *Context() const { return mContext; }
protected:
WebGLContext *mContext;
uint32_t mContextGeneration;
};
struct WebGLVertexAttribData {
// note that these initial values are what GL initializes vertex attribs to
WebGLVertexAttribData()
@ -1531,90 +1256,6 @@ struct WebGLVertexAttribData {
}
};
class WebGLBuffer MOZ_FINAL
: public nsISupports
, public WebGLRefCountedObject<WebGLBuffer>
, public LinkedListElement<WebGLBuffer>
, public WebGLContextBoundObject
, public nsWrapperCache
{
public:
WebGLBuffer(WebGLContext *context)
: WebGLContextBoundObject(context)
, mHasEverBeenBound(false)
, mByteLength(0)
, mTarget(LOCAL_GL_NONE)
{
SetIsDOMBinding();
mContext->MakeContextCurrent();
mContext->gl->fGenBuffers(1, &mGLName);
mContext->mBuffers.insertBack(this);
}
~WebGLBuffer() {
DeleteOnce();
}
void Delete() {
mContext->MakeContextCurrent();
mContext->gl->fDeleteBuffers(1, &mGLName);
mByteLength = 0;
mCache = nullptr;
LinkedListElement<WebGLBuffer>::removeFrom(mContext->mBuffers);
}
size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
return aMallocSizeOf(this) + sizeOfCache;
}
bool HasEverBeenBound() { return mHasEverBeenBound; }
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
GLuint GLName() const { return mGLName; }
GLuint ByteLength() const { return mByteLength; }
GLenum Target() const { return mTarget; }
void SetByteLength(GLuint byteLength) { mByteLength = byteLength; }
void SetTarget(GLenum target) {
mTarget = target;
if (!mCache && mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
mCache = new WebGLElementArrayCache;
}
bool ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes) {
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
return mCache->BufferData(ptr, buffer_size_in_bytes);
return true;
}
void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes) {
if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
mCache->BufferSubData(pos, ptr, update_size_in_bytes);
}
bool Validate(WebGLenum type, uint32_t max_allowed, size_t first, size_t count) {
return mCache->Validate(type, max_allowed, first, count);
}
WebGLContext *GetParentObject() const {
return Context();
}
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLBuffer)
protected:
WebGLuint mGLName;
bool mHasEverBeenBound;
GLuint mByteLength;
GLenum mTarget;
nsAutoPtr<WebGLElementArrayCache> mCache;
};
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
@ -3467,22 +3108,4 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
aCallback.NoteXPCOMChild(aField.buf);
}
template <typename T>
inline void
ImplCycleCollectionUnlink(mozilla::WebGLRefPtr<T>& aField)
{
aField = nullptr;
}
template <typename T>
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
mozilla::WebGLRefPtr<T>& aField,
const char* aName,
uint32_t aFlags = 0)
{
CycleCollectionNoteEdgeName(aCallback, aName, aFlags);
aCallback.NoteXPCOMChild(aField);
}
#endif

View File

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLObjectModel.h"
#include "WebGLContext.h"
using namespace mozilla;
WebGLContextBoundObject::WebGLContextBoundObject(WebGLContext *context) {
mContext = context;
mContextGeneration = context->Generation();
}
bool
WebGLContextBoundObject::IsCompatibleWithContext(WebGLContext *other) {
return mContext == other &&
mContextGeneration == other->Generation();
}

View File

@ -0,0 +1,306 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef WEBGLOBJECTMODEL_H_
#define WEBGLOBJECTMODEL_H_
#include "nsCycleCollectionNoteChild.h"
#include "nsICanvasRenderingContextInternal.h"
// Manual reflection of WebIDL typedefs
typedef uint32_t WebGLenum;
typedef uint32_t WebGLbitfield;
typedef int32_t WebGLint;
typedef int32_t WebGLsizei;
typedef int64_t WebGLsizeiptr;
typedef int64_t WebGLintptr;
typedef uint32_t WebGLuint;
typedef float WebGLfloat;
typedef float WebGLclampf;
typedef bool WebGLboolean;
namespace mozilla {
class WebGLBuffer;
class WebGLContext;
/* Each WebGL object class WebGLFoo wants to:
* - inherit WebGLRefCountedObject<WebGLFoo>
* - implement a Delete() method
* - have its destructor call DeleteOnce()
*
* This base class provides two features to WebGL object types:
* 1. support for OpenGL object reference counting
* 2. support for OpenGL deletion statuses
*
***** 1. OpenGL object reference counting *****
*
* WebGL objects such as WebGLTexture's really have two different refcounts:
* the XPCOM refcount, that is directly exposed to JavaScript, and the OpenGL
* refcount.
*
* For example, when in JavaScript one does: var newname = existingTexture;
* that increments the XPCOM refcount, but doesn't affect the OpenGL refcount.
* When one attaches the texture to a framebuffer object, that does increment
* its OpenGL refcount (and also its XPCOM refcount, to prevent the regular
* XPCOM refcounting mechanism from destroying objects prematurely).
*
* The actual OpenGL refcount is opaque to us (it's internal to the OpenGL
* implementation) but is affects the WebGL semantics that we have to implement:
* for example, a WebGLTexture that is attached to a WebGLFramebuffer must not
* be actually deleted, even if deleteTexture has been called on it, and even
* if JavaScript doesn't have references to it anymore. We can't just rely on
* OpenGL to keep alive the underlying OpenGL texture for us, for a variety of
* reasons, most importantly: we'd need to know when OpenGL objects are actually
* deleted, and OpenGL doesn't notify us about that, so we would have to query
* status very often with glIsXxx calls which isn't practical.
*
* This means that we have to keep track of the OpenGL refcount ourselves,
* in addition to the XPCOM refcount.
*
* This class implements such a refcount, see the mWebGLRefCnt
* member. In order to avoid name clashes (with regular XPCOM refcounting)
* in the derived class, we prefix members with 'WebGL', whence the names
* WebGLAddRef, WebGLRelease, etc.
*
* In practice, WebGLAddRef and WebGLRelease are only called from the
* WebGLRefPtr class.
*
***** 2. OpenGL deletion statuses *****
*
* In OpenGL, an object can go through 3 different deletion statuses during its
* lifetime, which correspond to the 3 enum values for DeletionStatus in this class:
* - the Default status, which it has from its creation to when the
* suitable glDeleteXxx function is called on it;
* - the DeleteRequested status, which is has from when the suitable glDeleteXxx
* function is called on it to when it is no longer referenced by other OpenGL
* objects. For example, a texture that is attached to a non-current FBO
* will enter that status when glDeleteTexture is called on it. For objects
* with that status, GL_DELETE_STATUS queries return true, but glIsXxx
* functions still return true.
* - the Deleted status, which is the status of objects on which the
* suitable glDeleteXxx function has been called, and that are not referenced
* by other OpenGL objects.
*
* This state is stored in the mDeletionStatus member of this class.
*
* When the GL refcount hits zero, if the status is DeleteRequested then we call
* the Delete() method on the derived class and the status becomes Deleted. This is
* what the MaybeDelete() function does.
*
* The DeleteOnce() function implemented here is a helper to ensure that we don't
* call Delete() twice on the same object. Since the derived class' destructor
* needs to call DeleteOnce() which calls Delete(), we can't allow either to be
* virtual. Strictly speaking, we could let them be virtual if the derived class
* were final, but that would be impossible to enforce and would lead to strange
* bugs if it were subclassed.
*
* This WebGLRefCountedObject class takes the Derived type
* as template parameter, as a means to allow DeleteOnce to call Delete()
* on the Derived class, without either method being virtual. This is a common
* C++ pattern known as the "curiously recursive template pattern (CRTP)".
*/
template<typename Derived>
class WebGLRefCountedObject
{
public:
enum DeletionStatus { Default, DeleteRequested, Deleted };
WebGLRefCountedObject()
: mDeletionStatus(Default)
{ }
~WebGLRefCountedObject() {
NS_ABORT_IF_FALSE(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
NS_ABORT_IF_FALSE(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
}
// called by WebGLRefPtr
void WebGLAddRef() {
++mWebGLRefCnt;
}
// called by WebGLRefPtr
void WebGLRelease() {
NS_ABORT_IF_FALSE(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
--mWebGLRefCnt;
MaybeDelete();
}
// this is the function that WebGL.deleteXxx() functions want to call
void RequestDelete() {
if (mDeletionStatus == Default)
mDeletionStatus = DeleteRequested;
MaybeDelete();
}
bool IsDeleted() const {
return mDeletionStatus == Deleted;
}
bool IsDeleteRequested() const {
return mDeletionStatus != Default;
}
void DeleteOnce() {
if (mDeletionStatus != Deleted) {
static_cast<Derived*>(this)->Delete();
mDeletionStatus = Deleted;
}
}
private:
void MaybeDelete() {
if (mWebGLRefCnt == 0 &&
mDeletionStatus == DeleteRequested)
{
DeleteOnce();
}
}
protected:
nsAutoRefCnt mWebGLRefCnt;
DeletionStatus mDeletionStatus;
};
/* This WebGLRefPtr class is meant to be used for references between WebGL objects.
* For example, a WebGLProgram holds WebGLRefPtr's to the WebGLShader's attached
* to it.
*
* Why the need for a separate refptr class? The only special thing that WebGLRefPtr
* does is that it increments and decrements the WebGL refcount of
* WebGLRefCountedObject's, in addition to incrementing and decrementing the
* usual XPCOM refcount.
*
* This means that by using a WebGLRefPtr instead of a nsRefPtr, you ensure that
* the WebGL refcount is incremented, which means that the object will be kept
* alive by this reference even if the matching webgl.deleteXxx() function is
* called on it.
*/
template<typename T>
class WebGLRefPtr
{
public:
WebGLRefPtr()
: mRawPtr(0)
{ }
WebGLRefPtr(const WebGLRefPtr<T>& aSmartPtr)
: mRawPtr(aSmartPtr.mRawPtr)
{
AddRefOnPtr(mRawPtr);
}
WebGLRefPtr(T *aRawPtr)
: mRawPtr(aRawPtr)
{
AddRefOnPtr(mRawPtr);
}
~WebGLRefPtr() {
ReleasePtr(mRawPtr);
}
WebGLRefPtr<T>&
operator=(const WebGLRefPtr<T>& rhs)
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
WebGLRefPtr<T>&
operator=(T* rhs)
{
assign_with_AddRef(rhs);
return *this;
}
T* get() const {
return static_cast<T*>(mRawPtr);
}
operator T*() const {
return get();
}
T* operator->() const {
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL WebGLRefPtr with operator->()!");
return get();
}
T& operator*() const {
NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a NULL WebGLRefPtr with operator*()!");
return *get();
}
private:
static void AddRefOnPtr(T* rawPtr) {
if (rawPtr) {
rawPtr->WebGLAddRef();
rawPtr->AddRef();
}
}
static void ReleasePtr(T* rawPtr) {
if (rawPtr) {
rawPtr->WebGLRelease(); // must be done first before Release(), as Release() might actually destroy the object
rawPtr->Release();
}
}
void assign_with_AddRef(T* rawPtr) {
AddRefOnPtr(rawPtr);
assign_assuming_AddRef(rawPtr);
}
void assign_assuming_AddRef(T* newPtr) {
T* oldPtr = mRawPtr;
mRawPtr = newPtr;
ReleasePtr(oldPtr);
}
protected:
T *mRawPtr;
};
// This class is a mixin for objects that are tied to a specific
// context (which is to say, all of them). They provide initialization
// as well as comparison with the current context.
class WebGLContextBoundObject
{
public:
WebGLContextBoundObject(WebGLContext *context);
bool IsCompatibleWithContext(WebGLContext *other);
WebGLContext *Context() const { return mContext; }
protected:
WebGLContext *mContext;
uint32_t mContextGeneration;
};
}// namespace mozilla
template <typename T>
inline void
ImplCycleCollectionUnlink(mozilla::WebGLRefPtr<T>& aField)
{
aField = nullptr;
}
template <typename T>
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
mozilla::WebGLRefPtr<T>& aField,
const char* aName,
uint32_t aFlags = 0)
{
CycleCollectionNoteEdgeName(aCallback, aName, aFlags);
aCallback.NoteXPCOMChild(aField);
}
#endif

View File

@ -256,6 +256,8 @@ BodyRule::MapRuleInfoInto(nsRuleData* aData)
/* virtual */ void
BodyRule::List(FILE* out, int32_t aIndent) const
{
for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out);
fputs("[body rule] {}\n", out);
}
#endif

View File

@ -81,6 +81,7 @@ MOCHITEST_FILES = \
test_delay_load.html \
test_error_on_404.html \
test_info_leak.html \
test_invalid_reject.html \
test_load.html \
test_load_candidates.html \
test_load_same_resource.html \
@ -246,6 +247,16 @@ MOCHITEST_FILES += \
# Other files
MOCHITEST_FILES += \
bogus.duh \
invalid-m0c0.opus \
invalid-m0c3.opus \
invalid-m1c0.opus \
invalid-m1c9.opus \
invalid-m2c0.opus \
invalid-m2c1.opus \
invalid-cmap-short.opus \
invalid-cmap-s0c0.opus \
invalid-cmap-s0c2.opus \
invalid-cmap-s1c2.opus \
$(NULL)
# These tests contain backend-specific tests. Try to write backend

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -167,6 +167,20 @@ var gSnifferTests = [
{ name:"bogus.duh", type:"bogus/duh" }
];
// Files we must reject as invalid.
var gInvalidTests = [
{ name:"invalid-m0c0.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-m0c3.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-m1c0.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-m1c9.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-m2c0.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-m2c1.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-cmap-short.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-cmap-s0c0.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-cmap-s0c2.opus", type:"audio/ogg; codecs=opus"},
{ name:"invalid-cmap-s1c2.opus", type:"audio/ogg; codecs=opus"},
];
// Converts a path/filename to a file:// URI which we can load from disk.
// Optionally checks whether the file actually exists on disk at the location
// we've specified.

View File

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<title>Test rejection of invalid files</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
var manager = new MediaTestManager;
function startTest(test, token) {
var v = document.createElement('video');
manager.started(token);
// Set up event handlers. Seeing any of these is a failure.
function badEvent(type) { return function(e) {
ok(false, test.name + " should not fire '" + type + "' event");
}};
var events = [
'loadedmetadata', 'load',
'canplay', 'canplaythrough',
'playing'
];
events.forEach( function(e) {
v.addEventListener(e, badEvent(e));
});
// Seeing a decoder error is a success.
v.addEventListener("error", function(e) {
is(v.error.code, v.error.MEDIA_ERR_DECODE,
"decoder should reject " + test.name);
manager.finished(token);
});
// Now try to load and play the file, which should result in the
// error event handler above being called, terminating the test.
document.body.appendChild(v);
v.src = test.name;
v.play();
}
manager.runTests(gInvalidTests, startTest);
</script>
</pre>
</body>
</html>

View File

@ -21,13 +21,11 @@ using namespace mozilla::dom;
/*static*/ nsSMILCSSValueType nsSMILCSSValueType::sSingleton;
struct ValueWrapper {
ValueWrapper(nsCSSProperty aPropID, const nsStyleAnimation::Value& aValue,
nsPresContext* aPresContext) :
mPropID(aPropID), mCSSValue(aValue), mPresContext(aPresContext) {}
ValueWrapper(nsCSSProperty aPropID, const nsStyleAnimation::Value& aValue) :
mPropID(aPropID), mCSSValue(aValue) {}
nsCSSProperty mPropID;
nsStyleAnimation::Value mCSSValue;
nsPresContext* mPresContext;
};
// Helper "zero" values of various types
@ -194,7 +192,6 @@ nsSMILCSSValueType::IsEqual(const nsSMILValue& aLeft,
// Both non-null
NS_WARN_IF_FALSE(leftWrapper != rightWrapper,
"Two nsSMILValues with matching ValueWrapper ptr");
// mPresContext doesn't really matter for equality comparison
return (leftWrapper->mPropID == rightWrapper->mPropID &&
leftWrapper->mCSSValue == rightWrapper->mCSSValue);
}
@ -247,7 +244,7 @@ nsSMILCSSValueType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
// Handle barely-initialized "zero" destination.
if (!destWrapper) {
aDest.mU.mPtr = destWrapper =
new ValueWrapper(property, *destValue, valueToAddWrapper->mPresContext);
new ValueWrapper(property, *destValue);
}
return nsStyleAnimation::Add(property,
@ -311,8 +308,7 @@ nsSMILCSSValueType::Interpolate(const nsSMILValue& aStartVal,
if (nsStyleAnimation::Interpolate(endWrapper->mPropID,
*startCSSValue, *endCSSValue,
aUnitDistance, resultValue)) {
aResult.mU.mPtr = new ValueWrapper(endWrapper->mPropID, resultValue,
endWrapper->mPresContext);
aResult.mU.mPtr = new ValueWrapper(endWrapper->mPropID, resultValue);
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -399,7 +395,7 @@ nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
aString, parsedValue, aIsContextSensitive)) {
sSingleton.Init(aValue);
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext);
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue);
}
}
@ -412,6 +408,6 @@ nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue,
"Unexpected SMIL value type");
const ValueWrapper* wrapper = ExtractValueWrapper(aValue);
return !wrapper ||
nsStyleAnimation::UncomputeValue(wrapper->mPropID, wrapper->mPresContext,
nsStyleAnimation::UncomputeValue(wrapper->mPropID,
wrapper->mCSSValue, aString);
}

View File

@ -258,16 +258,38 @@ let Activities = {
};
let matchFunc = function matchFunc(aResult) {
// Bug 773383: arrays of strings / regexp.
for (let prop in aResult.description.filters) {
if (Array.isArray(aResult.description.filters[prop])) {
if (aResult.description.filters[prop].indexOf(aMsg.options.data[prop]) == -1) {
return false;
function matchFuncValue(aValue, aFilter) {
// Bug 805822 - Regexp support for MozActivity
let values = Array.isArray(aValue) ? aValue : [aValue];
let filters = Array.isArray(aFilter) ? aFilter : [aFilter];
// At least 1 value must match.
let ret = false;
values.forEach(function(value) {
if (filters.indexOf(value) != -1) {
ret = true;
}
} else if (aResult.description.filters[prop] !== aMsg.options.data[prop] ) {
});
return ret;
}
// For any incoming property.
for (let prop in aMsg.options.data) {
// If this is unknown for the app, this app must be excluded.
if (!(prop in aResult.description.filters)) {
return false;
}
// Otherwise, let's check the value against the filter.
if (!matchFuncValue(aMsg.options.data[prop], aResult.description.filters[prop])) {
return false;
}
}
return true;
};

View File

@ -1104,6 +1104,7 @@ this.DOMApplicationRegistry = {
appObject.localId = localId;
appObject.basePath = FileUtils.getDir(DIRECTORY_NAME, ["webapps"], true, true).path;
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
dir.permissions = FileUtils.PERMS_DIRECTORY;
let manFile = dir.clone();
manFile.append(manifestName);
let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
@ -1180,6 +1181,7 @@ this.DOMApplicationRegistry = {
let zipFile = FileUtils.getFile("TmpD", ["webapps", aId, "application.zip"], true);
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
zipFile.moveTo(dir, "application.zip");
zipFile.permissions = FileUtils.PERMS_FILE;
let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
try {
tmpDir.remove(true);

View File

@ -475,13 +475,16 @@ public:
// non-wrapper-cached object using WebIDL bindings. "value" must implement a
// WrapObject() method taking a JSContext and a scope.
template <class T>
inline bool
MOZ_ALWAYS_INLINE bool
WrapNewBindingObject(JSContext* cx, JSObject* scope, T* value, JS::Value* vp)
{
JSObject* obj = value->GetWrapper();
if (obj && js::GetObjectCompartment(obj) == js::GetObjectCompartment(scope)) {
*vp = JS::ObjectValue(*obj);
return true;
JSObject* obj = value->GetWrapperPreserveColor();
if (obj) {
xpc_UnmarkNonNullGrayObject(obj);
if (js::GetObjectCompartment(obj) == js::GetObjectCompartment(scope)) {
*vp = JS::ObjectValue(*obj);
return true;
}
}
if (!obj) {

View File

@ -23,6 +23,7 @@ MOCHITEST_FILES := \
test_Range-extractContents.html.json \
test_Range-intersectsNode.html.json \
test_Range-isPointInRange.html.json \
test_Range-mutations.html.json \
test_Range-set.html.json \
test_interfaces.html.json \
$(NULL)

View File

@ -0,0 +1,12 @@
{
"paras[0].firstChild.splitText(1), with unselected range on paras[0] from 0 to 1": true,
"paras[0].firstChild.splitText(1), with selected range on paras[0] from 0 to 1": true,
"paras[0].firstChild.splitText(1), with unselected range collapsed at (paras[0], 1)": true,
"paras[0].firstChild.splitText(1), with selected range collapsed at (paras[0], 1)": true,
"paras[0].firstChild.splitText(1), with unselected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
"paras[0].firstChild.splitText(1), with selected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
"paras[0].firstChild.splitText(2), with unselected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
"paras[0].firstChild.splitText(2), with selected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
"paras[0].firstChild.splitText(3), with unselected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
"paras[0].firstChild.splitText(3), with selected range from (paras[0].firstChild, 1) to (paras[0], 1)": true
}

View File

@ -32,9 +32,17 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const crashReporter = Cc["@mozilla.org/toolkit/crash-reporter;1"].getService(Ci.nsICrashReporter);
const oldServerPref = Services.prefs.getCharPref("toolkit.crashreporter.pluginHangSubmitURL");
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
const serverPrefName = "toolkit.crashreporter.pluginHangSubmitURL";
var oldServerPref;
try {
oldServerPref = Services.prefs.getCharPref(serverPrefName);
}
catch(e) {
}
const oldTimeoutPref = Services.prefs.getIntPref("dom.ipc.plugins.timeoutSecs");
var testObserver = {
@ -81,7 +89,12 @@ var testObserver = {
env.set("MOZ_CRASHREPORTER_NO_REPORT", "1");
// Finally re-set prefs
Services.prefs.setCharPref("toolkit.crashreporter.pluginHangSubmitURL", oldServerPref);
if (oldServerPref === undefined) {
Services.prefs.clearUserPref(serverPrefName);
}
else {
Services.prefs.setCharPref(serverPrefName, oldServerPref);
}
Services.prefs.setIntPref("dom.ipc.plugins.timeoutSecs", oldTimeoutPref);
SimpleTest.finish();
},

View File

@ -9503,69 +9503,73 @@
< sonofabitch
---
> sonofabitch/!
44371a50184
44346a50159
> spelled
44348a50162
> spelt
44371a50186
> spick/S!
44383c50196
44383c50198
< spik/S
---
> spik/S!
46106a51920
46106a51922
> syllabi
46160c51974
46160c51976
< synch/GMD
---
> synch/GMDS
46167d51980
46167d51982
< synchs
46203,46204c52016,52017
46203,46204c52018,52019
< sysadmin/S
< sysop/S
---
> sysadmin/MS
> sysop/MS
46752a52566
46752a52568
> terabit/MS
46753a52568,52569
46753a52570,52571
> terahertz/M
> terapixel/MS
46817a52634
46817a52636
> testcase/MS
46831a52649
46831a52651
> testsuite/MS
46925a52744
46925a52746
> theremin/MS
47755a53575
47755a53577
> transfect/DSMG
47774a53595,53596
47774a53597,53598
> transgenderism
> transgene/MS
47951c53773
47951c53775
< triage/M
---
> triage/MG
48869a54692
48869a54694
> unlikeable
49211c55034
49211c55036
< vagina/M
---
> vagina/MS
49368,49369c55191
49368,49369c55193
< velour's
< velours's
---
> velour/MS
49478a55301
49478a55303
> vertices
50148a55972
50148a55974
> weaponize/DSG
50260,50261d56083
50260,50261d56085
< werwolf/M
< werwolves
50728c56550
50728c56552
< women
---
> women/M
50794c56616
50794c56618
< wop/S!
---
> wop/MS!

View File

@ -1,4 +1,4 @@
57438
57440
0/nm
0th/pt
1/n1
@ -50500,8 +50500,10 @@ spellbinder/M
spellbound
spellchecker/S
spelldown/SM
spelled
speller/M
spelling/M
spelt
spelunker/MS
spelunking/M
spend/BSRZG

View File

@ -2525,8 +2525,8 @@ RasterImage::InitDecoder(bool aDoSizeDecode)
// If we have all the data we don't want to waste cpu time doing
// a progressive decode
mDecoder = new nsJPEGDecoder(*this, observer,
mHasBeenDecoded ? Decoder::DecodeStyle::SEQUENTIAL :
Decoder::DecodeStyle::PROGRESSIVE);
mHasBeenDecoded ? Decoder::SEQUENTIAL :
Decoder::PROGRESSIVE);
break;
case eDecoderType_bmp:
mDecoder = new nsBMPDecoder(*this, observer);

View File

@ -36,26 +36,11 @@ const size_t ChunkShift = 20;
const size_t ChunkSize = size_t(1) << ChunkShift;
const size_t ChunkMask = ChunkSize - 1;
const size_t CellShift = 3;
const size_t CellSize = size_t(1) << CellShift;
const size_t CellMask = CellSize - 1;
/* These are magic constants derived from actual offsets in gc/Heap.h. */
const size_t ChunkMarkBitmapOffset = 1032376;
const size_t ChunkMarkBitmapBits = 129024;
/*
* Live objects are marked black. How many other additional colors are available
* depends on the size of the GCThing. Objects marked gray are eligible for
* cycle collection.
*/
static const uint32_t BLACK = 0;
static const uint32_t GRAY = 1;
} /* namespace gc */
} /* namespace js */
namespace JS {
namespace shadow {
struct ArenaHeader
@ -63,39 +48,7 @@ struct ArenaHeader
JSCompartment *compartment;
};
struct Compartment
{
bool needsBarrier_;
Compartment() : needsBarrier_(false) {}
};
} /* namespace shadow */
} /* namespace JS */
namespace js {
namespace gc {
static inline uintptr_t *
GetGCThingMarkBitmap(const void *thing)
{
uintptr_t addr = uintptr_t(thing);
addr &= ~js::gc::ChunkMask;
addr |= js::gc::ChunkMarkBitmapOffset;
return reinterpret_cast<uintptr_t *>(addr);
}
static inline void
GetGCThingMarkWordAndMask(const void *thing, uint32_t color,
uintptr_t **wordp, uintptr_t *maskp)
{
uintptr_t addr = uintptr_t(thing);
size_t bit = (addr & js::gc::ChunkMask) / js::gc::CellSize + color;
JS_ASSERT(bit < js::gc::ChunkMarkBitmapBits);
uintptr_t *bitmap = GetGCThingMarkBitmap(thing);
*maskp = uintptr_t(1) << (bit % JS_BITS_PER_WORD);
*wordp = &bitmap[bit / JS_BITS_PER_WORD];
}
static inline shadow::ArenaHeader *
GetGCThingArena(void *thing)
@ -105,16 +58,11 @@ GetGCThingArena(void *thing)
return reinterpret_cast<shadow::ArenaHeader *>(addr);
}
} /* namespace gc */
} /* namespace js */
namespace JS {
static inline JSCompartment *
GetGCThingCompartment(void *thing)
{
JS_ASSERT(thing);
return js::gc::GetGCThingArena(thing)->compartment;
return GetGCThingArena(thing)->compartment;
}
static inline JSCompartment *
@ -123,21 +71,6 @@ GetObjectCompartment(JSObject *obj)
return GetGCThingCompartment(obj);
}
static inline bool
GCThingIsMarkedGray(void *thing)
{
uintptr_t *word, mask;
js::gc::GetGCThingMarkWordAndMask(thing, js::gc::GRAY, &word, &mask);
return *word & mask;
}
static inline bool
IsIncrementalBarrierNeededOnGCThing(void *thing)
{
JSCompartment *comp = GetGCThingCompartment(thing);
return reinterpret_cast<shadow::Compartment *>(comp)->needsBarrier_;
}
} /* namespace JS */
#endif /* js_heap_api_h___ */

View File

@ -12,6 +12,8 @@
#include <string.h>
#include <stdint.h>
using namespace js;
#ifndef TRACE_LOG_DIR
# if defined(_WIN32)
# define TRACE_LOG_DIR ""
@ -20,11 +22,9 @@
# endif
#endif
namespace js {
#if defined(__i386__)
static __inline__ uint64_t
rdtsc(void)
js::rdtsc(void)
{
uint64_t x;
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
@ -32,7 +32,7 @@ rdtsc(void)
}
#elif defined(__x86_64__)
static __inline__ uint64_t
rdtsc(void)
js::rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
@ -40,7 +40,7 @@ rdtsc(void)
}
#elif defined(__powerpc__)
static __inline__ uint64_t
rdtsc(void)
js::rdtsc(void)
{
uint64_t result=0;
uint32_t upper, lower,tmp;
@ -242,19 +242,19 @@ TraceLogging::releaseDefaultLogger()
/* Helper functions for asm calls */
void
TraceLog(TraceLogging* logger, TraceLogging::Type type, JSScript* script)
js::TraceLog(TraceLogging* logger, TraceLogging::Type type, JSScript* script)
{
logger->log(type, script);
}
void
TraceLog(TraceLogging* logger, const char* log)
js::TraceLog(TraceLogging* logger, const char* log)
{
logger->log(log);
}
void
TraceLog(TraceLogging* logger, TraceLogging::Type type)
js::TraceLog(TraceLogging* logger, TraceLogging::Type type)
{
logger->log(type);
}
} /* namespace js */

View File

@ -14,6 +14,7 @@
#include "jsprf.h"
#include "jswrapper.h"
#include "builtin/TestingFunctions.h"
#include "methodjit/MethodJIT.h"
#include "vm/Stack-inl.h"
@ -925,12 +926,8 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FS_HELP_END
};
namespace js {
bool
DefineTestingFunctions(JSContext *cx, HandleObject obj)
js::DefineTestingFunctions(JSContext *cx, HandleObject obj)
{
return JS_DefineFunctionsWithHelp(cx, obj, TestingFunctions);
}
} /* namespace js */

View File

@ -6464,7 +6464,7 @@ Parser::atomNode(ParseNodeKind kind, JSOp op)
// them, so we don't wait for a long time for compression to finish at the
// end of compilation.
const size_t HUGE_STRING = 50000;
if (sct && kind == PNK_STRING && node->pn_atom->length() >= HUGE_STRING)
if (sct && sct->active() && kind == PNK_STRING && node->pn_atom->length() >= HUGE_STRING)
sct->abort();
return node;

View File

@ -34,6 +34,14 @@ struct Arena;
struct ArenaHeader;
struct Chunk;
/*
* Live objects are marked black. How many other additional colors are available
* depends on the size of the GCThing. Objects marked gray are eligible for
* cycle collection.
*/
static const uint32_t BLACK = 0;
static const uint32_t GRAY = 1;
/* The GC allocation kinds. */
enum AllocKind {
FINALIZE_OBJECT0,
@ -77,6 +85,10 @@ static const size_t MAX_BACKGROUND_FINALIZE_KINDS = FINALIZE_LIMIT - FINALIZE_OB
*/
struct Cell
{
static const size_t CellShift = 3;
static const size_t CellSize = size_t(1) << CellShift;
static const size_t CellMask = CellSize - 1;
inline uintptr_t address() const;
inline ArenaHeader *arenaHeader() const;
inline Chunk *chunk() const;
@ -104,7 +116,7 @@ const static uint32_t FreeCommittedArenasThreshold = (32 << 20) / ArenaSize;
* accessing the bitmap. In addition this allows to use some bits for colored
* marking during the cycle GC.
*/
const size_t ArenaCellCount = size_t(1) << (ArenaShift - CellShift);
const size_t ArenaCellCount = size_t(1) << (ArenaShift - Cell::CellShift);
const size_t ArenaBitmapBits = ArenaCellCount;
const size_t ArenaBitmapBytes = ArenaBitmapBits / 8;
const size_t ArenaBitmapWords = ArenaBitmapBits / JS_BITS_PER_WORD;
@ -133,7 +145,7 @@ const size_t ArenaBitmapWords = ArenaBitmapBits / JS_BITS_PER_WORD;
* fully used.
*
* Also only for the last span (|last| & 1)! = 0 as all allocation sizes are
* multiples of CellSize.
* multiples of Cell::CellSize.
*/
struct FreeSpan
{
@ -250,7 +262,7 @@ struct FreeSpan
/* See comments before FreeSpan for details. */
MOZ_ALWAYS_INLINE void *allocate(size_t thingSize) {
JS_ASSERT(thingSize % CellSize == 0);
JS_ASSERT(thingSize % Cell::CellSize == 0);
checkSpan();
uintptr_t thing = first;
if (thing < last) {
@ -271,7 +283,7 @@ struct FreeSpan
/* A version of allocate when we know that the span is not empty. */
MOZ_ALWAYS_INLINE void *infallibleAllocate(size_t thingSize) {
JS_ASSERT(thingSize % CellSize == 0);
JS_ASSERT(thingSize % Cell::CellSize == 0);
checkSpan();
uintptr_t thing = first;
if (thing < last) {
@ -319,7 +331,7 @@ struct FreeSpan
return;
}
size_t spanLength = last - first + 1;
JS_ASSERT(spanLength % CellSize == 0);
JS_ASSERT(spanLength % Cell::CellSize == 0);
/* Start and end must belong to the same arena. */
JS_ASSERT((first & ~ArenaMask) == arenaAddr);
@ -329,7 +341,7 @@ struct FreeSpan
/* The span is not the last and we have more spans to follow. */
JS_ASSERT(first <= last);
size_t spanLengthWithoutOneThing = last - first;
JS_ASSERT(spanLengthWithoutOneThing % CellSize == 0);
JS_ASSERT(spanLengthWithoutOneThing % Cell::CellSize == 0);
JS_ASSERT((first & ~ArenaMask) == arenaAddr);
@ -339,7 +351,7 @@ struct FreeSpan
* storing useless empty span reference.
*/
size_t beforeTail = ArenaSize - (last & ArenaMask);
JS_ASSERT(beforeTail >= sizeof(FreeSpan) + CellSize);
JS_ASSERT(beforeTail >= sizeof(FreeSpan) + Cell::CellSize);
FreeSpan *next = reinterpret_cast<FreeSpan *>(last);
@ -537,7 +549,7 @@ struct Arena
}
static size_t thingsPerArena(size_t thingSize) {
JS_ASSERT(thingSize % CellSize == 0);
JS_ASSERT(thingSize % Cell::CellSize == 0);
/* We should be able to fit FreeSpan in any GC thing. */
JS_ASSERT(thingSize >= sizeof(FreeSpan));
@ -587,14 +599,6 @@ struct ChunkInfo
/* Free arenas are linked together with aheader.next. */
ArenaHeader *freeArenasHead;
#if JS_BITS_PER_WORD == 32
/*
* Calculating sizes and offsets is simpler if sizeof(ChunkInfo) is
* architecture-independent.
*/
char padding[12];
#endif
/*
* Decommitted arenas are tracked by a bitmap in the chunk header. We use
* this offset to start our search iteration close to a decommitted arena
@ -652,10 +656,7 @@ struct ChunkBitmap
uintptr_t bitmap[ArenaBitmapWords * ArenasPerChunk];
MOZ_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color,
uintptr_t **wordp, uintptr_t *maskp)
{
GetGCThingMarkWordAndMask(cell, color, wordp, maskp);
}
uintptr_t **wordp, uintptr_t *maskp);
MOZ_ALWAYS_INLINE bool isMarked(const Cell *cell, uint32_t color) {
uintptr_t *word, mask;
@ -707,7 +708,6 @@ struct ChunkBitmap
};
JS_STATIC_ASSERT(ArenaBitmapBytes * ArenasPerChunk == sizeof(ChunkBitmap));
JS_STATIC_ASSERT(js::gc::ChunkMarkBitmapBits == ArenaBitmapBits * ArenasPerChunk);
typedef BitArray<ArenasPerChunk> PerArenaBitmap;
@ -810,13 +810,12 @@ struct Chunk
};
JS_STATIC_ASSERT(sizeof(Chunk) == ChunkSize);
JS_STATIC_ASSERT(js::gc::ChunkMarkBitmapOffset == offsetof(Chunk, bitmap));
inline uintptr_t
Cell::address() const
{
uintptr_t addr = uintptr_t(this);
JS_ASSERT(addr % CellSize == 0);
JS_ASSERT(addr % Cell::CellSize == 0);
JS_ASSERT(Chunk::withinArenasRange(addr));
return addr;
}
@ -920,12 +919,22 @@ ArenaHeader::unsetAllocDuringSweep()
auxNextLink = 0;
}
JS_ALWAYS_INLINE void
ChunkBitmap::getMarkWordAndMask(const Cell *cell, uint32_t color,
uintptr_t **wordp, uintptr_t *maskp)
{
size_t bit = (cell->address() & ChunkMask) / Cell::CellSize + color;
JS_ASSERT(bit < ArenaBitmapBits * ArenasPerChunk);
*maskp = uintptr_t(1) << (bit % JS_BITS_PER_WORD);
*wordp = &bitmap[bit / JS_BITS_PER_WORD];
}
static void
AssertValidColor(const void *thing, uint32_t color)
{
#ifdef DEBUG
ArenaHeader *aheader = reinterpret_cast<const Cell *>(thing)->arenaHeader();
JS_ASSERT_IF(color, color < aheader->getThingSize() / CellSize);
JS_ASSERT_IF(color, color < aheader->getThingSize() / Cell::CellSize);
#endif
}
@ -941,7 +950,7 @@ Chunk *
Cell::chunk() const
{
uintptr_t addr = uintptr_t(this);
JS_ASSERT(addr % CellSize == 0);
JS_ASSERT(addr % Cell::CellSize == 0);
addr &= ~(ChunkSize - 1);
return reinterpret_cast<Chunk *>(addr);
}

View File

@ -19,6 +19,9 @@
#include "ion/IonCode.h"
#include "vm/String-inl.h"
using namespace js;
using namespace js::gc;
using mozilla::DebugOnly;
void * const js::NullPtr::constNullValue = NULL;
@ -53,9 +56,6 @@ void * const js::NullPtr::constNullValue = NULL;
* scanning functions, but they don't push onto an explicit stack.
*/
namespace js {
namespace gc {
#if JS_HAS_XML_SUPPORT
static inline void
PushMarkStack(GCMarker *gcmarker, JSXML *thing);
@ -79,6 +79,22 @@ PushMarkStack(GCMarker *gcmarker, JSString *thing);
static inline void
PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing);
namespace js {
namespace gc {
static void MarkChildren(JSTracer *trc, JSString *str);
static void MarkChildren(JSTracer *trc, JSScript *script);
static void MarkChildren(JSTracer *trc, Shape *shape);
static void MarkChildren(JSTracer *trc, BaseShape *base);
static void MarkChildren(JSTracer *trc, types::TypeObject *type);
static void MarkChildren(JSTracer *trc, ion::IonCode *code);
#if JS_HAS_XML_SUPPORT
static void MarkChildren(JSTracer *trc, JSXML *xml);
#endif
} /* namespace gc */
} /* namespace js */
/*** Object Marking ***/
template<typename T>
@ -104,7 +120,7 @@ CheckMarkedThing(JSTracer *trc, T *thing)
}
template<typename T>
void
static void
MarkInternal(JSTracer *trc, T **thingp)
{
JS_ASSERT(thingp);
@ -143,6 +159,9 @@ MarkUnbarriered(JSTracer *trc, T **thingp, const char *name)
MarkInternal(trc, thingp);
}
namespace js {
namespace gc {
template <typename T>
static void
Mark(JSTracer *trc, EncapsulatedPtr<T> *thing, const char *name)
@ -151,6 +170,9 @@ Mark(JSTracer *trc, EncapsulatedPtr<T> *thing, const char *name)
MarkInternal(trc, thing->unsafeGet());
}
} /* namespace gc */
} /* namespace js */
template <typename T>
static void
MarkRoot(JSTracer *trc, T **thingp, const char *name)
@ -185,6 +207,9 @@ MarkRootRange(JSTracer *trc, size_t len, T **vec, const char *name)
}
}
namespace js {
namespace gc {
template <typename T>
static bool
IsMarked(T **thingp)
@ -215,22 +240,26 @@ Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name)
MarkUnbarriered<type>(trc, thingp, name); \
} \
\
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *vec, const char *name) \
void \
Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *vec, const char *name) \
{ \
MarkRange<type>(trc, len, vec, name); \
} \
\
void Mark##base##RootRange(JSTracer *trc, size_t len, type **vec, const char *name) \
void \
Mark##base##RootRange(JSTracer *trc, size_t len, type **vec, const char *name) \
{ \
MarkRootRange<type>(trc, len, vec, name); \
} \
\
bool Is##base##Marked(type **thingp) \
bool \
Is##base##Marked(type **thingp) \
{ \
return IsMarked<type>(thingp); \
} \
\
bool Is##base##Marked(EncapsulatedPtr<type> *thingp) \
bool \
Is##base##Marked(EncapsulatedPtr<type> *thingp) \
{ \
return IsMarked<type>(thingp->unsafeGet()); \
}
@ -251,15 +280,18 @@ DeclMarkerImpl(String, JSString)
DeclMarkerImpl(String, JSFlatString)
DeclMarkerImpl(String, JSLinearString)
DeclMarkerImpl(String, PropertyName)
DeclMarkerImpl(TypeObject, types::TypeObject)
DeclMarkerImpl(TypeObject, js::types::TypeObject)
#if JS_HAS_XML_SUPPORT
DeclMarkerImpl(XML, JSXML)
#endif
} /* namespace gc */
} /* namespace js */
/*** Externally Typed Marking ***/
void
MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
gc::MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
{
JS_ASSERT(thingp);
JS_ASSERT(*thingp);
@ -294,7 +326,7 @@ MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
}
}
void
static void
MarkGCThingInternal(JSTracer *trc, void **thingp, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
@ -305,14 +337,14 @@ MarkGCThingInternal(JSTracer *trc, void **thingp, const char *name)
}
void
MarkGCThingRoot(JSTracer *trc, void **thingp, const char *name)
gc::MarkGCThingRoot(JSTracer *trc, void **thingp, const char *name)
{
JS_ROOT_MARKING_ASSERT(trc);
MarkGCThingInternal(trc, thingp, name);
}
void
MarkGCThingUnbarriered(JSTracer *trc, void **thingp, const char *name)
gc::MarkGCThingUnbarriered(JSTracer *trc, void **thingp, const char *name)
{
MarkGCThingInternal(trc, thingp, name);
}
@ -339,14 +371,14 @@ MarkIdInternal(JSTracer *trc, jsid *id)
}
void
MarkId(JSTracer *trc, EncapsulatedId *id, const char *name)
gc::MarkId(JSTracer *trc, EncapsulatedId *id, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkIdInternal(trc, id->unsafeGet());
}
void
MarkIdRoot(JSTracer *trc, jsid *id, const char *name)
gc::MarkIdRoot(JSTracer *trc, jsid *id, const char *name)
{
JS_ROOT_MARKING_ASSERT(trc);
JS_SET_TRACING_NAME(trc, name);
@ -354,14 +386,14 @@ MarkIdRoot(JSTracer *trc, jsid *id, const char *name)
}
void
MarkIdUnbarriered(JSTracer *trc, jsid *id, const char *name)
gc::MarkIdUnbarriered(JSTracer *trc, jsid *id, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkIdInternal(trc, id);
}
void
MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name)
gc::MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name)
{
for (size_t i = 0; i < len; ++i) {
JS_SET_TRACING_INDEX(trc, name, i);
@ -370,7 +402,7 @@ MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name)
}
void
MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
gc::MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
{
JS_ROOT_MARKING_ASSERT(trc);
for (size_t i = 0; i < len; ++i) {
@ -400,14 +432,14 @@ MarkValueInternal(JSTracer *trc, Value *v)
}
void
MarkValue(JSTracer *trc, EncapsulatedValue *v, const char *name)
gc::MarkValue(JSTracer *trc, EncapsulatedValue *v, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkValueInternal(trc, v->unsafeGet());
}
void
MarkValueRoot(JSTracer *trc, Value *v, const char *name)
gc::MarkValueRoot(JSTracer *trc, Value *v, const char *name)
{
JS_ROOT_MARKING_ASSERT(trc);
JS_SET_TRACING_NAME(trc, name);
@ -415,7 +447,7 @@ MarkValueRoot(JSTracer *trc, Value *v, const char *name)
}
void
MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name)
gc::MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name)
{
JS_ROOT_MARKING_ASSERT(trc);
JS_SET_TRACING_NAME(trc, name);
@ -431,7 +463,7 @@ MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name)
}
void
MarkValueRange(JSTracer *trc, size_t len, EncapsulatedValue *vec, const char *name)
gc::MarkValueRange(JSTracer *trc, size_t len, EncapsulatedValue *vec, const char *name)
{
for (size_t i = 0; i < len; ++i) {
JS_SET_TRACING_INDEX(trc, name, i);
@ -440,7 +472,7 @@ MarkValueRange(JSTracer *trc, size_t len, EncapsulatedValue *vec, const char *na
}
void
MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name)
gc::MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name)
{
JS_ROOT_MARKING_ASSERT(trc);
for (size_t i = 0; i < len; ++i) {
@ -450,7 +482,7 @@ MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name)
}
bool
IsValueMarked(Value *v)
gc::IsValueMarked(Value *v)
{
JS_ASSERT(v->isMarkable());
bool rv;
@ -469,14 +501,14 @@ IsValueMarked(Value *v)
/*** Slot Marking ***/
void
MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
gc::MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkValueInternal(trc, s->unsafeGet());
}
void
MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
gc::MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
{
for (size_t i = 0; i < len; ++i) {
JS_SET_TRACING_INDEX(trc, name, i);
@ -485,7 +517,7 @@ MarkArraySlots(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
}
void
MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots)
gc::MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots)
{
JS_ASSERT(obj->isNative());
for (uint32_t i = start; i < (start + nslots); ++i) {
@ -495,7 +527,7 @@ MarkObjectSlots(JSTracer *trc, JSObject *obj, uint32_t start, uint32_t nslots)
}
void
MarkCrossCompartmentObjectUnbarriered(JSTracer *trc, JSObject **obj, const char *name)
gc::MarkCrossCompartmentObjectUnbarriered(JSTracer *trc, JSObject **obj, const char *name)
{
if (IS_GC_MARKING_TRACER(trc) && !(*obj)->compartment()->isCollecting())
return;
@ -504,7 +536,7 @@ MarkCrossCompartmentObjectUnbarriered(JSTracer *trc, JSObject **obj, const char
}
void
MarkCrossCompartmentScriptUnbarriered(JSTracer *trc, JSScript **script, const char *name)
gc::MarkCrossCompartmentScriptUnbarriered(JSTracer *trc, JSScript **script, const char *name)
{
if (IS_GC_MARKING_TRACER(trc) && !(*script)->compartment()->isCollecting())
return;
@ -513,7 +545,7 @@ MarkCrossCompartmentScriptUnbarriered(JSTracer *trc, JSScript **script, const ch
}
void
MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
gc::MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
{
if (s->isMarkable()) {
Cell *cell = (Cell *)s->toGCThing();
@ -527,21 +559,21 @@ MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
/*** Special Marking ***/
void
MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name)
gc::MarkObject(JSTracer *trc, HeapPtr<GlobalObject, JSScript *> *thingp, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkInternal(trc, thingp->unsafeGet());
}
void
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
gc::MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkValueInternal(trc, v);
}
bool
IsCellMarked(Cell **thingp)
gc::IsCellMarked(Cell **thingp)
{
return IsMarked<Cell>(thingp);
}
@ -593,9 +625,6 @@ PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing)
gcmarker->pushType(thing);
}
static void
MarkChildren(JSTracer *trc, JSScript *script);
static void
PushMarkStack(GCMarker *gcmarker, JSScript *thing)
{
@ -623,7 +652,7 @@ PushMarkStack(GCMarker *gcmarker, Shape *thing)
ScanShape(gcmarker, thing);
}
void
static void
PushMarkStack(GCMarker *gcmarker, ion::IonCode *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -789,13 +818,13 @@ PushMarkStack(GCMarker *gcmarker, JSString *str)
}
void
MarkChildren(JSTracer *trc, JSObject *obj)
gc::MarkChildren(JSTracer *trc, JSObject *obj)
{
obj->markChildren(trc);
}
static void
MarkChildren(JSTracer *trc, JSString *str)
gc::MarkChildren(JSTracer *trc, JSString *str)
{
if (str->hasBase())
str->markBase(trc);
@ -804,19 +833,19 @@ MarkChildren(JSTracer *trc, JSString *str)
}
static void
MarkChildren(JSTracer *trc, JSScript *script)
gc::MarkChildren(JSTracer *trc, JSScript *script)
{
script->markChildren(trc);
}
static void
MarkChildren(JSTracer *trc, Shape *shape)
gc::MarkChildren(JSTracer *trc, Shape *shape)
{
shape->markChildren(trc);
}
static void
MarkChildren(JSTracer *trc, BaseShape *base)
gc::MarkChildren(JSTracer *trc, BaseShape *base)
{
base->markChildren(trc);
}
@ -829,7 +858,7 @@ MarkChildren(JSTracer *trc, BaseShape *base)
* marked only if it isn't the same as prevParent, which will be
* updated to the current shape's parent.
*/
inline void
static inline void
MarkCycleCollectorChildren(JSTracer *trc, BaseShape *base, JSObject **prevParent)
{
JS_ASSERT(base);
@ -870,7 +899,7 @@ MarkCycleCollectorChildren(JSTracer *trc, BaseShape *base, JSObject **prevParent
* parent pointer will only be marked once.
*/
void
MarkCycleCollectorChildren(JSTracer *trc, Shape *shape)
gc::MarkCycleCollectorChildren(JSTracer *trc, Shape *shape)
{
JSObject *prevParent = NULL;
do {
@ -909,7 +938,7 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
}
static void
MarkChildren(JSTracer *trc, types::TypeObject *type)
gc::MarkChildren(JSTracer *trc, types::TypeObject *type)
{
unsigned count = type->getPropertyCount();
for (unsigned i = 0; i < count; i++) {
@ -933,8 +962,8 @@ MarkChildren(JSTracer *trc, types::TypeObject *type)
MarkObject(trc, &type->interpretedFunction, "type_function");
}
void
MarkChildren(JSTracer *trc, ion::IonCode *code)
static void
gc::MarkChildren(JSTracer *trc, ion::IonCode *code)
{
#ifdef JS_ION
code->trace(trc);
@ -943,14 +972,14 @@ MarkChildren(JSTracer *trc, ion::IonCode *code)
#if JS_HAS_XML_SUPPORT
static void
MarkChildren(JSTracer *trc, JSXML *xml)
gc::MarkChildren(JSTracer *trc, JSXML *xml)
{
js_TraceXML(trc, xml);
}
#endif
template<typename T>
void
static void
PushArenaTyped(GCMarker *gcmarker, ArenaHeader *aheader)
{
for (CellIterUnderGC i(aheader); !i.done(); i.next())
@ -958,7 +987,7 @@ PushArenaTyped(GCMarker *gcmarker, ArenaHeader *aheader)
}
void
PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
gc::PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
{
switch (MapAllocToTraceKind(aheader->getAllocKind())) {
case JSTRACE_OBJECT:
@ -997,10 +1026,6 @@ PushArena(GCMarker *gcmarker, ArenaHeader *aheader)
}
}
} /* namespace gc */
using namespace js::gc;
struct SlotArrayLayout
{
union {
@ -1118,7 +1143,7 @@ GCMarker::processMarkStackOther(SliceBudget &budget, uintptr_t tag, uintptr_t ad
if (tag == TypeTag) {
ScanTypeObject(this, reinterpret_cast<types::TypeObject *>(addr));
} else if (tag == SavedValueArrayTag) {
JS_ASSERT(!(addr & CellMask));
JS_ASSERT(!(addr & Cell::CellMask));
JSObject *obj = reinterpret_cast<JSObject *>(addr);
HeapValue *vp, *end;
if (restoreValueArray(obj, (void **)&vp, (void **)&end))
@ -1183,7 +1208,7 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
if (tag == ValueArrayTag) {
JS_STATIC_ASSERT(ValueArrayTag == 0);
JS_ASSERT(!(addr & CellMask));
JS_ASSERT(!(addr & Cell::CellMask));
obj = reinterpret_cast<JSObject *>(addr);
uintptr_t addr2 = stack.pop();
uintptr_t addr3 = stack.pop();
@ -1325,7 +1350,7 @@ GCMarker::drainMarkStack(SliceBudget &budget)
}
void
TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
js::TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
{
switch (kind) {
case JSTRACE_OBJECT:
@ -1365,12 +1390,10 @@ TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
}
void
CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind)
js::CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind)
{
JS_ASSERT(thing);
void *tmp = thing;
MarkKind(trc, &tmp, kind);
JS_ASSERT(tmp == thing);
}
} /* namespace js */

View File

@ -7,17 +7,16 @@
#include "mozilla/Assertions.h"
#include "jstypes.h"
#include "jsapi.h"
#include "js/HeapAPI.h"
#include "js/Utility.h"
#include "gc/Memory.h"
namespace js {
namespace gc {
using namespace js;
using namespace js::gc;
/* Unused memory decommiting requires the arena size match the page size. */
extern const size_t PageSize;
extern const size_t ArenaSize;
static bool
DecommitEnabled()
{
@ -31,7 +30,7 @@ DecommitEnabled()
static size_t AllocationGranularity = 0;
void
InitMemorySubsystem()
gc::InitMemorySubsystem()
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
@ -43,7 +42,7 @@ InitMemorySubsystem()
}
void *
MapAlignedPages(size_t size, size_t alignment)
gc::MapAlignedPages(size_t size, size_t alignment)
{
JS_ASSERT(size >= alignment);
JS_ASSERT(size % alignment == 0);
@ -86,13 +85,13 @@ MapAlignedPages(size_t size, size_t alignment)
}
void
UnmapPages(void *p, size_t size)
gc::UnmapPages(void *p, size_t size)
{
JS_ALWAYS_TRUE(VirtualFree(p, 0, MEM_RELEASE));
}
bool
MarkPagesUnused(void *p, size_t size)
gc::MarkPagesUnused(void *p, size_t size)
{
if (!DecommitEnabled())
return false;
@ -103,14 +102,14 @@ MarkPagesUnused(void *p, size_t size)
}
bool
MarkPagesInUse(void *p, size_t size)
gc::MarkPagesInUse(void *p, size_t size)
{
JS_ASSERT(uintptr_t(p) % PageSize == 0);
return true;
}
size_t
GetPageFaultCount()
gc::GetPageFaultCount()
{
PROCESS_MEMORY_COUNTERS pmc;
if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)))
@ -127,12 +126,12 @@ GetPageFaultCount()
#define OS2_MAX_RECURSIONS 16
void
InitMemorySubsystem()
gc::InitMemorySubsystem()
{
}
void
UnmapPages(void *addr, size_t size)
gc::UnmapPages(void *addr, size_t size)
{
if (!DosFreeMem(addr))
return;
@ -153,7 +152,7 @@ UnmapPages(void *addr, size_t size)
}
static void *
MapAlignedPagesRecursively(size_t size, size_t alignment, int& recursions)
gc::MapAlignedPagesRecursively(size_t size, size_t alignment, int& recursions)
{
if (++recursions >= OS2_MAX_RECURSIONS)
return NULL;
@ -194,7 +193,7 @@ MapAlignedPagesRecursively(size_t size, size_t alignment, int& recursions)
}
void *
MapAlignedPages(size_t size, size_t alignment)
gc::MapAlignedPages(size_t size, size_t alignment)
{
JS_ASSERT(size >= alignment);
JS_ASSERT(size % alignment == 0);
@ -230,21 +229,21 @@ MapAlignedPages(size_t size, size_t alignment)
}
bool
MarkPagesUnused(void *p, size_t size)
gc::MarkPagesUnused(void *p, size_t size)
{
JS_ASSERT(uintptr_t(p) % PageSize == 0);
return true;
}
bool
MarkPagesInUse(void *p, size_t size)
gc::MarkPagesInUse(void *p, size_t size)
{
JS_ASSERT(uintptr_t(p) % PageSize == 0);
return true;
}
size_t
GetPageFaultCount()
gc::GetPageFaultCount()
{
return 0;
}
@ -259,12 +258,12 @@ GetPageFaultCount()
#endif
void
InitMemorySubsystem()
gc::InitMemorySubsystem()
{
}
void *
MapAlignedPages(size_t size, size_t alignment)
gc::MapAlignedPages(size_t size, size_t alignment)
{
JS_ASSERT(size >= alignment);
JS_ASSERT(size % alignment == 0);
@ -281,27 +280,27 @@ MapAlignedPages(size_t size, size_t alignment)
}
void
UnmapPages(void *p, size_t size)
gc::UnmapPages(void *p, size_t size)
{
JS_ALWAYS_TRUE(0 == munmap((caddr_t)p, size));
}
bool
MarkPagesUnused(void *p, size_t size)
gc::MarkPagesUnused(void *p, size_t size)
{
JS_ASSERT(uintptr_t(p) % PageSize == 0);
return true;
}
bool
MarkPagesInUse(void *p, size_t size)
gc::MarkPagesInUse(void *p, size_t size)
{
JS_ASSERT(uintptr_t(p) % PageSize == 0);
return true;
}
size_t
GetPageFaultCount()
gc::GetPageFaultCount()
{
return 0;
}
@ -314,7 +313,7 @@ GetPageFaultCount()
#include <unistd.h>
void
InitMemorySubsystem()
gc::InitMemorySubsystem()
{
if (size_t(sysconf(_SC_PAGESIZE)) != PageSize) {
fprintf(stderr,"SpiderMonkey compiled with incorrect page size; please update js/public/HeapAPI.h.\n");
@ -323,7 +322,7 @@ InitMemorySubsystem()
}
void *
MapAlignedPages(size_t size, size_t alignment)
gc::MapAlignedPages(size_t size, size_t alignment)
{
JS_ASSERT(size >= alignment);
JS_ASSERT(size % alignment == 0);
@ -360,13 +359,13 @@ MapAlignedPages(size_t size, size_t alignment)
}
void
UnmapPages(void *p, size_t size)
gc::UnmapPages(void *p, size_t size)
{
JS_ALWAYS_TRUE(0 == munmap(p, size));
}
bool
MarkPagesUnused(void *p, size_t size)
gc::MarkPagesUnused(void *p, size_t size)
{
if (!DecommitEnabled())
return false;
@ -377,14 +376,14 @@ MarkPagesUnused(void *p, size_t size)
}
bool
MarkPagesInUse(void *p, size_t size)
gc::MarkPagesInUse(void *p, size_t size)
{
JS_ASSERT(uintptr_t(p) % PageSize == 0);
return true;
}
size_t
GetPageFaultCount()
gc::GetPageFaultCount()
{
struct rusage usage;
int err = getrusage(RUSAGE_SELF, &usage);
@ -396,6 +395,3 @@ GetPageFaultCount()
#else
#error "Memory mapping functions are not defined for your OS."
#endif
} /* namespace gc */
} /* namespace js */

View File

@ -22,13 +22,13 @@
#include "gc/Barrier-inl.h"
namespace js {
namespace gcstats {
using namespace js;
using namespace js::gcstats;
/* Except for the first and last, slices of less than 42ms are not reported. */
static const int64_t SLICE_MIN_REPORT_TIME = 42 * PRMJ_USEC_PER_MSEC;
class StatisticsSerializer
class gcstats::StatisticsSerializer
{
typedef Vector<char, 128, SystemAllocPolicy> CharBuffer;
CharBuffer buf_;
@ -682,6 +682,3 @@ Statistics::computeMMU(int64_t window)
return double(window - gcMax) / window;
}
} /* namespace gcstats */
} /* namespace js */

View File

@ -13,8 +13,7 @@
#include "gc/StoreBuffer.h"
#include "vm/ObjectImpl-inl.h"
namespace js {
namespace gc {
using namespace js::gc;
/*** MonoTypeBuffer ***/
@ -265,7 +264,4 @@ template class StoreBuffer::MonoTypeBuffer<StoreBuffer::SlotEdge>;
template class StoreBuffer::RelocatableMonoTypeBuffer<StoreBuffer::ValueEdge>;
template class StoreBuffer::RelocatableMonoTypeBuffer<StoreBuffer::CellPtrEdge>;
} /* namespace gc */
} /* namespace js */
#endif /* JSGC_GENERATIONAL */

View File

@ -50,7 +50,7 @@ using namespace js::ion;
IonOptions ion::js_IonOptions;
// Assert that IonCode is gc::Cell aligned.
JS_STATIC_ASSERT(sizeof(IonCode) % gc::CellSize == 0);
JS_STATIC_ASSERT(sizeof(IonCode) % gc::Cell::CellSize == 0);
#ifdef JS_THREADSAFE
static bool IonTLSInitialized = false;

View File

@ -470,6 +470,29 @@ NextInstructionHasFixedUses(LBlock *block, LInstruction *ins)
}
return false;
}
// Returns true iff ins has a def/temp reusing the input allocation.
static bool
IsInputReused(LInstruction *ins, LUse *use)
{
for (size_t i = 0; i < ins->numDefs(); i++) {
if (ins->getDef(i)->policy() == LDefinition::MUST_REUSE_INPUT &&
ins->getOperand(ins->getDef(i)->getReusedInput())->toUse() == use)
{
return true;
}
}
for (size_t i = 0; i < ins->numTemps(); i++) {
if (ins->getTemp(i)->policy() == LDefinition::MUST_REUSE_INPUT &&
ins->getOperand(ins->getTemp(i)->getReusedInput())->toUse() == use)
{
return true;
}
}
return false;
}
#endif
/*
@ -618,6 +641,9 @@ LinearScanAllocator::buildLivenessInfo()
}
}
DebugOnly<bool> hasUseRegister = false;
DebugOnly<bool> hasUseRegisterAtStart = false;
for (LInstruction::InputIterator alloc(**ins); alloc.more(); alloc.next()) {
if (alloc->isUse()) {
LUse *use = alloc->toUse();
@ -637,6 +663,20 @@ LinearScanAllocator::buildLivenessInfo()
for (size_t i = 0; i < ins->numTemps(); i++)
JS_ASSERT(vregs[ins->getTemp(i)].isDouble() != vregs[use].isDouble());
}
// If there are both useRegisterAtStart(x) and useRegister(y)
// uses, we may assign the same register to both operands due to
// interval splitting (bug 772830). Don't allow this for now.
if (use->policy() == LUse::REGISTER) {
if (use->usedAtStart()) {
if (!IsInputReused(*ins, use))
hasUseRegisterAtStart = true;
} else {
hasUseRegister = true;
}
}
JS_ASSERT(!(hasUseRegister && hasUseRegisterAtStart));
#endif
CodePosition to;

View File

@ -8,7 +8,7 @@
#include "jsalloc.h"
#include "jscntxt.h"
namespace js {
using namespace js;
void *
TempAllocPolicy::onOutOfMemory(void *p, size_t nbytes)
@ -21,5 +21,3 @@ TempAllocPolicy::reportAllocOverflow() const
{
js_ReportAllocationOverflow(cx);
}
} /* namespace js */

View File

@ -13,9 +13,8 @@
#include "jsobjinlines.h"
using mozilla::DebugOnly;
namespace js {
namespace analyze {
using namespace js;
using namespace js::analyze;
/////////////////////////////////////////////////////////////////////
// Bytecode
@ -23,7 +22,7 @@ namespace analyze {
#ifdef DEBUG
void
PrintBytecode(JSContext *cx, JSScript *scriptArg, jsbytecode *pc)
analyze::PrintBytecode(JSContext *cx, JSScript *scriptArg, jsbytecode *pc)
{
RootedScript script(cx, scriptArg);
@ -36,7 +35,7 @@ PrintBytecode(JSContext *cx, JSScript *scriptArg, jsbytecode *pc)
}
#endif
inline bool
static inline bool
IsJumpOpcode(JSOp op)
{
uint32_t type = JOF_TYPE(js_CodeSpec[op].format);
@ -2129,6 +2128,3 @@ ScriptAnalysis::assertMatchingDebugMode()
}
#endif /* DEBUG */
} /* namespace analyze */
} /* namespace js */

View File

@ -57,6 +57,7 @@ CPPSRCS = \
testScriptInfo.cpp \
testScriptObject.cpp \
testSetProperty.cpp \
testSourcePolicy.cpp \
testStringBuffer.cpp \
testTrap.cpp \
testTypedArrays.cpp \

View File

@ -0,0 +1,23 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tests.h"
BEGIN_TEST(testBug795104)
{
JS::CompileOptions opts(cx);
opts.setSourcePolicy(JS::CompileOptions::NO_SOURCE);
const size_t strLen = 60002;
char *s = static_cast<char *>(JS_malloc(cx, strLen));
CHECK(s);
s[0] = '"';
memset(s + 1, 'x', strLen - 2);
s[strLen - 1] = '"';
CHECK(JS::Evaluate(cx, global, opts, s, strLen, NULL));
CHECK(JS::CompileFunction(cx, global, opts, "f", 0, NULL, s, strLen));
JS_free(cx, s);
return true;
}
END_TEST(testBug795104)

View File

@ -680,49 +680,43 @@ static JSBool js_NewRuntimeWasCalled = JS_FALSE;
/*
* Thread Local Storage slot for storing the runtime for a thread.
*/
namespace js {
mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
}
namespace JS {
mozilla::ThreadLocal<PerThreadData *> js::TlsPerThreadData;
#ifdef DEBUG
JS_FRIEND_API(void)
EnterAssertNoGCScope()
JS::EnterAssertNoGCScope()
{
++TlsPerThreadData.get()->gcAssertNoGCDepth;
}
JS_FRIEND_API(void)
LeaveAssertNoGCScope()
JS::LeaveAssertNoGCScope()
{
--TlsPerThreadData.get()->gcAssertNoGCDepth;
JS_ASSERT(TlsPerThreadData.get()->gcAssertNoGCDepth >= 0);
}
JS_FRIEND_API(bool)
InNoGCScope()
JS::InNoGCScope()
{
return TlsPerThreadData.get()->gcAssertNoGCDepth > 0;
}
JS_FRIEND_API(bool)
NeedRelaxedRootChecks()
JS::NeedRelaxedRootChecks()
{
return TlsPerThreadData.get()->gcRelaxRootChecks;
}
#else
JS_FRIEND_API(void) EnterAssertNoGCScope() {}
JS_FRIEND_API(void) LeaveAssertNoGCScope() {}
JS_FRIEND_API(bool) InNoGCScope() { return false; }
JS_FRIEND_API(bool) NeedRelaxedRootChecks() { return false; }
JS_FRIEND_API(void) JS::EnterAssertNoGCScope() {}
JS_FRIEND_API(void) JS::LeaveAssertNoGCScope() {}
JS_FRIEND_API(bool) JS::InNoGCScope() { return false; }
JS_FRIEND_API(bool) JS::NeedRelaxedRootChecks() { return false; }
#endif
} /* namespace JS */
static const JSSecurityCallbacks NullSecurityCallbacks = { };
js::PerThreadData::PerThreadData(JSRuntime *runtime)
PerThreadData::PerThreadData(JSRuntime *runtime)
: runtime_(runtime)
#ifdef DEBUG
, gcRelaxRootChecks(false)
@ -5478,16 +5472,20 @@ JS_CompileFunction(JSContext *cx, JSObject *objArg, const char *name,
}
JS_PUBLIC_API(JSString *)
JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent)
JS_DecompileScript(JSContext *cx, JSScript *scriptArg, const char *name, unsigned indent)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
RootedScript script(cx, scriptArg);
RootedFunction fun(cx, script->function());
if (fun)
return JS_DecompileFunction(cx, fun, indent);
return script->sourceData(cx);
bool haveSource = script->scriptSource()->hasSourceData();
if (!haveSource && !JSScript::loadSource(cx, script, &haveSource))
return NULL;
return haveSource ? script->sourceData(cx) : js_NewStringCopyZ(cx, "[no source]");
}
JS_PUBLIC_API(JSString *)
@ -5766,10 +5764,8 @@ JS_CallFunctionValue(JSContext *cx, JSObject *objArg, jsval fval, unsigned argc,
return Invoke(cx, ObjectOrNullValue(obj), fval, argc, argv, rval);
}
namespace JS {
JS_PUBLIC_API(bool)
Call(JSContext *cx, jsval thisv, jsval fval, unsigned argc, jsval *argv, jsval *rval)
JS::Call(JSContext *cx, jsval thisv, jsval fval, unsigned argc, jsval *argv, jsval *rval)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
@ -5779,8 +5775,6 @@ Call(JSContext *cx, jsval thisv, jsval fval, unsigned argc, jsval *argv, jsval *
return Invoke(cx, thisv, fval, argc, argv, rval);
}
} // namespace JS
JS_PUBLIC_API(JSObject *)
JS_New(JSContext *cx, JSObject *ctorArg, unsigned argc, jsval *argv)
{
@ -7102,8 +7096,6 @@ JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
#endif
}
namespace JS {
AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
: down(cx->runtime->autoGCRooters), tag(tag), stackTop(&cx->runtime->autoGCRooters)
{
@ -7113,7 +7105,7 @@ AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
#ifdef DEBUG
JS_PUBLIC_API(void)
AssertArgumentsAreSane(JSContext *cx, const JS::Value &value)
JS::AssertArgumentsAreSane(JSContext *cx, const JS::Value &value)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
@ -7121,8 +7113,6 @@ AssertArgumentsAreSane(JSContext *cx, const JS::Value &value)
}
#endif /* DEBUG */
} // namespace JS
JS_PUBLIC_API(void *)
JS_EncodeScript(JSContext *cx, JSRawScript scriptArg, uint32_t *lengthp)
{

View File

@ -120,10 +120,8 @@ using mozilla::ArrayLength;
using mozilla::DebugOnly;
using mozilla::PointerRangeSize;
namespace js {
JSBool
GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp)
js::GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp)
{
if (obj->isArray()) {
*lengthp = obj->getArrayLength();
@ -170,7 +168,7 @@ GetLengthProperty(JSContext *cx, HandleObject obj, uint32_t *lengthp)
*
*/
JS_FRIEND_API(bool)
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp)
js::StringIsArrayIndex(JSLinearString *str, uint32_t *indexp)
{
const jschar *s = str->chars();
uint32_t length = str->length();
@ -207,7 +205,7 @@ StringIsArrayIndex(JSLinearString *str, uint32_t *indexp)
}
Shape *
GetDenseArrayShape(JSContext *cx, HandleObject globalObj)
js::GetDenseArrayShape(JSContext *cx, HandleObject globalObj)
{
JS_ASSERT(globalObj);
@ -219,8 +217,6 @@ GetDenseArrayShape(JSContext *cx, HandleObject globalObj)
gc::FINALIZE_OBJECT0);
}
}
bool
JSObject::willBeSparseDenseArray(unsigned requiredCapacity, unsigned newElementsHint)
{
@ -364,8 +360,6 @@ GetElement(JSContext *cx, HandleObject obj, IndexType index, JSBool *hole, Mutab
return DoGetElement(cx, obj, index, hole, vp);
}
namespace js {
static bool
GetElementsSlow(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
{
@ -378,7 +372,7 @@ GetElementsSlow(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
}
bool
GetElements(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
js::GetElements(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
{
if (aobj->isDenseArray() && length <= aobj->getDenseArrayInitializedLength() &&
!js_PrototypeHasIndexedProperties(aobj)) {
@ -402,8 +396,6 @@ GetElements(JSContext *cx, HandleObject aobj, uint32_t length, Value *vp)
return GetElementsSlow(cx, aobj, length, vp);
}
}
/*
* Set the value of the property at the given index to v assuming v is rooted.
*/
@ -984,12 +976,10 @@ array_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, H
return array_defineGeneric(cx, obj, id, value, getter, setter, attrs);
}
namespace js {
/* non-static for direct definition of array elements within the engine */
JSBool
array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
js::array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
{
if (!obj->isDenseArray())
return baseops::DefineElement(cx, obj, index, value, getter, setter, attrs);
@ -1023,8 +1013,6 @@ array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue
return baseops::DefineElement(cx, obj, index, value, getter, setter, attrs);
}
} // namespace js
static JSBool
array_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
@ -1108,12 +1096,10 @@ array_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
return true;
}
namespace js {
/* non-static for direct deletion of array elements within the engine */
JSBool
array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleValue rval, JSBool strict)
js::array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue rval,
JSBool strict)
{
if (!obj->isDenseArray())
return baseops::DeleteElement(cx, obj, index, rval, strict);
@ -1130,8 +1116,6 @@ array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
return true;
}
} // namespace js
static JSBool
array_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleValue rval, JSBool strict)
@ -3615,7 +3599,6 @@ js_InitArrayClass(JSContext *cx, HandleObject obj)
/*
* Array allocation functions.
*/
namespace js {
static inline bool
EnsureNewArrayElements(JSContext *cx, JSObject *obj, uint32_t length)
@ -3692,19 +3675,19 @@ NewArray(JSContext *cx, uint32_t length, RawObject protoArg)
}
JSObject * JS_FASTCALL
NewDenseEmptyArray(JSContext *cx, RawObject proto /* = NULL */)
js::NewDenseEmptyArray(JSContext *cx, RawObject proto /* = NULL */)
{
return NewArray<false>(cx, 0, proto);
}
JSObject * JS_FASTCALL
NewDenseAllocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */)
js::NewDenseAllocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */)
{
return NewArray<true>(cx, length, proto);
}
JSObject * JS_FASTCALL
NewDenseUnallocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */)
js::NewDenseUnallocatedArray(JSContext *cx, uint32_t length, RawObject proto /* = NULL */)
{
return NewArray<false>(cx, length, proto);
}
@ -3722,7 +3705,8 @@ mjit::stubs::NewDenseUnallocatedArray(VMFrame &f, uint32_t length)
#endif
JSObject *
NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t elementOffset, RawObject proto /* = NULL */)
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t elementOffset,
RawObject proto /* = NULL */)
{
JSObject* obj = NewArray<true>(cx, length, proto);
if (!obj)
@ -3741,7 +3725,8 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t e
// values must point at already-rooted Value objects
JSObject *
NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, RawObject proto /* = NULL */)
js::NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values,
RawObject proto /* = NULL */)
{
JSObject* obj = NewArray<true>(cx, length, proto);
if (!obj)
@ -3758,7 +3743,7 @@ NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, RawObje
}
JSObject *
NewSlowEmptyArray(JSContext *cx)
js::NewSlowEmptyArray(JSContext *cx)
{
RootedObject obj(cx, NewBuiltinClassInstance(cx, &SlowArrayClass));
if (!obj || !AddLengthProperty(cx, obj))
@ -3768,8 +3753,6 @@ NewSlowEmptyArray(JSContext *cx)
return obj;
}
} // namespace js
#ifdef DEBUG
JSBool
js_ArrayInfo(JSContext *cx, unsigned argc, Value *vp)

View File

@ -371,10 +371,8 @@ js::AtomizeChars(JSContext *cx, const jschar *chars, size_t length, InternBehavi
return AtomizeInline(cx, &chars, length, ib);
}
namespace js {
bool
IndexToIdSlow(JSContext *cx, uint32_t index, jsid *idp)
js::IndexToIdSlow(JSContext *cx, uint32_t index, jsid *idp)
{
JS_ASSERT(index > JSID_INT_MAX);
@ -390,8 +388,6 @@ IndexToIdSlow(JSContext *cx, uint32_t index, jsid *idp)
return true;
}
} /* namespace js */
bool
js::InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval,
jsid *idp, MutableHandleValue vp)

View File

@ -94,6 +94,9 @@ BackfillIndexInCharBuffer(uint32_t index, mozilla::RangedPtr<T> end)
return end;
}
bool
IndexToIdSlow(JSContext *cx, uint32_t index, jsid *idp);
inline bool
IndexToId(JSContext *cx, uint32_t index, jsid *idp)
{
@ -104,7 +107,6 @@ IndexToId(JSContext *cx, uint32_t index, jsid *idp)
return true;
}
extern bool IndexToIdSlow(JSContext *cx, uint32_t index, jsid *idp);
return IndexToIdSlow(cx, index, idp);
}

View File

@ -26,6 +26,7 @@
#include "vm/GlobalObject.h"
#include "vm/StringBuffer.h"
#include "jsboolinlines.h"
#include "jsinferinlines.h"
#include "jsobjinlines.h"
@ -192,17 +193,15 @@ js_BooleanToString(JSContext *cx, JSBool b)
return b ? cx->runtime->atomState.true_ : cx->runtime->atomState.false_;
}
namespace js {
JS_PUBLIC_API(bool)
ToBooleanSlow(const Value &v)
js::ToBooleanSlow(const Value &v)
{
JS_ASSERT(v.isString());
return v.toString()->length() != 0;
}
bool
BooleanGetPrimitiveValueSlow(JSContext *cx, JSObject &obj, Value *vp)
js::BooleanGetPrimitiveValueSlow(JSContext *cx, JSObject &obj, Value *vp)
{
InvokeArgsGuard ag;
if (!cx->stack.pushInvokeArgs(cx, 0, &ag))
@ -214,7 +213,3 @@ BooleanGetPrimitiveValueSlow(JSContext *cx, JSObject &obj, Value *vp)
*vp = ag.rval();
return true;
}
} /* namespace js */

View File

@ -13,6 +13,8 @@
namespace js {
bool BooleanGetPrimitiveValueSlow(JSContext *, JSObject &, Value *);
inline bool
BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp)
{
@ -21,7 +23,6 @@ BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp)
return true;
}
extern bool BooleanGetPrimitiveValueSlow(JSContext *, JSObject &, Value *);
return BooleanGetPrimitiveValueSlow(cx, obj, vp);
}

View File

@ -120,12 +120,10 @@ SwapBytes(uint64_t u)
#endif
}
namespace js {
bool
WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nbytesp,
const JSStructuredCloneCallbacks *cb, void *cbClosure,
jsval transferable)
js::WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nbytesp,
const JSStructuredCloneCallbacks *cb, void *cbClosure,
jsval transferable)
{
SCOutput out(cx);
JSStructuredCloneWriter w(out, cb, cbClosure, transferable);
@ -133,8 +131,8 @@ WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nby
}
bool
ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
const JSStructuredCloneCallbacks *cb, void *cbClosure)
js::ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
const JSStructuredCloneCallbacks *cb, void *cbClosure)
{
SCInput in(cx, data, nbytes);
@ -146,7 +144,7 @@ ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
}
bool
ClearStructuredClone(const uint64_t *data, size_t nbytes)
js::ClearStructuredClone(const uint64_t *data, size_t nbytes)
{
const uint64_t *point = data;
const uint64_t *end = data + nbytes / 8;
@ -171,8 +169,7 @@ ClearStructuredClone(const uint64_t *data, size_t nbytes)
}
bool
StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes,
bool *hasTransferable)
js::StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes, bool *hasTransferable)
{
*hasTransferable = false;
@ -187,8 +184,6 @@ StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes,
return true;
}
} /* namespace js */
static inline uint64_t
PairToUInt64(uint32_t tag, uint32_t data)
{

View File

@ -541,8 +541,6 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode)
js_delete(cx);
}
namespace js {
bool
AutoResolving::alreadyStartedSlow() const
{
@ -556,8 +554,6 @@ AutoResolving::alreadyStartedSlow() const
return false;
}
} /* namespace js */
static void
ReportError(JSContext *cx, const char *message, JSErrorReport *reportp,
JSErrorCallback callback, void *userRef)
@ -754,11 +750,9 @@ js_ReportErrorVA(JSContext *cx, unsigned flags, const char *format, va_list ap)
return warning;
}
namespace js {
/* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
void
ReportUsageError(JSContext *cx, HandleObject callee, const char *msg)
js::ReportUsageError(JSContext *cx, HandleObject callee, const char *msg)
{
const char *usageStr = "usage";
PropertyName *usageAtom = Atomize(cx, usageStr, strlen(usageStr))->asPropertyName();
@ -784,8 +778,8 @@ ReportUsageError(JSContext *cx, HandleObject callee, const char *msg)
}
bool
PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report,
bool reportWarnings)
js::PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report,
bool reportWarnings)
{
if (!report) {
fprintf(file, "%s\n", message);
@ -855,8 +849,6 @@ PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report
return true;
}
} /* namespace js */
/*
* The arguments from ap need to be packaged up into an array and stored
* into the report struct.
@ -1610,8 +1602,6 @@ JSContext::mark(JSTracer *trc)
MarkValueRoot(trc, &iterValue, "iterValue");
}
namespace JS {
#if defined JS_THREADSAFE && defined DEBUG
AutoCheckRequestDepth::AutoCheckRequestDepth(JSContext *cx)
@ -1629,5 +1619,3 @@ AutoCheckRequestDepth::~AutoCheckRequestDepth()
}
#endif
} // namespace JS

View File

@ -385,8 +385,6 @@ CallNativeImpl(JSContext *cx, NativeImpl impl, const CallArgs &args)
return ok;
}
extern JSBool CallOrConstructBoundFunction(JSContext *, unsigned, js::Value *);
STATIC_PRECONDITION(ubound(args.argv_) >= argc)
JS_ALWAYS_INLINE bool
CallJSNativeConstructor(JSContext *cx, Native native, const CallArgs &args)

View File

@ -50,6 +50,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
#ifdef JSGC_GENERATIONAL
gcStoreBuffer(&gcNursery),
#endif
needsBarrier_(false),
ionUsingBarriers_(false),
gcScheduled(false),
gcState(NoGC),

View File

@ -116,7 +116,7 @@ namespace js {
class AutoDebugModeGC;
}
struct JSCompartment : private JS::shadow::Compartment
struct JSCompartment
{
JSRuntime *rt;
JSPrincipals *principals;
@ -156,6 +156,7 @@ struct JSCompartment : private JS::shadow::Compartment
#endif
private:
bool needsBarrier_;
bool ionUsingBarriers_;
public:

View File

@ -12,8 +12,8 @@
#include <time.h>
namespace js {
namespace crash {
using namespace js;
using namespace js::crash;
const static int stack_snapshot_max_size = 32768;
@ -139,6 +139,9 @@ GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffe
#endif
namespace js {
namespace crash {
class Stack : private CrashStack
{
public:
@ -206,6 +209,9 @@ Ring::copyBytes(void *data, size_t size)
}
}
} /* namespace crash */
} /* namespace js */
static bool gInitialized;
static Stack gGCStack(JS_CRASH_STACK_GC);
@ -213,32 +219,26 @@ static Stack gErrorStack(JS_CRASH_STACK_ERROR);
static Ring gRingBuffer(JS_CRASH_RING);
void
SnapshotGCStack()
js::crash::SnapshotGCStack()
{
if (gInitialized)
gGCStack.snapshot();
}
void
SnapshotErrorStack()
js::crash::SnapshotErrorStack()
{
if (gInitialized)
gErrorStack.snapshot();
}
void
SaveCrashData(uint64_t tag, void *ptr, size_t size)
js::crash::SaveCrashData(uint64_t tag, void *ptr, size_t size)
{
if (gInitialized)
gRingBuffer.push(tag, ptr, size);
}
} /* namespace crash */
} /* namespace js */
using namespace js;
using namespace js::crash;
JS_PUBLIC_API(void)
JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback)
{

View File

@ -70,10 +70,8 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug)
rt->debugMode = !!debug;
}
namespace js {
JSTrapStatus
ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
js::ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
{
JS_ASSERT(fp == cx->fp());
@ -106,7 +104,7 @@ ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
}
bool
ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
js::ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
{
JS_ASSERT(fp == cx->fp());
JSBool ok = okArg;
@ -124,8 +122,6 @@ ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
return Debugger::onLeaveFrame(cx, ok);
}
} /* namespace js */
JS_FRIEND_API(JSBool)
JS_SetDebugModeForAllCompartments(JSContext *cx, JSBool debug)
{

View File

@ -875,10 +875,8 @@ js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
return errorString;
}
namespace js {
JS_FRIEND_API(const jschar*)
GetErrorTypeName(JSContext* cx, int16_t exnType)
js::GetErrorTypeName(JSContext* cx, int16_t exnType)
{
/*
* JSEXN_INTERNALERR returns null to prevent that "InternalError: "
@ -893,8 +891,6 @@ GetErrorTypeName(JSContext* cx, int16_t exnType)
return ClassName(key, cx)->chars();
}
} /* namespace js */
#if defined ( DEBUG_mccabe ) && defined ( PRINTNAMES )
/* For use below... get character strings for error name and exception name */
static struct exnname { char *name; char *exception; } errortoexnname[] = {

View File

@ -502,6 +502,7 @@ js::SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback)
* sufficient data has been harvested.
*/
// Defined in jsxml.cpp.
extern size_t sE4XObjectsCreated;
JS_FRIEND_API(size_t)
@ -511,6 +512,7 @@ JS_GetE4XObjectsCreated(JSContext *)
}
namespace js {
// Defined in vm/GlobalObject.cpp.
extern size_t sSetProtoCalled;
}
@ -520,6 +522,7 @@ JS_SetProtoCalled(JSContext *)
return sSetProtoCalled;
}
// Defined in jsiter.cpp.
extern size_t sCustomIteratorCount;
JS_FRIEND_API(size_t)
@ -546,6 +549,13 @@ js::TraceWeakMaps(WeakMapTracer *trc)
WatchpointMap::traceAll(trc);
}
JS_FRIEND_API(bool)
js::GCThingIsMarkedGray(void *thing)
{
JS_ASSERT(thing);
return reinterpret_cast<gc::Cell *>(thing)->isMarked(gc::GRAY);
}
JS_FRIEND_API(JSGCTraceKind)
js::GCThingTraceKind(void *thing)
{
@ -710,29 +720,27 @@ js::DumpHeapComplete(JSRuntime *rt, FILE *fp)
fflush(dtrc.output);
}
namespace js {
JS_FRIEND_API(const JSStructuredCloneCallbacks *)
GetContextStructuredCloneCallbacks(JSContext *cx)
js::GetContextStructuredCloneCallbacks(JSContext *cx)
{
return cx->runtime->structuredCloneCallbacks;
}
JS_FRIEND_API(JSVersion)
VersionSetMoarXML(JSVersion version, bool enable)
js::VersionSetMoarXML(JSVersion version, bool enable)
{
return enable ? JSVersion(uint32_t(version) | VersionFlags::MOAR_XML)
: JSVersion(uint32_t(version) & ~VersionFlags::MOAR_XML);
}
JS_FRIEND_API(bool)
CanCallContextDebugHandler(JSContext *cx)
js::CanCallContextDebugHandler(JSContext *cx)
{
return !!cx->runtime->debugHooks.debuggerHandler;
}
JS_FRIEND_API(JSTrapStatus)
CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval)
js::CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval)
{
if (!cx->runtime->debugHooks.debuggerHandler)
return JSTRAP_RETURN;
@ -743,51 +751,51 @@ CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *
#ifdef JS_THREADSAFE
void *
GetOwnerThread(const JSContext *cx)
js::GetOwnerThread(const JSContext *cx)
{
return cx->runtime->ownerThread();
}
JS_FRIEND_API(bool)
ContextHasOutstandingRequests(const JSContext *cx)
js::ContextHasOutstandingRequests(const JSContext *cx)
{
return cx->outstandingRequests > 0;
}
#endif
JS_FRIEND_API(JSCompartment *)
GetContextCompartment(const JSContext *cx)
js::GetContextCompartment(const JSContext *cx)
{
return cx->compartment;
}
JS_FRIEND_API(bool)
HasUnrootedGlobal(const JSContext *cx)
js::HasUnrootedGlobal(const JSContext *cx)
{
return cx->hasRunOption(JSOPTION_UNROOTED_GLOBAL);
}
JS_FRIEND_API(void)
SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg)
js::SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg)
{
rt->activityCallback = cb;
rt->activityCallbackArg = arg;
}
JS_FRIEND_API(bool)
IsContextRunningJS(JSContext *cx)
js::IsContextRunningJS(JSContext *cx)
{
return !cx->stack.empty();
}
JS_FRIEND_API(const CompartmentVector&)
GetRuntimeCompartments(JSRuntime *rt)
js::GetRuntimeCompartments(JSRuntime *rt)
{
return rt->compartments;
}
JS_FRIEND_API(GCSliceCallback)
SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
js::SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
{
GCSliceCallback old = rt->gcSliceCallback;
rt->gcSliceCallback = callback;
@ -795,7 +803,7 @@ SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
}
JS_FRIEND_API(bool)
WasIncrementalGC(JSRuntime *rt)
js::WasIncrementalGC(JSRuntime *rt)
{
return rt->gcIsIncremental;
}
@ -813,7 +821,7 @@ GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const
}
JS_FRIEND_API(AnalysisPurgeCallback)
SetAnalysisPurgeCallback(JSRuntime *rt, AnalysisPurgeCallback callback)
js::SetAnalysisPurgeCallback(JSRuntime *rt, AnalysisPurgeCallback callback)
{
AnalysisPurgeCallback old = rt->analysisPurgeCallback;
rt->analysisPurgeCallback = callback;
@ -821,7 +829,7 @@ SetAnalysisPurgeCallback(JSRuntime *rt, AnalysisPurgeCallback callback)
}
JS_FRIEND_API(void)
NotifyDidPaint(JSRuntime *rt)
js::NotifyDidPaint(JSRuntime *rt)
{
if (rt->gcZeal() == gc::ZealFrameVerifierPreValue) {
gc::VerifyBarriers(rt, gc::PreBarrierVerifier);
@ -847,38 +855,50 @@ NotifyDidPaint(JSRuntime *rt)
rt->gcInterFrameGC = false;
}
extern JS_FRIEND_API(bool)
IsIncrementalGCEnabled(JSRuntime *rt)
JS_FRIEND_API(bool)
js::IsIncrementalGCEnabled(JSRuntime *rt)
{
return rt->gcIncrementalEnabled && rt->gcMode == JSGC_MODE_INCREMENTAL;
}
JS_FRIEND_API(bool)
IsIncrementalGCInProgress(JSRuntime *rt)
js::IsIncrementalGCInProgress(JSRuntime *rt)
{
return (rt->gcIncrementalState != gc::NO_INCREMENTAL && !rt->gcVerifyPreData);
}
extern JS_FRIEND_API(void)
DisableIncrementalGC(JSRuntime *rt)
JS_FRIEND_API(void)
js::DisableIncrementalGC(JSRuntime *rt)
{
rt->gcIncrementalEnabled = false;
}
JS_FRIEND_API(bool)
IsIncrementalBarrierNeeded(JSRuntime *rt)
js::IsIncrementalBarrierNeeded(JSRuntime *rt)
{
return (rt->gcIncrementalState == gc::MARK && !rt->isHeapBusy());
}
JS_FRIEND_API(bool)
IsIncrementalBarrierNeeded(JSContext *cx)
js::IsIncrementalBarrierNeeded(JSContext *cx)
{
return IsIncrementalBarrierNeeded(cx->runtime);
}
extern JS_FRIEND_API(void)
IncrementalReferenceBarrier(void *ptr)
JS_FRIEND_API(bool)
js::IsIncrementalBarrierNeededOnObject(RawObject obj)
{
return obj->compartment()->needsBarrier();
}
JS_FRIEND_API(bool)
js::IsIncrementalBarrierNeededOnScript(JSScript *script)
{
return script->compartment()->needsBarrier();
}
JS_FRIEND_API(void)
js::IncrementalReferenceBarrier(void *ptr)
{
if (!ptr)
return;
@ -905,20 +925,20 @@ IncrementalReferenceBarrier(void *ptr)
JS_NOT_REACHED("invalid trace kind");
}
extern JS_FRIEND_API(void)
IncrementalValueBarrier(const Value &v)
JS_FRIEND_API(void)
js::IncrementalValueBarrier(const Value &v)
{
HeapValue::writeBarrierPre(v);
}
extern JS_FRIEND_API(void)
PokeGC(JSRuntime *rt)
JS_FRIEND_API(void)
js::PokeGC(JSRuntime *rt)
{
rt->gcPoke = true;
}
JS_FRIEND_API(JSObject *)
GetTestingFunctions(JSContext *cx)
js::GetTestingFunctions(JSContext *cx)
{
RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
if (!obj)
@ -931,32 +951,31 @@ GetTestingFunctions(JSContext *cx)
}
JS_FRIEND_API(void)
SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size,
uint32_t max)
js::SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size, uint32_t max)
{
rt->spsProfiler.setProfilingStack(stack, size, max);
}
JS_FRIEND_API(void)
EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled)
js::EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled)
{
rt->spsProfiler.enable(enabled);
}
JS_FRIEND_API(jsbytecode*)
ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip)
js::ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip)
{
return rt->spsProfiler.ipToPC(script, size_t(ip));
}
JS_FRIEND_API(void)
SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks)
js::SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks)
{
rt->DOMcallbacks = callbacks;
}
JS_FRIEND_API(const DOMCallbacks *)
GetDOMCallbacks(JSRuntime *rt)
js::GetDOMCallbacks(JSRuntime *rt)
{
return rt->DOMcallbacks;
}
@ -965,22 +984,20 @@ static void *gListBaseHandlerFamily = NULL;
static uint32_t gListBaseExpandoSlot = 0;
JS_FRIEND_API(void)
SetListBaseInformation(void *listBaseHandlerFamily, uint32_t listBaseExpandoSlot)
js::SetListBaseInformation(void *listBaseHandlerFamily, uint32_t listBaseExpandoSlot)
{
gListBaseHandlerFamily = listBaseHandlerFamily;
gListBaseExpandoSlot = listBaseExpandoSlot;
}
void *
GetListBaseHandlerFamily()
js::GetListBaseHandlerFamily()
{
return gListBaseHandlerFamily;
}
uint32_t
GetListBaseExpandoSlot()
js::GetListBaseExpandoSlot()
{
return gListBaseExpandoSlot;
}
} // namespace js

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