Merge from mozilla-central.

This commit is contained in:
David Anderson 2012-01-09 11:29:09 -08:00
commit 74673de353
137 changed files with 1703 additions and 1093 deletions

View File

@ -45,7 +45,8 @@ b2g/chrome/Makefile
b2g/components/Makefile
b2g/installer/Makefile
b2g/locales/Makefile
b2g/Makefile"
b2g/Makefile
"
if test -n "$MOZ_UPDATE_PACKAGING"; then
add_makefiles "

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1325216886000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1325894427000">
<emItems>
<emItem blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
@ -139,6 +139,8 @@
<versionRange minVersion="2.0" maxVersion="2.0">
</versionRange>
</emItem>
<emItem blockID="i49" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE63}">
</emItem>
<emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
</emItem>
<emItem blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">

View File

@ -398,6 +398,7 @@ pref("browser.tabs.loadDivertedInBackground", false);
pref("browser.tabs.loadBookmarksInBackground", false);
pref("browser.tabs.tabClipWidth", 140);
pref("browser.tabs.animate", true);
pref("browser.tabs.onTop", true);
pref("browser.tabs.drawInTitlebar", true);
// Where to show tab close buttons:
@ -968,6 +969,7 @@ pref("services.sync.prefs.sync.browser.tabs.closeButtons", true);
pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true);
pref("services.sync.prefs.sync.browser.tabs.warnOnClose", true);
pref("services.sync.prefs.sync.browser.tabs.warnOnOpen", true);
pref("services.sync.prefs.sync.browser.tabs.onTop", true);
pref("services.sync.prefs.sync.browser.urlbar.autocomplete.enabled", true);
pref("services.sync.prefs.sync.browser.urlbar.autoFill", true);
pref("services.sync.prefs.sync.browser.urlbar.default.behavior", true);

View File

@ -1364,7 +1364,7 @@ function BrowserStartup() {
allTabs.readPref();
TabsOnTop.syncCommand();
TabsOnTop.init();
BookmarksMenuButton.init();
@ -3905,7 +3905,8 @@ var FullScreen = {
}
else {
// The user may quit fullscreen during an animation
clearInterval(this._animationInterval);
window.mozCancelAnimationFrame(this._animationHandle);
this._animationHandle = 0;
clearTimeout(this._animationTimeout);
gNavToolbox.style.marginTop = "";
if (this._isChromeCollapsed)
@ -4096,33 +4097,40 @@ var FullScreen = {
// Animate the toolbars disappearing
_shouldAnimate: true,
_isAnimating: false,
_animationTimeout: null,
_animationInterval: null,
_animateUp: function()
{
_animationTimeout: 0,
_animationHandle: 0,
_animateUp: function() {
// check again, the user may have done something before the animation was due to start
if (!window.fullScreen || !FullScreen._safeToCollapse(false)) {
FullScreen._isAnimating = false;
FullScreen._shouldAnimate = true;
if (!window.fullScreen || !this._safeToCollapse(false)) {
this._isAnimating = false;
this._shouldAnimate = true;
return;
}
var animateFrameAmount = 2;
function animateUpFrame() {
animateFrameAmount *= 2;
if (animateFrameAmount >= gNavToolbox.boxObject.height) {
// We've animated enough
clearInterval(FullScreen._animationInterval);
gNavToolbox.style.marginTop = "";
FullScreen._isAnimating = false;
FullScreen._shouldAnimate = false; // Just to make sure
FullScreen.mouseoverToggle(false);
return;
}
gNavToolbox.style.marginTop = (animateFrameAmount * -1) + "px";
this._animateStartTime = window.mozAnimationStartTime;
if (!this._animationHandle)
this._animationHandle = window.mozRequestAnimationFrame(this);
},
sample: function (timeStamp) {
const duration = 1500;
const timePassed = timeStamp - this._animateStartTime;
const pos = timePassed >= duration ? 1 :
1 - Math.pow(1 - timePassed / duration, 4);
if (pos >= 1) {
// We've animated enough
window.mozCancelAnimationFrame(this._animationHandle);
gNavToolbox.style.marginTop = "";
this._animationHandle = 0;
this._isAnimating = false;
this._shouldAnimate = false; // Just to make sure
this.mouseoverToggle(false);
return;
}
FullScreen._animationInterval = setInterval(animateUpFrame, 70);
gNavToolbox.style.marginTop = (gNavToolbox.boxObject.height * pos * -1) + "px";
this._animationHandle = window.mozRequestAnimationFrame(this);
},
cancelWarning: function(event) {
@ -4223,7 +4231,7 @@ var FullScreen = {
if (!aShow && this._shouldAnimate) {
this._isAnimating = true;
this._shouldAnimate = false;
this._animationTimeout = setTimeout(this._animateUp, 800);
this._animationTimeout = setTimeout(this._animateUp.bind(this), 800);
return;
}
@ -5278,27 +5286,44 @@ function setToolbarVisibility(toolbar, isVisible) {
}
var TabsOnTop = {
toggle: function () {
this.enabled = !this.enabled;
init: function TabsOnTop_init() {
this.syncUI();
Services.prefs.addObserver(this._prefName, this, false);
},
syncCommand: function () {
let enabled = this.enabled;
toggle: function () {
this.enabled = !Services.prefs.getBoolPref(this._prefName);
},
syncUI: function () {
let userEnabled = Services.prefs.getBoolPref(this._prefName);
let enabled = userEnabled && gBrowser.tabContainer.visible;
document.getElementById("cmd_ToggleTabsOnTop")
.setAttribute("checked", enabled);
.setAttribute("checked", userEnabled);
document.documentElement.setAttribute("tabsontop", enabled);
document.getElementById("navigator-toolbox").setAttribute("tabsontop", enabled);
document.getElementById("TabsToolbar").setAttribute("tabsontop", enabled);
gBrowser.tabContainer.setAttribute("tabsontop", enabled);
TabsInTitlebar.allowedBy("tabs-on-top", enabled);
},
get enabled () {
return gNavToolbox.getAttribute("tabsontop") == "true";
},
set enabled (val) {
gNavToolbox.setAttribute("tabsontop", !!val);
this.syncCommand();
set enabled (val) {
Services.prefs.setBoolPref(this._prefName, !!val);
return val;
}
},
observe: function (subject, topic, data) {
if (topic == "nsPref:changed")
this.syncUI();
},
_prefName: "browser.tabs.onTop"
}
var TabsInTitlebar = {

View File

@ -444,9 +444,7 @@
<toolbox id="navigator-toolbox"
defaultmode="icons" mode="icons"
iconsize="large"
tabsontop="true"
persist="tabsontop">
iconsize="large">
<!-- Menu -->
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
defaultset="menubar-items"

View File

@ -151,9 +151,6 @@
false
#endif
</field>
<field name="mAddProgressListenerWasCalled">
false
</field>
<field name="_browsers">
null
</field>
@ -1912,11 +1909,6 @@
"608628.");
}
if (!this.mAddProgressListenerWasCalled) {
this.mAddProgressListenerWasCalled = true;
this.tabContainer.updateVisibility();
}
this.mProgressListeners.push(aListener);
]]>
</body>
@ -2770,8 +2762,8 @@
Services.prefs.addObserver("browser.tabs.", this._prefObserver, false);
window.addEventListener("resize", this, false);
if (window.TabsInTitlebar)
TabsInTitlebar.allowedBy("tabs-visible", this.visible);
this.updateVisibility();
this._propagateVisibility();
]]>
</constructor>
@ -2839,17 +2831,30 @@
this._container.collapsed = !val;
document.getElementById("menu_closeWindow").hidden = !val;
document.getElementById("menu_close").setAttribute("label",
this.tabbrowser.mStringBundle.getString(val ? "tabs.closeTab" : "tabs.close"));
if (window.TabsInTitlebar)
TabsInTitlebar.allowedBy("tabs-visible", val);
this._propagateVisibility();
return val;
]]></setter>
</property>
<method name="_propagateVisibility">
<body><![CDATA[
let visible = this.visible;
document.getElementById("menu_closeWindow").hidden = !visible;
document.getElementById("menu_close").setAttribute("label",
this.tabbrowser.mStringBundle.getString(visible ? "tabs.closeTab" : "tabs.close"));
goSetCommandEnabled("cmd_ToggleTabsOnTop", visible);
if (window.TabsOnTop)
TabsOnTop.syncUI();
if (window.TabsInTitlebar)
TabsInTitlebar.allowedBy("tabs-visible", visible);
]]></body>
</method>
<method name="updateVisibility">
<body><![CDATA[
if (this.childNodes.length - this.tabbrowser._removingTabs.length == 1)

View File

@ -88,13 +88,14 @@ endif
# browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
# browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
_BROWSER_FILES = \
browser_typeAheadFind.js \
browser_keywordSearch.js \
browser_allTabsPanel.js \
browser_alltabslistener.js \
browser_bug304198.js \
browser_bug321000.js \
title_test.svg \
browser_bug329212.js \
browser_bug356571.js \

View File

@ -2,7 +2,7 @@
<html>
<head>
<title>Tests for browser context menu</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
@ -28,29 +28,21 @@ function openContextMenuFor(element, shiftkey, shouldWaitForFocus) {
// Context menu should be closed before we open it again.
is(contextMenu.state, "closed", "checking if popup is closed");
//Some elements need time to focus and spellcheck before any tests are
//run on them.
if(shouldWaitForFocus)
{
if (lastElement)
lastElement.blur();
element.focus();
SimpleTest.executeSoon(function() {
lastElement = element;
var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
});
}
else
{
if (lastElement)
lastElement.blur();
element.focus();
if (lastElement)
lastElement.blur();
element.focus();
// Some elements need time to focus and spellcheck before any tests are
// run on them.
function actuallyOpenContextMenuFor() {
lastElement = element;
var eventDetails = { type : "contextmenu", button : 2, shiftKey : shiftkey };
synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
}
if (shouldWaitForFocus)
SimpleTest.executeSoon(actuallyOpenContextMenuFor);
else
actuallyOpenContextMenuFor();
}
function closeContextMenu() {
@ -77,7 +69,7 @@ function invokeItemAction(generatedItemId)
generatedItemId)[0];
ok(item, "Got generated XUL menu item");
item.doCommand();
is(pagemenu.hasAttribute("hopeless"), false, "attribute got removed");
ok(!pagemenu.hasAttribute("hopeless"), "attribute got removed");
}
function getVisibleMenuItems(aMenu, aData) {
@ -178,7 +170,7 @@ function checkContextMenu(expectedItems) {
* ["sub1", true, // submenu contents
* "sub2", false], null, // submenu contents
* "lol", false] // item disabled
*
*
*/
function checkMenu(menu, expectedItems, data) {
var actualItems = getVisibleMenuItems(menu, data);
@ -192,8 +184,12 @@ function checkMenu(menu, expectedItems, data) {
ok(true, "Checking submenu...");
var menuID = expectedItems[i - 2]; // The last item was the menu ID.
var submenu = menu.getElementsByAttribute("id", menuID)[0];
ok(submenu && submenu.nodeName == "menu", "got expected submenu element");
checkMenu(submenu.menupopup, expectedItem, data);
ok(submenu, "got a submenu element of id='" + menuID + "'");
if (submenu) {
is(submenu.nodeName, "menu", "submenu element of id='" + menuID +
"' has expected nodeName");
checkMenu(submenu.menupopup, expectedItem, data);
}
} else {
is(actualItem, expectedItem,
"checking item #" + i/2 + " (" + expectedItem + ") name");
@ -513,7 +509,7 @@ function runTest(testNum) {
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null,
"spell-add-dictionaries", true], null
].concat(inspectItems));
contextMenu.ownerDocument.getElementById("spell-add-to-dictionary").doCommand(); // Add to dictionary
closeContextMenu();
@ -537,7 +533,7 @@ function runTest(testNum) {
"spell-dictionaries", true,
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null,
"spell-add-dictionaries", true], null
].concat(inspectItems));
contextMenu.ownerDocument.getElementById("spell-undo-add-to-dictionary").doCommand(); // Undo add to dictionary
closeContextMenu();
@ -661,6 +657,7 @@ function runTest(testNum) {
"context-viewsource", true,
"context-viewinfo", true
].concat(inspectItems));
closeContextMenu();
subwindow.close();
SimpleTest.finish();
@ -703,6 +700,7 @@ function startTest() {
ok(contextMenu, "Got context menu XUL");
if (chromeWin.document.getElementById("Browser:Stop").getAttribute("disabled") != "true") {
todo(false, "Wait for subwindow to load... (This should usually happen once.)");
SimpleTest.executeSoon(startTest);
return;
}

View File

@ -99,6 +99,8 @@
#include "nsIWindowsRegKey.h"
#include "nsISupportsPrimitives.h"
#define kNotFound -1
#define TRIDENTPROFILE_BUNDLE "chrome://browser/locale/migration/migration.properties"
#define REGISTRY_IE_MAIN_KEY \
@ -602,9 +604,13 @@ nsIEProfileMigrator::TestForIE7()
iePath = destination;
// Check if the path is enclosed in quotation marks.
if (StringBeginsWith(iePath, NS_LITERAL_STRING("\""))) {
iePath.Cut(0,1);
PRUint32 index = iePath.FindChar('\"', 0);
PRInt32 index = iePath.FindChar('\"', 0);
// After removing the opening quoation mark,
// remove the closing one and everything after it.
if (index > 0)
iePath.Cut(index,iePath.Length());
}
@ -621,8 +627,8 @@ nsIEProfileMigrator::TestForIE7()
return false;
if (ieVersion.Length() > 2) {
PRUint32 index = ieVersion.FindChar('.', 0);
if (index < 0)
PRInt32 index = ieVersion.FindChar('.', 0);
if (index == kNotFound)
return false;
ieVersion.Cut(index, ieVersion.Length());
PRInt32 ver = wcstol(ieVersion.get(), nsnull, 0);

View File

@ -1100,7 +1100,7 @@ BrowserGlue.prototype = {
},
_migrateUI: function BG__migrateUI() {
const UI_VERSION = 5;
const UI_VERSION = 6;
const BROWSER_DOCURL = "chrome://browser/content/browser.xul#";
let currentUIVersion = 0;
try {
@ -1222,6 +1222,15 @@ BrowserGlue.prototype = {
}
}
if (currentUIVersion < 6) {
// convert tabsontop attribute to pref
let toolboxResource = this._rdf.GetResource(BROWSER_DOCURL + "navigator-toolbox");
let tabsOnTopResource = this._rdf.GetResource("tabsontop");
let tabsOnTopAttribute = this._getPersist(toolboxResource, tabsOnTopResource);
if (tabsOnTopAttribute)
Services.prefs.setBoolPref("browser.tabs.onTop", tabsOnTopAttribute == "true");
}
if (this._dirty)
this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();

View File

@ -40,6 +40,7 @@ let stateBackup = ss.getBrowserState();
function test() {
/** Test for bug 581593 **/
waitForExplicitFinish();
ignoreAllUncaughtExceptions();
let oldState = { windows: [{ tabs: [{ entries: [{ url: "example.com" }] }] }]};
let pageData = {

View File

@ -14,3 +14,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -23,3 +23,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -23,3 +23,6 @@ export PKG_CONFIG_PATH=/tools/qt-4.6.3/qt/lib/pkgconfig
ac_add_options --with-qtdir=/tools/qt-4.6.3/qt
ac_add_options --enable-default-toolkit=cairo-qt
ac_add_options --disable-crashreporter
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -15,3 +15,6 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profilese
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -26,3 +26,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -11,3 +11,6 @@ export MOZILLA_OFFICIAL=1
# Enable parallel compiling
mk_add_options MOZ_MAKE_FLAGS="-j4"
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -23,3 +23,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -15,3 +15,6 @@ mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profilese
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -26,3 +26,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
#Use ccache
ac_add_options --with-ccache=/usr/bin/ccache
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -18,3 +18,6 @@ export MOZ_TELEMETRY_REPORTING=1
mk_add_options MOZ_MAKE_FLAGS="-j4"
ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -11,3 +11,6 @@ ac_add_options --enable-official-branding
export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -20,3 +20,6 @@ ac_add_options --enable-dtrace
# Need this to prevent name conflicts with the normal nightly build packages
export MOZ_PKG_SPECIAL="shark"
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -9,3 +9,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
export MOZILLA_OFFICIAL=1
ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -11,3 +11,6 @@ mk_add_options MOZ_MAKE_FLAGS="-j4"
export MOZILLA_OFFICIAL=1
ac_add_options --with-macbundlename-prefix=Firefox
# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
ac_add_options --enable-warnings-as-errors

View File

@ -50,18 +50,6 @@
#include "nsMemory.h"
#include "nsStringBuffer.h"
static void *
nsGetPrincipalArray(JSContext *cx, JSPrincipals *prin)
{
return nsnull;
}
static JSBool
nsGlobalPrivilegesEnabled(JSContext *cx, JSPrincipals *jsprin)
{
return JS_TRUE;
}
static JSBool
nsJSPrincipalsSubsume(JSPrincipals *jsprin, JSPrincipals *other)
{
@ -192,8 +180,6 @@ nsJSPrincipals::Startup()
nsJSPrincipals::nsJSPrincipals()
{
codebase = nsnull;
getPrincipalArray = nsGetPrincipalArray;
globalPrivilegesEnabled = nsGlobalPrivilegesEnabled;
refcount = 0;
destroy = nsDestroyJSPrincipals;
subsume = nsJSPrincipalsSubsume;

View File

@ -69,7 +69,6 @@ JAVAC_FLAGS = \
-source $(JAVA_VERSION) \
-classpath $(JAVA_CLASSPATH) \
-bootclasspath $(JAVA_BOOTCLASSPATH) \
-encoding ascii \
-encoding UTF8 \
-g \
$(NULL)

View File

@ -475,13 +475,6 @@ FAIL_ON_WARNINGS_DEBUG=
FAIL_ON_WARNINGS=
endif # WINNT && (MOS_PROFILE_GENERATE ^ MOZ_PROFILE_USE)
# Also clear FAIL_ON_WARNINGS[_DEBUG] for Android builds, since
# they have some platform-specific warnings we haven't fixed yet.
ifeq ($(OS_TARGET),Android)
FAIL_ON_WARNINGS_DEBUG=
FAIL_ON_WARNINGS=
endif # Android
# Now, check for debug version of flag; it turns on normal flag in debug builds.
ifdef FAIL_ON_WARNINGS_DEBUG
ifdef MOZ_DEBUG

View File

@ -7053,14 +7053,14 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -n "$MOZ_DEBUG_FLAGS"; then
fi
dnl ========================================================
dnl = Disable any treating of compile warnings as errors
dnl = Enable any treating of compile warnings as errors
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(warnings-as-errors,
[ --disable-warnings-as-errors
Disable treating of warnings as errors],
MOZ_DISABLE_WARNINGS_AS_ERRORS=1,
MOZ_DISABLE_WARNINGS_AS_ERRORS= )
if test "$MOZ_DISABLE_WARNINGS_AS_ERRORS"; then
MOZ_ARG_ENABLE_BOOL(warnings-as-errors,
[ --enable-warnings-as-errors
Enable treating of warnings as errors],
MOZ_ENABLE_WARNINGS_AS_ERRORS=1,
MOZ_ENABLE_WARNINGS_AS_ERRORS=)
if test -z "$MOZ_ENABLE_WARNINGS_AS_ERRORS"; then
WARNINGS_AS_ERRORS=''
fi

View File

@ -90,7 +90,7 @@ public:
protected:
nsDOMEventTargetWrapperCache() : nsDOMEventTargetHelper(), nsWrapperCache() {}
virtual ~nsDOMEventTargetWrapperCache() {}
virtual ~nsDOMEventTargetWrapperCache();
};
#define NS_DECL_EVENT_HANDLER(_event) \

View File

@ -93,3 +93,8 @@ nsDOMEventTargetWrapperCache::Init(JSContext* aCx)
mOwner = window->GetCurrentInnerWindow();
}
}
nsDOMEventTargetWrapperCache::~nsDOMEventTargetWrapperCache()
{
nsContentUtils::ReleaseWrapper(this, this);
}

View File

@ -1203,13 +1203,19 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
mMessageManager->GetParentManager() : nsnull;
nsFrameMessageManager* otherParentManager = aOther->mMessageManager ?
aOther->mMessageManager->GetParentManager() : nsnull;
JSContext* thisCx =
mMessageManager ? mMessageManager->GetJSContext() : nsnull;
JSContext* otherCx =
aOther->mMessageManager ? aOther->mMessageManager->GetJSContext() : nsnull;
if (mMessageManager) {
mMessageManager->Disconnect();
mMessageManager->RemoveFromParent();
mMessageManager->SetJSContext(otherCx);
mMessageManager->SetParentManager(otherParentManager);
mMessageManager->SetCallbackData(aOther, false);
}
if (aOther->mMessageManager) {
aOther->mMessageManager->Disconnect();
aOther->mMessageManager->RemoveFromParent();
aOther->mMessageManager->SetJSContext(thisCx);
aOther->mMessageManager->SetParentManager(ourParentManager);
aOther->mMessageManager->SetCallbackData(this, false);
}

View File

@ -346,6 +346,28 @@ nsFrameMessageManager::Atob(const nsAString& aAsciiString,
return NS_OK;
}
class MMListenerRemover
{
public:
MMListenerRemover(nsFrameMessageManager* aMM)
: mMM(aMM), mWasHandlingMessage(aMM->mHandlingMessage)
{
mMM->mHandlingMessage = true;
}
~MMListenerRemover()
{
if (!mWasHandlingMessage) {
mMM->mHandlingMessage = false;
if (mMM->mDisconnected) {
mMM->mListeners.Clear();
}
}
}
bool mWasHandlingMessage;
nsRefPtr<nsFrameMessageManager> mMM;
};
nsresult
nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
const nsAString& aMessage,
@ -360,7 +382,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
}
if (mListeners.Length()) {
nsCOMPtr<nsIAtom> name = do_GetAtom(aMessage);
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip(this);
MMListenerRemover lr(this);
for (PRUint32 i = 0; i < mListeners.Length(); ++i) {
if (mListeners[i].mMessage == name) {
@ -531,9 +553,9 @@ nsFrameMessageManager::SetCallbackData(void* aData, bool aLoadScripts)
}
void
nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
nsFrameMessageManager::RemoveFromParent()
{
if (mParentManager && aRemoveFromParent) {
if (mParentManager) {
mParentManager->RemoveChildManager(this);
}
mParentManager = nsnull;
@ -541,6 +563,21 @@ nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
mContext = nsnull;
}
void
nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
{
if (mParentManager && aRemoveFromParent) {
mParentManager->RemoveChildManager(this);
}
mDisconnected = true;
mParentManager = nsnull;
mCallbackData = nsnull;
mContext = nsnull;
if (!mHandlingMessage) {
mListeners.Clear();
}
}
nsresult
NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult)
{

View File

@ -92,7 +92,7 @@ public:
bool aGlobal = false,
bool aProcessManager = false)
: mChrome(aChrome), mGlobal(aGlobal), mIsProcessManager(aProcessManager),
mParentManager(aParentManager),
mHandlingMessage(false), mDisconnected(false), mParentManager(aParentManager),
mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback),
mLoadScriptCallback(aLoadScriptCallback), mCallbackData(aCallbackData),
mContext(aContext)
@ -162,6 +162,8 @@ public:
nsresult SendAsyncMessageInternal(const nsAString& aMessage,
const nsAString& aJSON);
JSContext* GetJSContext() { return mContext; }
void SetJSContext(JSContext* aCx) { mContext = aCx; }
void RemoveFromParent();
nsFrameMessageManager* GetParentManager() { return mParentManager; }
void SetParentManager(nsFrameMessageManager* aParent)
{
@ -181,11 +183,14 @@ public:
return sChildProcessManager;
}
protected:
friend class MMListenerRemover;
nsTArray<nsMessageListenerInfo> mListeners;
nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
bool mChrome;
bool mGlobal;
bool mIsProcessManager;
bool mHandlingMessage;
bool mDisconnected;
nsFrameMessageManager* mParentManager;
nsSyncMessageCallback mSyncCallback;
nsAsyncMessageCallback mAsyncCallback;

View File

@ -250,6 +250,8 @@ nsInProcessTabChildGlobal::DelayedDisconnect()
}
if (!mLoadingScript) {
nsContentUtils::ReleaseWrapper(static_cast<nsIDOMEventTarget*>(this),
this);
if (mCx) {
DestroyCx();
}

View File

@ -54,6 +54,7 @@
#include "nsLayoutStatics.h"
#include "nsBindingManager.h"
#include "nsHashKeys.h"
#include "nsCCUncollectableMarker.h"
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
@ -161,6 +162,11 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsNodeInfoManager)
if (tmp->mDocument &&
nsCCUncollectableMarker::InGeneration(cb,
tmp->mDocument->GetMarkedCCGeneration())) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
if (tmp->mNonDocumentNodeInfos) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocument)
}

View File

@ -450,14 +450,6 @@ nsXMLHttpRequest::~nsXMLHttpRequest()
NS_ABORT_IF_FALSE(!(mState & XML_HTTP_REQUEST_SYNCLOOPING), "we rather crash than hang");
mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
// This can happen if the XHR was only used by C++ (and so never created a JS
// wrapper) that also made an ArrayBuffer.
if (PreservingWrapper()) {
nsContentUtils::ReleaseWrapper(
static_cast<nsIDOMEventTarget*>(
static_cast<nsDOMEventTargetHelper*>(this)), this);
}
nsLayoutStatics::Release();
}

View File

@ -1165,6 +1165,9 @@ nsCanvasRenderingContext2DAzure::Redraw()
return NS_OK;
}
if (mThebesSurface)
mThebesSurface->MarkDirty();
nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
HTMLCanvasElement()->InvalidateCanvasContent(nsnull);
@ -1192,6 +1195,9 @@ nsCanvasRenderingContext2DAzure::Redraw(const mgfx::Rect &r)
return;
}
if (mThebesSurface)
mThebesSurface->MarkDirty();
nsSVGEffects::InvalidateDirectRenderingObservers(HTMLCanvasElement());
gfxRect tmpR = ThebesRect(r);

View File

@ -123,6 +123,7 @@ TableRowsCollection::~TableRowsCollection()
NS_IMPL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TableRowsCollection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOrphanRows)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TableRowsCollection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mOrphanRows,
@ -344,6 +345,13 @@ nsHTMLTableElement::~nsHTMLTableElement()
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLTableElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLTableElement, nsGenericHTMLElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTBodies)
if (tmp->mRows) {
tmp->mRows->ParentDestroyed();
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRows)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLTableElement,
nsGenericHTMLElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTBodies,

View File

@ -91,8 +91,8 @@ public:
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, bool aNotify);
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableElement,
nsGenericHTMLElement)
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLTableElement,
nsGenericHTMLElement)
nsMappedAttributes* GetAttributesMappedForCell();
already_AddRefed<nsIDOMHTMLTableSectionElement> GetTHead() {
return GetSection(nsGkAtoms::thead);

View File

@ -381,6 +381,10 @@ ImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
target = do_QueryInterface(aScriptGlobalObject);
target->AddEventListener(NS_LITERAL_STRING("resize"), this, false);
target->AddEventListener(NS_LITERAL_STRING("keypress"), this, false);
if (!nsContentUtils::IsChildOfSameType(this)) {
LinkStylesheet(NS_LITERAL_STRING("resource://gre/res/TopLevelImageDocument.css"));
}
}
}
@ -665,8 +669,6 @@ ImageDocument::CreateSyntheticDocument()
styleContent->SetTextContent(NS_LITERAL_STRING("img { display: block; }"));
head->AppendChildTo(styleContent, false);
} else {
LinkStylesheet(NS_LITERAL_STRING("resource://gre/res/TopLevelImageDocument.css"));
}
// Add the image element

View File

@ -57,6 +57,7 @@ public:
nsIStreamListener** aDocListener,
bool aReset = true,
nsIContentSink* aSink = nsnull);
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
protected:
@ -94,6 +95,18 @@ VideoDocument::StartDocumentLoad(const char* aCommand,
return rv;
}
void
VideoDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject)
{
// Set the script global object on the superclass before doing
// anything that might require it....
MediaDocument::SetScriptGlobalObject(aScriptGlobalObject);
if (aScriptGlobalObject && !nsContentUtils::IsChildOfSameType(this)) {
LinkStylesheet(NS_LITERAL_STRING("resource://gre/res/TopLevelVideoDocument.css"));
}
}
nsresult
VideoDocument::CreateSyntheticVideoDocument(nsIChannel* aChannel,
nsIStreamListener** aListener)
@ -131,8 +144,6 @@ VideoDocument::CreateSyntheticVideoDocument(nsIChannel* aChannel,
element->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
NS_LITERAL_STRING("position:absolute; top:0; left:0; width:100%; height:100%"),
true);
} else {
LinkStylesheet(NS_LITERAL_STRING("resource://gre/res/TopLevelVideoDocument.css"));
}
return body->AppendChildTo(element, false);

View File

@ -58,7 +58,7 @@ const char gPrincipalCodebase[] = "Web Worker";
JSPrincipals gPrincipal = {
const_cast<char*>(gPrincipalCodebase),
NULL, NULL, 1, PrincipalDestroy, PrincipalSubsume
1, PrincipalDestroy, PrincipalSubsume
};
} // anonymous namespace

View File

@ -176,6 +176,8 @@ lround-c99-only.patch: Only use lround in C99 programs.
unicode-printing.patch: Print as unicode (bug 454532)
quartz-mark-dirty.patch: Add a quartz implementation of mark_dirty_rectangle (bug 715704)
==== pixman patches ====
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.

View File

@ -3121,6 +3121,17 @@ _cairo_quartz_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clip
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_quartz_surface_mark_dirty_rectangle (void *abstract_surface,
int x, int y,
int width, int height)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
_cairo_quartz_surface_will_change (surface);
return CAIRO_STATUS_SUCCESS;
}
// XXXtodo implement show_page; need to figure out how to handle begin/end
static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
@ -3143,7 +3154,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
_cairo_quartz_surface_mark_dirty_rectangle,
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */

View File

@ -0,0 +1,56 @@
Date: Thu Jan 5 18:40:01 2012 -0500
Bug 715704. Add a quartz implementation of mark_dirty_rectangle. r=roc
We need to drop our CGImage cache when the surface has been changed by outside users.
diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c
--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c
@@ -3116,16 +3116,27 @@ _cairo_quartz_surface_clipper_intersect_
CGContextEOClip (surface->cgContext);
}
ND((stderr, "-- intersect_clip_path\n"));
return CAIRO_STATUS_SUCCESS;
}
+static cairo_status_t
+_cairo_quartz_surface_mark_dirty_rectangle (void *abstract_surface,
+ int x, int y,
+ int width, int height)
+{
+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
+ _cairo_quartz_surface_will_change (surface);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+
// XXXtodo implement show_page; need to figure out how to handle begin/end
static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
CAIRO_SURFACE_TYPE_QUARTZ,
_cairo_quartz_surface_create_similar,
_cairo_quartz_surface_finish,
_cairo_quartz_surface_acquire_image,
_cairo_quartz_surface_release_source_image,
@@ -3138,17 +3149,17 @@ static const struct _cairo_surface_backe
NULL, /* create_span_renderer */
NULL, /* check_span_renderer */
NULL, /* copy_page */
NULL, /* show_page */
_cairo_quartz_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
- NULL, /* mark_dirty_rectangle */
+ _cairo_quartz_surface_mark_dirty_rectangle,
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
_cairo_quartz_surface_paint,
_cairo_quartz_surface_mask,
_cairo_quartz_surface_stroke,
_cairo_quartz_surface_fill,
_cairo_quartz_surface_show_glyphs,

View File

@ -62,6 +62,7 @@ SyncChannel::SyncChannel(SyncListener* aListener)
, mProcessingSyncMessage(false)
, mNextSeqno(0)
, mTimeoutMs(kNoTimeout)
, mInTimeoutSecondHalf(false)
#ifdef OS_WIN
, mTopFrame(NULL)
#endif
@ -283,6 +284,23 @@ SyncChannel::ShouldContinueFromTimeout()
return cont;
}
bool
SyncChannel::WaitResponse(bool aWaitTimedOut)
{
if (aWaitTimedOut) {
if (mInTimeoutSecondHalf) {
// We've really timed out this time
return false;
}
// Try a second time
mInTimeoutSecondHalf = true;
} else {
mInTimeoutSecondHalf = false;
}
return true;
}
// Windows versions of the following two functions live in
// WindowsMessageLoop.cpp.
@ -301,7 +319,7 @@ SyncChannel::WaitForNotify()
// if the timeout didn't expire, we know we received an event.
// The converse is not true.
return !IsTimeoutExpired(waitStart, timeout);
return WaitResponse(IsTimeoutExpired(waitStart, timeout));
}
void

View File

@ -81,9 +81,13 @@ public:
// Synchronously send |msg| (i.e., wait for |reply|)
virtual bool Send(Message* msg, Message* reply);
// Set channel timeout value. Since this is broken up into
// two period, the minimum timeout value is 2ms.
void SetReplyTimeoutMs(int32 aTimeoutMs) {
AssertWorkerThread();
mTimeoutMs = (aTimeoutMs <= 0) ? kNoTimeout : aTimeoutMs;
mTimeoutMs = (aTimeoutMs <= 0) ? kNoTimeout :
// timeouts are broken up into two periods
(int32)ceil((double)aTimeoutMs/2.0);
}
static bool IsPumpingMessages() {
@ -185,6 +189,12 @@ protected:
static bool sIsPumpingMessages;
// Timeout periods are broken up in two to prevent system suspension from
// triggering an abort. This method (called by WaitForNotify with a 'did
// timeout' flag) decides if we should wait again for half of mTimeoutMs
// or give up.
bool WaitResponse(bool aWaitTimedOut);
bool mInTimeoutSecondHalf;
int32 mTimeoutMs;
#ifdef OS_WIN

View File

@ -741,7 +741,7 @@ SyncChannel::WaitForNotify()
MonitorAutoUnlock unlock(*mMonitor);
bool retval = true;
bool timedout = false;
UINT_PTR timerId = NULL;
TimeoutData timeoutData = { 0 };
@ -795,7 +795,7 @@ SyncChannel::WaitForNotify()
if (TimeoutHasExpired(timeoutData)) {
// A timeout was specified and we've passed it. Break out.
retval = false;
timedout = true;
break;
}
@ -847,7 +847,7 @@ SyncChannel::WaitForNotify()
SyncChannel::SetIsPumpingMessages(false);
return retval;
return WaitResponse(timedout);
}
bool
@ -868,7 +868,7 @@ RPCChannel::WaitForNotify()
MonitorAutoUnlock unlock(*mMonitor);
bool retval = true;
bool timedout = false;
UINT_PTR timerId = NULL;
TimeoutData timeoutData = { 0 };
@ -949,7 +949,7 @@ RPCChannel::WaitForNotify()
if (TimeoutHasExpired(timeoutData)) {
// A timeout was specified and we've passed it. Break out.
retval = false;
timedout = true;
break;
}
@ -987,7 +987,7 @@ RPCChannel::WaitForNotify()
SyncChannel::SetIsPumpingMessages(false);
return retval;
return WaitResponse(timedout);
}
void

View File

@ -73,7 +73,7 @@ TestHangsParent::ShouldContinueFromReplyTimeout()
{
mDetectedHang = true;
// so we've detected a timeout after 1 ms ... now we cheat and
// so we've detected a timeout after 2 ms ... now we cheat and
// sleep for a long time, to allow the subprocess's reply to come
// in
@ -95,9 +95,9 @@ TestHangsParent::AnswerStackFrame()
fail("should have timed out!");
}
else {
// minimum possible, 1 ms. We want to detecting a hang to race
// minimum possible, 2 ms. We want to detecting a hang to race
// with the reply coming in, as reliably as possible
SetReplyTimeoutMs(1);
SetReplyTimeoutMs(2);
if (CallHang())
fail("should have timed out!");

View File

@ -475,13 +475,6 @@ FAIL_ON_WARNINGS_DEBUG=
FAIL_ON_WARNINGS=
endif # WINNT && (MOS_PROFILE_GENERATE ^ MOZ_PROFILE_USE)
# Also clear FAIL_ON_WARNINGS[_DEBUG] for Android builds, since
# they have some platform-specific warnings we haven't fixed yet.
ifeq ($(OS_TARGET),Android)
FAIL_ON_WARNINGS_DEBUG=
FAIL_ON_WARNINGS=
endif # Android
# Now, check for debug version of flag; it turns on normal flag in debug builds.
ifdef FAIL_ON_WARNINGS_DEBUG
ifdef MOZ_DEBUG

View File

@ -4214,14 +4214,14 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then
fi
dnl ========================================================
dnl = Disable any treating of compile warnings as errors
dnl = Enable any treating of compile warnings as errors
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(warnings-as-errors,
[ --disable-warnings-as-errors
Disable treating of warnings as errors],
MOZ_DISABLE_WARNINGS_AS_ERRORS=1,
MOZ_DISABLE_WARNINGS_AS_ERRORS= )
if test "$MOZ_DISABLE_WARNINGS_AS_ERRORS"; then
[ --enable-warnings-as-errors
Enable treating of warnings as errors],
MOZ_ENABLE_WARNINGS_AS_ERRORS=1,
MOZ_ENABLE_WARNINGS_AS_ERRORS=)
if test -z "$MOZ_ENABLE_WARNINGS_AS_ERRORS"; then
WARNINGS_AS_ERRORS=''
fi
@ -5350,12 +5350,6 @@ if test "$ENABLE_TESTS"; then
"
fi
if test "$DEHYDRA_PATH"; then
MAKEFILES="$MAKEFILES
analysis-tests/Makefile
"
fi
dnl
dnl Run a perl script to quickly create the makefiles.
dnl If it succeeds, it outputs a shell command to set CONFIG_FILES

View File

@ -502,6 +502,7 @@ struct ParseNode {
pn_used : 1, /* name node is on a use-chain */
pn_defn : 1; /* this node is a Definition */
ParseNode(const ParseNode &other) MOZ_DELETE;
void operator=(const ParseNode &other) MOZ_DELETE;
public:

View File

@ -711,7 +711,7 @@ ForgetUse(ParseNode *pn)
static ParseNode *
MakeAssignment(ParseNode *pn, ParseNode *rhs, TreeContext *tc)
{
ParseNode *lhs = tc->parser->new_<ParseNode>(*pn);
ParseNode *lhs = tc->parser->cloneNode(*pn);
if (!lhs)
return NULL;
@ -6948,9 +6948,20 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
return NULL;
} else if (tt == TOK_STRING) {
atom = tokenStream.currentToken().atom();
pn3 = NameNode::create(PNK_STRING, atom, tc);
if (!pn3)
return NULL;
uint32_t index;
if (atom->isIndex(&index)) {
pn3 = NullaryNode::create(PNK_NUMBER, tc);
if (!pn3)
return NULL;
pn3->pn_dval = index;
if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
return NULL;
} else {
pn3 = NameNode::create(PNK_STRING, atom, tc);
if (!pn3)
return NULL;
}
} else if (tt == TOK_NUMBER) {
pn3 = NullaryNode::create(PNK_NUMBER, tc);
if (!pn3)

View File

@ -142,9 +142,9 @@ struct Parser : private AutoGCRooter
inline bool reportErrorNumber(ParseNode *pn, uintN flags, uintN errorNumber, ...);
private:
void *allocParseNode(size_t size) {
ParseNode *allocParseNode(size_t size) {
JS_ASSERT(size == sizeof(ParseNode));
return allocator.allocNode();
return static_cast<ParseNode *>(allocator.allocNode());
}
/*
@ -160,6 +160,14 @@ struct Parser : private AutoGCRooter
/* new_ methods for creating parse nodes. These report OOM on context. */
JS_DECLARE_NEW_METHODS(allocParseNode, inline)
ParseNode *cloneNode(const ParseNode &other) {
ParseNode *node = allocParseNode(sizeof(ParseNode));
if (!node)
return NULL;
memcpy(node, &other, sizeof(*node));
return node;
}
/* Public entry points for parsing. */
ParseNode *statement();
bool recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMember);

View File

@ -4,7 +4,7 @@ static void
Destroy(JSContext *cx, JSPrincipals *prin);
JSPrincipals system_principals = {
(char *)"", NULL, NULL, 1, Destroy, NULL
(char *)"", 1, Destroy, NULL
};
static void

View File

@ -36,9 +36,9 @@ ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
}
char p1str[] = "principal1";
JSPrincipals prin1 = { p1str, 0, 0, 0, Destroy, Subsume };
JSPrincipals prin1 = { p1str, 0, Destroy, Subsume };
char p2str[] = "principal2";
JSPrincipals prin2 = { p2str, 0, 0, 0, Destroy, Subsume };
JSPrincipals prin2 = { p2str, 0, Destroy, Subsume };
BEGIN_TEST(testOriginPrincipals)
{

View File

@ -696,7 +696,6 @@ JSRuntime::JSRuntime()
gcLastBytes(0),
gcMaxBytes(0),
gcMaxMallocBytes(0),
gcEmptyArenaPoolLifespan(0),
gcNumArenasFreeCommitted(0),
gcNumber(0),
gcIncrementalTracer(NULL),
@ -2910,15 +2909,15 @@ JS_PUBLIC_API(void)
JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value)
{
switch (key) {
case JSGC_MAX_BYTES:
case JSGC_MAX_BYTES: {
AutoLockGC lock(rt);
JS_ASSERT(value >= rt->gcBytes);
rt->gcMaxBytes = value;
break;
}
case JSGC_MAX_MALLOC_BYTES:
rt->setGCMaxMallocBytes(value);
break;
case JSGC_STACKPOOL_LIFESPAN:
rt->gcEmptyArenaPoolLifespan = value;
break;
default:
JS_ASSERT(key == JSGC_MODE);
rt->gcMode = JSGCMode(value);
@ -2933,13 +2932,11 @@ JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
{
switch (key) {
case JSGC_MAX_BYTES:
return rt->gcMaxBytes;
return uint32_t(rt->gcMaxBytes);
case JSGC_MAX_MALLOC_BYTES:
return rt->gcMaxMallocBytes;
case JSGC_STACKPOOL_LIFESPAN:
return rt->gcEmptyArenaPoolLifespan;
case JSGC_BYTES:
return rt->gcBytes;
return uint32_t(rt->gcBytes);
case JSGC_MODE:
return uint32_t(rt->gcMode);
case JSGC_UNUSED_CHUNKS:
@ -4181,7 +4178,11 @@ JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
return obj->deleteGeneric(cx, id, rval, false);
if (JSID_IS_SPECIAL(id))
return obj->deleteSpecial(cx, JSID_TO_SPECIALID(id), rval, false);
return obj->deleteByValue(cx, IdToValue(id), rval, false);
}
JS_PUBLIC_API(JSBool)
@ -4189,24 +4190,37 @@ JS_DeleteElement2(JSContext *cx, JSObject *obj, uint32_t index, jsval *rval)
{
AssertNoGC(cx);
CHECK_REQUEST(cx);
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return JS_DeletePropertyById2(cx, obj, id, rval);
assertSameCompartment(cx, obj);
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
return obj->deleteElement(cx, index, rval, false);
}
JS_PUBLIC_API(JSBool)
JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, jsval *rval)
{
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
JSAtom *atom = js_Atomize(cx, name, strlen(name));
return atom && JS_DeletePropertyById2(cx, obj, ATOM_TO_JSID(atom), rval);
if (!atom)
return false;
return obj->deleteByValue(cx, StringValue(atom), rval, false);
}
JS_PUBLIC_API(JSBool)
JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *rval)
{
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
return atom && JS_DeletePropertyById2(cx, obj, ATOM_TO_JSID(atom), rval);
if (!atom)
return false;
return obj->deleteByValue(cx, StringValue(atom), rval, false);
}
JS_PUBLIC_API(JSBool)
@ -5354,7 +5368,7 @@ JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
filename, lineno, rval, avi.version());
}
extern JS_PUBLIC_API(JSBool)
JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
JSPrincipals *principals,

View File

@ -2968,9 +2968,6 @@ typedef enum JSGCParamKey {
/* Number of JS_malloc bytes before last ditch GC. */
JSGC_MAX_MALLOC_BYTES = 1,
/* Hoard stackPools for this long, in ms, default is 30 seconds. */
JSGC_STACKPOOL_LIFESPAN = 2,
/* Amount of bytes allocated by the GC. */
JSGC_BYTES = 3,
@ -3731,10 +3728,6 @@ JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32_t index, jsval v);
struct JSPrincipals {
char *codebase;
/* XXX unspecified and unused by Mozilla code -- can we remove these? */
void * (* getPrincipalArray)(JSContext *cx, JSPrincipals *);
JSBool (* globalPrivilegesEnabled)(JSContext *cx, JSPrincipals *);
/* Don't call "destroy"; use reference counting macros below. */
jsrefcount refcount;

View File

@ -522,9 +522,11 @@ static int
DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index, bool strict)
{
JS_ASSERT(index >= 0);
JS_ASSERT(floor(index) == index);
if (obj->isDenseArray()) {
if (index <= jsuint(-1)) {
jsuint idx = jsuint(index);
if (index <= UINT32_MAX) {
uint32_t idx = uint32_t(index);
if (idx < obj->getDenseArrayInitializedLength()) {
obj->markDenseArrayNotPacked(cx);
obj->setDenseArrayElement(idx, MagicValue(JS_ARRAY_HOLE));
@ -535,16 +537,15 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index, bool strict)
return 1;
}
AutoIdRooter idr(cx);
if (!IndexToId(cx, obj, index, NULL, idr.addr()))
return -1;
if (JSID_IS_VOID(idr.id()))
return 1;
Value v;
if (!obj->deleteGeneric(cx, idr.id(), &v, strict))
return -1;
if (index <= UINT32_MAX) {
if (!obj->deleteElement(cx, uint32_t(index), &v, strict))
return -1;
} else {
if (!obj->deleteByValue(cx, DoubleValue(index), &v, strict))
return -1;
}
return v.isTrue() ? 1 : 0;
}
@ -1140,36 +1141,20 @@ array_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *a
}
static JSBool
array_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
array_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
uint32_t i;
if (!obj->isDenseArray())
return js_DeleteProperty(cx, obj, id, rval, strict);
return js_DeleteProperty(cx, obj, name, rval, strict);
if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
if (name == cx->runtime->atomState.lengthAtom) {
rval->setBoolean(false);
return true;
}
if (js_IdIsIndex(id, &i) && i < obj->getDenseArrayInitializedLength()) {
obj->markDenseArrayNotPacked(cx);
obj->setDenseArrayElement(i, MagicValue(JS_ARRAY_HOLE));
}
if (!js_SuppressDeletedProperty(cx, obj, id))
return false;
rval->setBoolean(true);
return true;
}
static JSBool
array_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
return array_deleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict);
}
namespace js {
/* non-static for direct deletion of array elements within the engine */
@ -1196,7 +1181,11 @@ array_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, J
static JSBool
array_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
{
return array_deleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
if (!obj->isDenseArray())
return js_DeleteSpecial(cx, obj, sid, rval, strict);
rval->setBoolean(true);
return true;
}
static void
@ -1271,7 +1260,6 @@ Class js::ArrayClass = {
array_setPropertyAttributes,
array_setElementAttributes,
array_setSpecialAttributes,
array_deleteGeneric,
array_deleteProperty,
array_deleteElement,
array_deleteSpecial,

View File

@ -228,9 +228,7 @@ typedef JSBool
typedef JSBool
(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp);
typedef JSBool
(* DeleteGenericOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
typedef JSBool
(* DeleteIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
(* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
typedef JSBool
(* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
typedef JSBool
@ -329,8 +327,7 @@ struct ObjectOps
PropertyAttributesOp setPropertyAttributes;
ElementAttributesOp setElementAttributes;
SpecialAttributesOp setSpecialAttributes;
DeleteGenericOp deleteGeneric;
DeleteIdOp deleteProperty;
DeletePropertyOp deleteProperty;
DeleteElementOp deleteElement;
DeleteSpecialOp deleteSpecial;
@ -343,7 +340,7 @@ struct ObjectOps
#define JS_NULL_OBJECT_OPS \
{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL}
struct Class

View File

@ -796,9 +796,9 @@ js_ReportOutOfMemory(JSContext *cx)
{
cx->runtime->hadOutOfMemory = true;
/* AtomizeInline can cal this indirectly when it creates the string. */
/* AtomizeInline can call this indirectly when it creates the string. */
AutoUnlockAtomsCompartmentWhenLocked unlockAtomsCompartment(cx);
JSErrorReport report;
JSErrorReporter onError = cx->errorReporter;
@ -1261,13 +1261,6 @@ js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
return NULL;
}
bool
checkOutOfMemory(JSRuntime *rt)
{
AutoLockGC lock(rt);
return rt->gcBytes > rt->gcMaxBytes;
}
JSBool
js_InvokeOperationCallback(JSContext *cx)
{
@ -1289,34 +1282,9 @@ js_InvokeOperationCallback(JSContext *cx)
#endif
JS_UNLOCK_GC(rt);
if (rt->gcIsNeeded) {
if (rt->gcIsNeeded)
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, rt->gcTriggerReason);
/*
* On trace we can exceed the GC quota, see comments in NewGCArena. So
* we check the quota and report OOM here when we are off trace.
*/
if (checkOutOfMemory(rt)) {
#ifdef JS_THREADSAFE
/*
* We have to wait until the background thread is done in order
* to get a correct answer.
*/
{
AutoLockGC lock(rt);
rt->gcHelperThread.waitBackgroundSweepEnd();
}
if (checkOutOfMemory(rt)) {
js_ReportOutOfMemory(cx);
return false;
}
#else
js_ReportOutOfMemory(cx);
return false;
#endif
}
}
#ifdef JS_THREADSAFE
/*
* We automatically yield the current context every time the operation

View File

@ -425,12 +425,11 @@ struct JSRuntime
js::RootedValueMap gcRootsHash;
js::GCLocks gcLocksHash;
jsrefcount gcKeepAtoms;
uint32_t gcBytes;
uint32_t gcTriggerBytes;
size_t gcBytes;
size_t gcTriggerBytes;
size_t gcLastBytes;
size_t gcMaxBytes;
size_t gcMaxMallocBytes;
uint32_t gcEmptyArenaPoolLifespan;
/*
* Number of the committed arenas in all GC chunks including empty chunks.
@ -689,7 +688,7 @@ struct JSRuntime
JSRuntime *thisFromCtor() { return this; }
void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
void reduceGCTriggerBytes(uint32_t amount);
void reduceGCTriggerBytes(size_t amount);
/*
* Call the system malloc while checking for GC memory pressure and

View File

@ -188,8 +188,8 @@ struct JS_FRIEND_API(JSCompartment) {
return createBarrierTracer();
}
uint32_t gcBytes;
uint32_t gcTriggerBytes;
size_t gcBytes;
size_t gcTriggerBytes;
size_t gcLastBytes;
bool hold;
@ -315,7 +315,7 @@ struct JS_FRIEND_API(JSCompartment) {
void purge(JSContext *cx);
void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
void reduceGCTriggerBytes(uint32_t amount);
void reduceGCTriggerBytes(size_t amount);
js::DtoaCache dtoaCache;

View File

@ -532,7 +532,7 @@ JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fpArg)
if (fp->annotation() && fp->isScriptFrame()) {
JSPrincipals *principals = fp->scopeChain().principals(cx);
if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
if (principals) {
/*
* Give out an annotation only if privileges have not been revoked
* or disabled globally.
@ -550,17 +550,6 @@ JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation)
Valueify(fp)->setAnnotation(annotation);
}
JS_PUBLIC_API(void *)
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
{
JSPrincipals *principals;
principals = Valueify(fp)->scopeChain().principals(cx);
if (!principals)
return NULL;
return principals->getPrincipalArray(cx, principals);
}
JS_PUBLIC_API(JSBool)
JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp)
{

View File

@ -258,9 +258,6 @@ JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(void)
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
extern JS_PUBLIC_API(void *)
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSBool)
JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp);

View File

@ -331,7 +331,7 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
* that has a setter for this id.
*/
AutoValueRooter tvr(cx);
return js_DeleteProperty(cx, &argsobj, id, tvr.addr(), false) &&
return js_DeleteGeneric(cx, &argsobj, id, tvr.addr(), false) &&
js_DefineProperty(cx, &argsobj, id, vp, NULL, NULL, JSPROP_ENUMERATE);
}
@ -446,7 +446,7 @@ StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
* collect its value.
*/
AutoValueRooter tvr(cx);
return js_DeleteProperty(cx, &argsobj, id, tvr.addr(), strict) &&
return js_DeleteGeneric(cx, &argsobj, id, tvr.addr(), strict) &&
js_SetPropertyHelper(cx, &argsobj, id, 0, vp, strict);
}
@ -1036,7 +1036,7 @@ StackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
* barrier, so we must clone fun and store it in fp's callee to
* avoid re-cloning upon repeated foo.caller access.
*
* This must mean the code in js_DeleteProperty could not find this
* This must mean the code in js_DeleteGeneric could not find this
* stack frame on the stack when the method was deleted. We've lost
* track of the method, so we associate it with the first barriered
* object found starting from thisp on the prototype chain.

View File

@ -289,6 +289,13 @@ struct JSFunction : public JSObject
*/
inline JSAtom *methodAtom() const;
inline void setMethodAtom(JSAtom *atom);
/*
* These member functions are inherited from JSObject, but should never be applied to
* a value statically known to be a JSFunction.
*/
inline JSFunction *toFunction() MOZ_DELETE;
inline const JSFunction *toFunction() const MOZ_DELETE;
};
inline JSFunction *

View File

@ -732,6 +732,9 @@ Chunk::allocateArena(JSCompartment *comp, AllocKind thingKind)
JS_ASSERT(hasAvailableArenas());
JSRuntime *rt = comp->rt;
JS_ASSERT(rt->gcBytes <= rt->gcMaxBytes);
if (rt->gcMaxBytes - rt->gcBytes < ArenaSize)
return NULL;
ArenaHeader *aheader = JS_LIKELY(info.numArenasFreeCommitted > 0)
? fetchNextFreeArena(rt)
@ -741,8 +744,8 @@ Chunk::allocateArena(JSCompartment *comp, AllocKind thingKind)
removeFromAvailableList();
Probes::resizeHeap(comp, rt->gcBytes, rt->gcBytes + ArenaSize);
JS_ATOMIC_ADD(&rt->gcBytes, ArenaSize);
JS_ATOMIC_ADD(&comp->gcBytes, ArenaSize);
rt->gcBytes += ArenaSize;
comp->gcBytes += ArenaSize;
if (comp->gcBytes >= comp->gcTriggerBytes)
TriggerCompartmentGC(comp, gcstats::ALLOCTRIGGER);
@ -774,16 +777,16 @@ Chunk::releaseArena(ArenaHeader *aheader)
#endif
Probes::resizeHeap(comp, rt->gcBytes, rt->gcBytes - ArenaSize);
JS_ASSERT(size_t(rt->gcBytes) >= ArenaSize);
JS_ASSERT(size_t(comp->gcBytes) >= ArenaSize);
JS_ASSERT(rt->gcBytes >= ArenaSize);
JS_ASSERT(comp->gcBytes >= ArenaSize);
#ifdef JS_THREADSAFE
if (rt->gcHelperThread.sweeping()) {
rt->reduceGCTriggerBytes(GC_HEAP_GROWTH_FACTOR * ArenaSize);
comp->reduceGCTriggerBytes(GC_HEAP_GROWTH_FACTOR * ArenaSize);
}
#endif
JS_ATOMIC_ADD(&rt->gcBytes, -int32_t(ArenaSize));
JS_ATOMIC_ADD(&comp->gcBytes, -int32_t(ArenaSize));
rt->gcBytes -= ArenaSize;
comp->gcBytes -= ArenaSize;
aheader->setAsNotAllocated();
addArenaToFreeList(rt, aheader);
@ -902,7 +905,6 @@ js_InitGC(JSRuntime *rt, uint32_t maxbytes)
*/
rt->gcMaxBytes = maxbytes;
rt->setGCMaxMallocBytes(maxbytes);
rt->gcEmptyArenaPoolLifespan = 30000;
/*
* The assigned value prevents GC from running when GC memory is too low
@ -1419,7 +1421,7 @@ JSRuntime::setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind)
}
void
JSRuntime::reduceGCTriggerBytes(uint32_t amount) {
JSRuntime::reduceGCTriggerBytes(size_t amount) {
JS_ASSERT(amount > 0);
JS_ASSERT(gcTriggerBytes - amount >= 0);
if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * GC_HEAP_GROWTH_FACTOR)
@ -1438,7 +1440,7 @@ JSCompartment::setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind)
}
void
JSCompartment::reduceGCTriggerBytes(uint32_t amount) {
JSCompartment::reduceGCTriggerBytes(size_t amount) {
JS_ASSERT(amount > 0);
JS_ASSERT(gcTriggerBytes - amount >= 0);
if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * GC_HEAP_GROWTH_FACTOR)
@ -1466,33 +1468,21 @@ ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
* moment. So we always allocate a new arena in that case.
*/
maybeLock.lock(comp->rt);
for (;;) {
if (*bfs == BFS_DONE)
break;
if (*bfs == BFS_JUST_FINISHED) {
/*
* Before we took the GC lock or while waiting for the
* background finalization to finish the latter added new
* arenas to the list.
*/
*bfs = BFS_DONE;
break;
}
if (*bfs == BFS_RUN) {
JS_ASSERT(!*al->cursor);
chunk = PickChunk(comp);
if (chunk)
break;
/*
* If the background finalization still runs, wait for it to
* finish and retry to check if it populated the arena list or
* added new empty arenas.
*/
JS_ASSERT(*bfs == BFS_RUN);
comp->rt->gcHelperThread.waitBackgroundSweepEnd();
JS_ASSERT(*bfs == BFS_JUST_FINISHED || *bfs == BFS_DONE);
if (!chunk) {
/*
* Let the caller to wait for the background allocation to
* finish and restart the allocation attempt.
*/
return NULL;
}
} else if (*bfs == BFS_JUST_FINISHED) {
/* See comments before BackgroundFinalizeState definition. */
*bfs = BFS_DONE;
} else {
JS_ASSERT(*bfs == BFS_DONE);
}
}
#endif /* JS_THREADSAFE */
@ -1536,6 +1526,9 @@ ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
*/
JS_ASSERT(!*al->cursor);
ArenaHeader *aheader = chunk->allocateArena(comp, thingKind);
if (!aheader)
return NULL;
aheader->next = al->head;
if (!al->head) {
JS_ASSERT(al->cursor == &al->head);
@ -1717,13 +1710,6 @@ RunLastDitchGC(JSContext *cx)
/* The last ditch GC preserves all atoms. */
AutoKeepAtoms keep(rt);
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcstats::LASTDITCH);
#ifdef JS_THREADSAFE
if (rt->gcBytes >= rt->gcMaxBytes) {
AutoLockGC lock(rt);
cx->runtime->gcHelperThread.waitBackgroundSweepEnd();
}
#endif
}
/* static */ void *
@ -1740,10 +1726,6 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
if (JS_UNLIKELY(runGC)) {
RunLastDitchGC(cx);
/* Report OOM of the GC failed to free enough memory. */
if (rt->gcBytes > rt->gcMaxBytes)
break;
/*
* The JSGC_END callback can legitimately allocate new GC
* things and populate the free list. If that happens, just
@ -1753,9 +1735,27 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
if (void *thing = comp->arenas.allocateFromFreeList(thingKind, thingSize))
return thing;
}
void *thing = comp->arenas.allocateFromArena(comp, thingKind);
if (JS_LIKELY(!!thing))
return thing;
/*
* allocateFromArena may fail while the background finalization still
* run. In that case we want to wait for it to finish and restart.
* However, checking for that is racy as the background finalization
* could free some things after allocateFromArena decided to fail but
* at this point it may have already stopped. To avoid this race we
* always try to allocate twice.
*/
for (bool secondAttempt = false; ; secondAttempt = true) {
void *thing = comp->arenas.allocateFromArena(comp, thingKind);
if (JS_LIKELY(!!thing))
return thing;
if (secondAttempt)
break;
AutoLockGC lock(rt);
#ifdef JS_THREADSAFE
rt->gcHelperThread.waitBackgroundSweepEnd();
#endif
}
/*
* We failed to allocate. Run the GC if we haven't done it already.
@ -1963,7 +1963,14 @@ js_TraceStackFrame(JSTracer *trc, StackFrame *fp)
return;
if (fp->hasArgsObj())
MarkRoot(trc, &fp->argsObj(), "arguments");
MarkRoot(trc, fp->script(), "script");
if (fp->isFunctionFrame()) {
MarkRoot(trc, fp->fun(), "fun");
if (fp->isEvalFrame()) {
MarkRoot(trc, fp->script(), "eval script");
}
} else {
MarkRoot(trc, fp->script(), "script");
}
fp->script()->compartment()->active = true;
MarkRoot(trc, fp->returnValue(), "rval");
}
@ -2909,7 +2916,7 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind)
rt->gcTriggerCompartment = NULL;
/* Reset weak map list. */
rt->gcWeakMapList = NULL;
WeakMapBase::resetWeakMapList(rt);
/* Reset malloc counter. */
rt->resetGCMallocBytes();

View File

@ -2792,12 +2792,10 @@ BEGIN_CASE(JSOP_DELELEM)
JSObject *obj;
FETCH_OBJECT(cx, -2, obj);
/* Fetch index and convert it to id suitable for use with obj. */
jsid id;
FETCH_ELEMENT_ID(obj, -1, id);
const Value &propval = regs.sp[-1];
Value &rval = regs.sp[-2];
/* Get or set the element. */
if (!obj->deleteGeneric(cx, id, &regs.sp[-2], script->strictModeCode))
if (!obj->deleteByValue(cx, propval, &rval, script->strictModeCode))
goto error;
regs.sp--;

View File

@ -134,13 +134,13 @@ js_ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
extern JS_FRIEND_API(JSBool)
js_CloseIterator(JSContext *cx, JSObject *iterObj);
bool
extern bool
js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id);
bool
extern bool
js_SuppressDeletedElement(JSContext *cx, JSObject *obj, uint32_t index);
bool
extern bool
js_SuppressDeletedElements(JSContext *cx, JSObject *obj, uint32_t begin, uint32_t end);
/*

View File

@ -3347,6 +3347,28 @@ JSObject::nonNativeSetElement(JSContext *cx, uint32_t index, js::Value *vp, JSBo
return getOps()->setElement(cx, this, index, vp, strict);
}
bool
JSObject::deleteByValue(JSContext *cx, const Value &property, Value *rval, bool strict)
{
uint32_t index;
if (IsDefinitelyIndex(property, &index))
return deleteElement(cx, index, rval, strict);
Value propval = property;
SpecialId sid;
if (ValueIsSpecial(this, &propval, &sid, cx))
return deleteSpecial(cx, sid, rval, strict);
JSAtom *name;
if (!js_ValueToAtom(cx, propval, &name))
return false;
if (name->isIndex(&index))
return deleteElement(cx, index, rval, false);
return deleteProperty(cx, name->asPropertyName(), rval, false);
}
JS_FRIEND_API(bool)
JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj)
{
@ -3915,7 +3937,7 @@ DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, H
bad:
if (named) {
Value rval;
obj->deleteGeneric(cx, ATOM_TO_JSID(atom), &rval, false);
obj->deleteByValue(cx, StringValue(atom), &rval, false);
}
if (cached)
ClearClassObject(cx, obj, key);
@ -5903,7 +5925,7 @@ js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *att
}
JSBool
js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
js_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
{
JSObject *proto;
JSProperty *prop;
@ -5974,13 +5996,25 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str
return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id);
}
JSBool
js_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
return js_DeleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict);
}
JSBool
js_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
{
jsid id;
if (!IndexToId(cx, index, &id))
return false;
return js_DeleteProperty(cx, obj, id, rval, strict);
return js_DeleteGeneric(cx, obj, id, rval, strict);
}
JSBool
js_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
{
return js_DeleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
}
namespace js {

View File

@ -327,11 +327,17 @@ extern JSBool
js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, uintN *attrsp);
extern JSBool
js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *rval, JSBool strict);
js_DeleteProperty(JSContext *cx, JSObject *obj, js::PropertyName *name, js::Value *rval, JSBool strict);
extern JSBool
js_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, js::Value *rval, JSBool strict);
extern JSBool
js_DeleteSpecial(JSContext *cx, JSObject *obj, js::SpecialId sid, js::Value *rval, JSBool strict);
extern JSBool
js_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, js::Value *rval, JSBool strict);
extern JSType
js_TypeOf(JSContext *cx, JSObject *obj);
@ -1336,10 +1342,10 @@ struct JSObject : js::gc::Cell
inline JSBool setElementAttributes(JSContext *cx, uint32_t index, uintN *attrsp);
inline JSBool setSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp);
inline JSBool deleteGeneric(JSContext *cx, jsid id, js::Value *rval, JSBool strict);
inline JSBool deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, JSBool strict);
inline JSBool deleteElement(JSContext *cx, uint32_t index, js::Value *rval, JSBool strict);
inline JSBool deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, JSBool strict);
inline bool deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, bool strict);
inline bool deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict);
inline bool deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, bool strict);
bool deleteByValue(JSContext *cx, const js::Value &property, js::Value *rval, bool strict);
inline bool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp);
inline bool defaultValue(JSContext *cx, JSType hint, js::Value *vp);

View File

@ -229,35 +229,36 @@ JSObject::getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp)
return getGeneric(cx, ATOM_TO_JSID(name), vp);
}
inline JSBool
JSObject::deleteGeneric(JSContext *cx, jsid id, js::Value *rval, JSBool strict)
inline bool
JSObject::deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, bool strict)
{
js::types::AddTypePropertyId(cx, this, id,
js::types::Type::UndefinedType());
jsid id = js_CheckForStringIndex(ATOM_TO_JSID(name));
js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
js::types::MarkTypePropertyConfigured(cx, this, id);
js::DeleteGenericOp op = getOps()->deleteGeneric;
return (op ? op : js_DeleteProperty)(cx, this, id, rval, strict);
js::DeletePropertyOp op = getOps()->deleteProperty;
return (op ? op : js_DeleteProperty)(cx, this, name, rval, strict);
}
inline JSBool
JSObject::deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, JSBool strict)
{
return deleteGeneric(cx, ATOM_TO_JSID(name), rval, strict);
}
inline JSBool
JSObject::deleteElement(JSContext *cx, uint32_t index, js::Value *rval, JSBool strict)
inline bool
JSObject::deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict)
{
jsid id;
if (!js::IndexToId(cx, index, &id))
return false;
return deleteGeneric(cx, id, rval, strict);
js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
js::types::MarkTypePropertyConfigured(cx, this, id);
js::DeleteElementOp op = getOps()->deleteElement;
return (op ? op : js_DeleteElement)(cx, this, index, rval, strict);
}
inline JSBool
JSObject::deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, JSBool strict)
inline bool
JSObject::deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, bool strict)
{
return deleteGeneric(cx, SPECIALID_TO_JSID(sid), rval, strict);
jsid id = SPECIALID_TO_JSID(sid);
js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
js::types::MarkTypePropertyConfigured(cx, this, id);
js::DeleteSpecialOp op = getOps()->deleteSpecial;
return (op ? op : js_DeleteSpecial)(cx, this, sid, rval, strict);
}
inline void

View File

@ -839,7 +839,7 @@ Walk(JSContext *cx, JSObject *holder, jsid name, const Value &reviver, Value *vp
if (newElement.isUndefined()) {
/* Step 2b(ii)(2). */
if (!js_DeleteProperty(cx, obj, id, &newElement, false))
if (!obj->deleteByValue(cx, IdToValue(id), &newElement, false))
return false;
} else {
/* Step 2b(ii)(3). */

View File

@ -1166,7 +1166,7 @@ proxy_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *a
static JSBool
proxy_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
{
id = js_CheckForStringIndex(id);
JS_ASSERT(id == js_CheckForStringIndex(id));
// TODO: throwing away strict
bool deleted;
@ -1179,7 +1179,7 @@ proxy_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool s
static JSBool
proxy_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
return proxy_DeleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict);
return proxy_DeleteGeneric(cx, obj, js_CheckForStringIndex(ATOM_TO_JSID(name)), rval, strict);
}
static JSBool
@ -1309,7 +1309,6 @@ JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
proxy_SetPropertyAttributes,
proxy_SetElementAttributes,
proxy_SetSpecialAttributes,
proxy_DeleteGeneric,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,
@ -1371,7 +1370,6 @@ JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = {
proxy_SetPropertyAttributes,
proxy_SetElementAttributes,
proxy_SetSpecialAttributes,
proxy_DeleteGeneric,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,
@ -1445,7 +1443,6 @@ JS_FRIEND_DATA(Class) js::FunctionProxyClass = {
proxy_SetPropertyAttributes,
proxy_SetElementAttributes,
proxy_SetSpecialAttributes,
proxy_DeleteGeneric,
proxy_DeleteProperty,
proxy_DeleteElement,
proxy_DeleteSpecial,

View File

@ -582,9 +582,9 @@ ArrayBuffer::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId si
}
JSBool
ArrayBuffer::obj_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
ArrayBuffer::obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
if (name == cx->runtime->atomState.byteLengthAtom) {
rval->setBoolean(false);
return true;
}
@ -592,13 +592,7 @@ ArrayBuffer::obj_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rva
JSObject *delegate = DelegateObject(cx, obj);
if (!delegate)
return false;
return js_DeleteProperty(cx, delegate, id, rval, strict);
}
JSBool
ArrayBuffer::obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
return obj_deleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict);
return js_DeleteProperty(cx, delegate, name, rval, strict);
}
JSBool
@ -613,7 +607,10 @@ ArrayBuffer::obj_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Val
JSBool
ArrayBuffer::obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
{
return obj_deleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
JSObject *delegate = DelegateObject(cx, obj);
if (!delegate)
return false;
return js_DeleteSpecial(cx, delegate, sid, rval, strict);
}
JSBool
@ -1261,17 +1258,9 @@ class TypedArrayTemplate
}
static JSBool
obj_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
rval->setBoolean(false);
return true;
}
JSObject *tarray = TypedArray::getTypedArray(obj);
JS_ASSERT(tarray);
if (isArrayIndex(cx, tarray, id)) {
if (name == cx->runtime->atomState.lengthAtom) {
rval->setBoolean(false);
return true;
}
@ -1280,12 +1269,6 @@ class TypedArrayTemplate
return true;
}
static JSBool
obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
return obj_deleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict);
}
static JSBool
obj_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
{
@ -1304,7 +1287,8 @@ class TypedArrayTemplate
static JSBool
obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
{
return obj_deleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
rval->setBoolean(true);
return true;
}
static JSBool
@ -2172,7 +2156,6 @@ Class js::ArrayBufferClass = {
ArrayBuffer::obj_setPropertyAttributes,
ArrayBuffer::obj_setElementAttributes,
ArrayBuffer::obj_setSpecialAttributes,
ArrayBuffer::obj_deleteGeneric,
ArrayBuffer::obj_deleteProperty,
ArrayBuffer::obj_deleteElement,
ArrayBuffer::obj_deleteSpecial,
@ -2285,7 +2268,6 @@ JSFunctionSpec _typedArray::jsfuncs[] = { \
_typedArray::obj_setPropertyAttributes, \
_typedArray::obj_setElementAttributes, \
_typedArray::obj_setSpecialAttributes, \
_typedArray::obj_deleteGeneric, \
_typedArray::obj_deleteProperty, \
_typedArray::obj_deleteElement, \
_typedArray::obj_deleteSpecial, \

View File

@ -145,8 +145,6 @@ struct JS_FRIEND_API(ArrayBuffer) {
static JSBool
obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp);
static JSBool
obj_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict);
static JSBool
obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict);
static JSBool

View File

@ -86,6 +86,20 @@ WeakMapBase::traceAllMappings(WeakMapTracer *tracer)
m->traceMappings(tracer);
}
void
WeakMapBase::resetWeakMapList(JSRuntime *rt)
{
JS_ASSERT(WeakMapNotInList != NULL);
WeakMapBase *m = rt->gcWeakMapList;
rt->gcWeakMapList = NULL;
while (m) {
WeakMapBase *n = m->next;
m->next = WeakMapNotInList;
m = n;
}
}
} /* namespace js */
typedef WeakMap<HeapPtr<JSObject>, HeapValue> ObjectValueMap;

View File

@ -106,11 +106,14 @@ template <class Type> class DefaultMarkPolicy;
// provides default types for WeakMap's TracePolicy template parameter.
template <class Key, class Value> class DefaultTracePolicy;
// The value for the next pointer for maps not in the map list.
static WeakMapBase * const WeakMapNotInList = reinterpret_cast<WeakMapBase *>(1);
// Common base class for all WeakMap specializations. The collector uses this to call
// their markIteratively and sweep methods.
class WeakMapBase {
public:
WeakMapBase(JSObject *memOf) : memberOf(memOf), next(NULL) { }
WeakMapBase(JSObject *memOf) : memberOf(memOf), next(WeakMapNotInList) { }
virtual ~WeakMapBase() { }
void trace(JSTracer *tracer) {
@ -120,9 +123,14 @@ class WeakMapBase {
// known-live WeakMaps to be scanned in the iterative marking phase, by
// markAllIteratively.
JS_ASSERT(!tracer->eagerlyTraceWeakMaps);
JSRuntime *rt = tracer->context->runtime;
next = rt->gcWeakMapList;
rt->gcWeakMapList = this;
// Add ourselves to the list if we are not already in the list. We can already
// be in the list if the weak map is marked more than once due delayed marking.
if (next == WeakMapNotInList) {
JSRuntime *rt = tracer->context->runtime;
next = rt->gcWeakMapList;
rt->gcWeakMapList = this;
}
} else {
// If we're not actually doing garbage collection, the keys won't be marked
// nicely as needed by the true ephemeral marking algorithm --- custom tracers
@ -148,6 +156,9 @@ class WeakMapBase {
// Trace all delayed weak map bindings. Used by the cycle collector.
static void traceAllMappings(WeakMapTracer *tracer);
// Remove everything from the live weak map list.
static void resetWeakMapList(JSRuntime *rt);
protected:
// Instance member functions called by the above. Instantiations of WeakMap override
// these with definitions appropriate for their Key and Value types.
@ -161,7 +172,10 @@ class WeakMapBase {
private:
// Link in a list of WeakMaps to mark iteratively and sweep in this garbage
// collection, headed by JSRuntime::gcWeakMapList.
// collection, headed by JSRuntime::gcWeakMapList. The last element of the list
// has NULL as its next. Maps not in the list have WeakMapNotInList as their
// next. We must distinguish these cases to avoid creating infinite lists
// when a weak map gets traced twice due to delayed marking.
WeakMapBase *next;
};

View File

@ -4990,14 +4990,12 @@ xml_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *att
static JSBool
xml_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
{
JSXML *xml;
jsval idval;
uint32_t index;
JSObject *nameqn;
jsid funid;
idval = IdToJsval(id);
xml = (JSXML *) obj->getPrivate();
Value idval = IdToValue(id);
JSXML *xml = (JSXML *) obj->getPrivate();
if (js_IdIsIndex(id, &index)) {
if (xml->xml_class != JSXML_CLASS_LIST) {
/* See NOTE in spec: this variation is reserved for future use. */
@ -5012,7 +5010,7 @@ xml_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str
if (!nameqn)
return false;
if (!JSID_IS_VOID(funid))
return js_DeleteProperty(cx, obj, funid, rval, false);
return js_DeleteGeneric(cx, obj, funid, rval, false);
DeleteNamedProperty(cx, xml, nameqn,
nameqn->getClass() == &AttributeNameClass);
@ -5025,7 +5023,7 @@ xml_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool str
* property's getter or setter. But now it's time to remove any such
* property, to purge the property cache and remove the scope entry.
*/
if (!obj->nativeEmpty() && !js_DeleteProperty(cx, obj, id, rval, false))
if (!obj->nativeEmpty() && !js_DeleteGeneric(cx, obj, id, rval, false))
return false;
rval->setBoolean(true);
@ -5398,7 +5396,6 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
xml_setPropertyAttributes,
xml_setElementAttributes,
xml_setSpecialAttributes,
xml_deleteGeneric,
xml_deleteProperty,
xml_deleteElement,
xml_deleteSpecial,

View File

@ -3345,14 +3345,18 @@ mjit::Compiler::emitReturn(FrameEntry *fe)
}
/*
* Outside the mjit, activation objects are put by ContextStack::pop*
* members. For JSOP_RETURN, the interpreter only calls popInlineFrame if
* fp != entryFrame since the VM protocol is that Invoke/Execute are
* responsible for pushing/popping the initial frame. The mjit does not
* perform this branch (by instead using a trampoline at the return address
* to handle exiting mjit code) and thus always puts activation objects,
* even on the entry frame. To avoid double-putting, EnterMethodJIT clears
* out the entry frame's activation objects.
* Outside the mjit, activation objects (call objects and arguments objects) are put
* by ContextStack::pop* members. For JSOP_RETURN, the interpreter only calls
* popInlineFrame if fp != entryFrame since the VM protocol is that Invoke/Execute are
* responsible for pushing/popping the initial frame. However, an mjit function
* epilogue doesn't treat the initial StackFrame of its VMFrame specially: it always
* puts activation objects. And furthermore, if the last mjit frame throws, the mjit
* does *not* put the activation objects. So we can't assume any particular state of
* puttedness upon exit from the mjit.
*
* To avoid double-putting, EnterMethodJIT calls updateEpilogueFlags to clear the
* entry frame's hasArgsObj() and hasCallObj() flags if the given objects have already
* been put.
*/
if (script->function()) {
types::TypeScriptNesting *nesting = script->nesting();

View File

@ -1090,7 +1090,7 @@ mjit::EnterMethodJIT(JSContext *cx, StackFrame *fp, void *code, Value *stackLimi
/* See comment in mjit::Compiler::emitReturn. */
if (fp->isFunctionFrame())
fp->markFunctionEpilogueDone();
fp->updateEpilogueFlags();
return ok ? Jaeger_Returned : Jaeger_Throwing;
}

View File

@ -167,11 +167,13 @@ stubs::SetName(VMFrame &f, PropertyName *origName)
* on a prototype property that has a setter.
*/
const Shape *shape = entry->prop;
JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());
if (entry->isOwnPropertyHit() ||
((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) {
((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape))
{
JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());
#ifdef DEBUG
if (entry->isOwnPropertyHit()) {
JS_ASSERT(obj->nativeContains(cx, *shape));
@ -2052,11 +2054,10 @@ stubs::DelElem(VMFrame &f)
if (!obj)
THROW();
jsid id;
if (!FetchElementId(f, obj, f.regs.sp[-1], id, &f.regs.sp[-1]))
THROW();
const Value &propval = f.regs.sp[-1];
Value &rval = f.regs.sp[-2];
if (!obj->deleteGeneric(cx, id, &f.regs.sp[-2], strict))
if (!obj->deleteByValue(cx, propval, &rval, strict))
THROW();
}

View File

@ -1235,7 +1235,6 @@ static const struct ParamPair {
} paramMap[] = {
{"maxBytes", JSGC_MAX_BYTES },
{"maxMallocBytes", JSGC_MAX_MALLOC_BYTES},
{"gcStackpoolLifespan", JSGC_STACKPOOL_LIFESPAN},
{"gcBytes", JSGC_BYTES},
{"gcNumber", JSGC_NUMBER},
};
@ -5311,8 +5310,6 @@ ShellPrincipalsSubsume(JSPrincipals *, JSPrincipals *)
JSPrincipals shellTrustedPrincipals = {
(char *)"[shell trusted principals]",
NULL,
NULL,
1,
NULL, /* nobody should be destroying this */
ShellPrincipalsSubsume

View File

@ -3,4 +3,5 @@ script 11.1.5-01.js
script named-accessor-function.js
script nested-delete-name-in-evalcode.js
script object-literal-accessor-arguments.js
script object-literal-accessor-property-name.js
script string-literal-escape-sequences.js

View File

@ -0,0 +1,30 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var gTestfile = 'object-literal-accessor-property-name.js';
//-----------------------------------------------------------------------------
var BUGNUMBER = 536472;
var summary =
'ES5: { get x(v) { } } and { set x(v, v2) { } } should be syntax errors';
print(BUGNUMBER + ": " + summary);
//-----------------------------------------------------------------------------
({ get "0"() { } });
({ get 0() { } });
({ get 0.0() { } });
({ get 0.() { } });
({ get 1.() { } });
({ get 5.2322341234123() { } });
({ set "0"(q) { } });
({ set 0(q) { } });
({ set 0.0(q) { } });
({ set 0.(q) { } });
({ set 1.(q) { } });
({ set 5.2322341234123(q) { } });
//-----------------------------------------------------------------------------
reportCompare(true, true);

View File

@ -3364,17 +3364,14 @@ static JSBool
DebuggerObject_deleteProperty(JSContext *cx, uintN argc, Value *vp)
{
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "deleteProperty", args, dbg, obj);
Value arg = argc > 0 ? args[0] : UndefinedValue();
jsid id;
if (!ValueToId(cx, arg, &id))
return false;
Value nameArg = argc > 0 ? args[0] : UndefinedValue();
AutoCompartment ac(cx, obj);
if (!ac.enter() || !cx->compartment->wrapId(cx, &id))
if (!ac.enter() || !cx->compartment->wrap(cx, &nameArg))
return false;
ErrorCopier ec(ac, dbg->toJSObject());
return obj->deleteGeneric(cx, id, &args.rval(), false);
return obj->deleteByValue(cx, nameArg, &args.rval(), false);
}
enum SealHelperOp { Seal, Freeze, PreventExtensions };

View File

@ -331,12 +331,6 @@ with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *at
return obj->asWith().object().setSpecialAttributes(cx, sid, attrsp);
}
static JSBool
with_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
{
return obj->asWith().object().deleteGeneric(cx, id, rval, strict);
}
static JSBool
with_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
{
@ -421,7 +415,6 @@ Class js::WithClass = {
with_SetPropertyAttributes,
with_SetElementAttributes,
with_SetSpecialAttributes,
with_DeleteGeneric,
with_DeleteProperty,
with_DeleteElement,
with_DeleteSpecial,

View File

@ -152,13 +152,13 @@ StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
LOWERED_CALL_APPLY |
OVERFLOW_ARGS |
UNDERFLOW_ARGS)) == 0);
JS_ASSERT(script == callee.toFunction()->script());
JS_ASSERT(script == callee.script());
/* Initialize stack frame members. */
flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg;
exec.fun = &callee;
args.nactual = nactual;
scopeChain_ = callee.toFunction()->environment();
scopeChain_ = callee.environment();
ncode_ = NULL;
initPrev(cx);
blockChain_= NULL;
@ -461,7 +461,7 @@ StackFrame::functionEpilogue()
}
inline void
StackFrame::markFunctionEpilogueDone()
StackFrame::updateEpilogueFlags()
{
if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
if (hasArgsObj() && !argsObj().maybeStackFrame()) {
@ -569,7 +569,7 @@ ContextStack::pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &ar
JS_ASSERT(onTop());
JS_ASSERT(regs.sp == args.end());
/* Cannot assert callee == args.callee() since this is called from LeaveTree. */
JS_ASSERT(script == callee.toFunction()->script());
JS_ASSERT(script == callee.script());
/*StackFrame::Flags*/ uint32_t flags = ToFrameFlags(initial);
StackFrame *fp = getCallFrame(cx, REPORT_ERROR, args, &callee, script, &flags);

View File

@ -878,15 +878,15 @@ class StackFrame
* Epilogue for function frames: put any args or call object for the frame
* which may still be live, and maintain type nesting invariants. Note:
* this does not mark the epilogue as having been completed, since the
* frame is about to be popped. Use markFunctionEpilogueDone for this.
* frame is about to be popped. Use updateEpilogueFlags for this.
*/
inline void functionEpilogue();
/*
* Mark any work needed in the function's epilogue as done. This call must
* be followed by a later functionEpilogue.
* If callObj() or argsObj() have already been put, update our flags
* accordingly. This call must be followed by a later functionEpilogue.
*/
inline void markFunctionEpilogueDone();
inline void updateEpilogueFlags();
inline bool maintainNestingState() const;

View File

@ -876,7 +876,6 @@ js::Class XPC_WN_NoHelper_JSClass = {
nsnull, // setAttributes
nsnull, // setElementAttributes
nsnull, // setSpecialAttributes
nsnull, // deleteGeneric
nsnull, // deleteProperty
nsnull, // deleteElement
nsnull, // deleteSpecial

View File

@ -1415,7 +1415,6 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
nsnull, /* setAttributes */ \
nsnull, /* setElementAttributes */ \
nsnull, /* setSpecialAttributes */ \
nsnull, /* deleteGeneric */ \
nsnull, /* deleteProperty */ \
nsnull, /* deleteElement */ \
nsnull, /* deleteSpecial */ \
@ -1453,7 +1452,6 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
nsnull, /* setAttributes */ \
nsnull, /* setElementAttributes */ \
nsnull, /* setSpecialAttributes */ \
nsnull, /* deleteGeneric */ \
nsnull, /* deleteProperty */ \
nsnull, /* deleteElement */ \
nsnull, /* deleteSpecial */ \

View File

@ -194,6 +194,8 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
//switch to page layout
#include "nsGfxCIID.h"
#include "nsObserverService.h"
#include "mozilla/dom/Element.h"
using namespace mozilla;
@ -509,6 +511,18 @@ public:
nsCOMPtr<nsIDocument> mTop;
};
class nsDocumentShownDispatcher : public nsRunnable
{
public:
nsDocumentShownDispatcher(nsCOMPtr<nsIDocument> aDocument)
: mDocument(aDocument) {}
NS_IMETHOD Run();
private:
nsCOMPtr<nsIDocument> mDocument;
};
//------------------------------------------------------------------
// DocumentViewerImpl
@ -2039,6 +2053,10 @@ DocumentViewerImpl::Show(void)
}
}
// Notify observers that a new page has been shown. (But not right now;
// running JS at this time is not safe.)
NS_DispatchToMainThread(new nsDocumentShownDispatcher(mDocument));
return NS_OK;
}
@ -4371,3 +4389,17 @@ DocumentViewerImpl::SetPrintPreviewPresentation(nsIViewManager* aViewManager,
mPresContext = aPresContext;
mPresShell = aPresShell;
}
// Fires the "document-shown" event so that interested parties (right now, the
// mobile browser) are aware of it.
NS_IMETHODIMP
nsDocumentShownDispatcher::Run()
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->NotifyObservers(mDocument, "document-shown", NULL);
}
return NS_OK;
}

View File

@ -101,10 +101,10 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
Log.d(LOGTAG, "creating awesomebar");
setContentView(R.layout.awesomebar_search);
setContentView(R.layout.awesomebar);
if (Build.VERSION.SDK_INT >= 11) {
RelativeLayout actionBarLayout = (RelativeLayout) getLayoutInflater().inflate(R.layout.awesomebar_search_actionbar, null);
RelativeLayout actionBarLayout = (RelativeLayout) getLayoutInflater().inflate(R.layout.awesomebar_search, null);
GeckoActionBar.setBackgroundDrawable(this, getResources().getDrawable(R.drawable.gecko_actionbar_bg));
GeckoActionBar.setDisplayOptions(this, ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM |
@ -405,7 +405,7 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
int groupPosition = exList.getPackedPositionGroup(info.packedPosition);
selectedItem = exList.getExpandableListAdapter().getChild(groupPosition, childPosition);
Map<String, Object> map = (Map<String, Object>)selectedItem;
Map map = (Map)selectedItem;
title = (String)map.get(URLColumns.TITLE);
} else {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
@ -439,10 +439,10 @@ public class AwesomeBar extends Activity implements GeckoEventListener {
if (mContextMenuSubject instanceof Cursor) {
Cursor cursor = (Cursor)mContextMenuSubject;
url = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.URL));
b = (byte[]) cursor.getBlob(cursor.getColumnIndexOrThrow(URLColumns.FAVICON));
b = cursor.getBlob(cursor.getColumnIndexOrThrow(URLColumns.FAVICON));
title = cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.TITLE));
} else if (mContextMenuSubject instanceof Map) {
Map<String, Object> map = (Map<String, Object>)mContextMenuSubject;
Map map = (Map)mContextMenuSubject;
url = (String)map.get(URLColumns.URL);
b = (byte[]) map.get(URLColumns.FAVICON);
title = (String)map.get(URLColumns.TITLE);

View File

@ -479,8 +479,7 @@ public class AwesomeBarTabs extends TabHost {
try {
byte[] bytes = Base64.decode(base64, Base64.DEFAULT);
ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
drawable = (Drawable) Drawable.createFromStream(stream, "src");
drawable = Drawable.createFromStream(stream, "src");
stream.close();
} catch (IllegalArgumentException e) {
Log.i(LOGTAG, "exception while decoding drawable: " + base64, e);

View File

@ -52,6 +52,8 @@ import org.mozilla.gecko.Tab.HistoryEntry;
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.zip.*;
import java.net.URL;
import java.nio.*;
@ -133,7 +135,6 @@ abstract public class GeckoApp
private static GeckoSoftwareLayerClient mSoftwareLayerClient;
private AboutHomeContent mAboutHomeContent;
private static AbsoluteLayout mPluginContainer;
boolean mUserDefinedProfile = false;
public String mLastUri;
public String mLastTitle;
@ -417,8 +418,8 @@ abstract public class GeckoApp
InputStream is = (InputStream) url.getContent();
Drawable drawable = Drawable.createFromStream(is, "src");
mi.setIcon(drawable);
} catch(Exception e) {
Log.e(LOGTAG, "onPrepareOptionsMenu: Unable to set icon", e);
} catch (Exception e) {
Log.w(LOGTAG, "onPrepareOptionsMenu: Unable to set icon", e);
}
}
});
@ -762,24 +763,16 @@ abstract public class GeckoApp
}
public File getProfileDir() {
// XXX: TO-DO read profiles.ini to get the default profile
return getProfileDir("default");
}
public File getProfileDir(final String profileName) {
if (mProfileDir == null && !mUserDefinedProfile) {
File mozDir = new File(GeckoAppShell.sHomeDir, "mozilla");
if (!mozDir.exists()) {
// Profile directory may have been deleted or not created yet.
return null;
}
File[] profiles = mozDir.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith("." + profileName);
}
});
if (profiles != null && profiles.length == 1)
mProfileDir = profiles[0];
if (mProfileDir != null)
return mProfileDir;
try {
mProfileDir = GeckoDirProvider.getProfileDir(mAppContext, profileName);
} catch (IOException ex) {
Log.e(LOGTAG, "Error getting profile dir.", ex);
}
return mProfileDir;
}
@ -1435,6 +1428,19 @@ abstract public class GeckoApp
}
Intent intent = getIntent();
String args = intent.getStringExtra("args");
if (args != null && args.contains("-profile")) {
Pattern p = Pattern.compile("(?:-profile\\s*)(\\w*)(\\s*)");
Matcher m = p.matcher(args);
if (m.find()) {
mProfileDir = new File(m.group(1));
mLastUri = null;
mLastTitle = null;
mLastViewport = null;
mLastScreen = null;
}
}
String uri = intent.getDataString();
String title = uri;
if (uri != null && uri.length() > 0) {
@ -1452,12 +1458,6 @@ abstract public class GeckoApp
if (sGREDir == null)
sGREDir = new File(this.getApplicationInfo().dataDir);
String args = intent.getStringExtra("args");
if (args != null && args.contains("-profile")) {
// XXX: TO-DO set mProfileDir to the path passed in
mUserDefinedProfile = true;
}
prefetchDNS(intent.getData());
sGeckoThread = new GeckoThread(intent, mLastUri, mLastTitle);
@ -1470,7 +1470,7 @@ abstract public class GeckoApp
setContentView(R.layout.gecko_app);
if (Build.VERSION.SDK_INT >= 11) {
mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.gecko_app_actionbar, null);
mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.browser_toolbar, null);
GeckoActionBar.setBackgroundDrawable(this, getResources().getDrawable(R.drawable.gecko_actionbar_bg));
GeckoActionBar.setDisplayOptions(this, ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM |
@ -1524,11 +1524,8 @@ abstract public class GeckoApp
* run experience, perhaps?
*/
mLayerController = new LayerController(this);
mPlaceholderLayerClient = mUserDefinedProfile ? null :
PlaceholderLayerClient.createInstance(this);
if (mPlaceholderLayerClient != null) {
mLayerController.setLayerClient(mPlaceholderLayerClient);
}
mPlaceholderLayerClient = PlaceholderLayerClient.createInstance(this);
mLayerController.setLayerClient(mPlaceholderLayerClient);
mGeckoLayout.addView(mLayerController.getView(), 0);
}
@ -1848,7 +1845,19 @@ abstract public class GeckoApp
mAutoCompletePopup.hide();
if (Build.VERSION.SDK_INT >= 11) {
mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.gecko_app_actionbar, null);
mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.browser_toolbar, null);
Tab tab = Tabs.getInstance().getSelectedTab();
if (tab != null) {
mBrowserToolbar.setTitle(tab.getDisplayTitle());
mBrowserToolbar.setFavicon(tab.getFavicon());
mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
mBrowserToolbar.setProgressVisibility(tab.isLoading());
mBrowserToolbar.setShadowVisibility(!(tab.getURL().startsWith("about:")));
mBrowserToolbar.updateTabs(Tabs.getInstance().getCount());
}
GeckoActionBar.setBackgroundDrawable(this, getResources().getDrawable(R.drawable.gecko_actionbar_bg));
GeckoActionBar.setCustomView(mAppContext, mBrowserToolbar);
}
}
@ -2377,10 +2386,10 @@ class PluginLayoutParams extends AbsoluteLayout.LayoutParams
}
public static PluginLayoutParams create(int aX, int aY, int aWidth, int aHeight, float aResolution) {
aX = (int)Math.round(aX * aResolution);
aY = (int)Math.round(aY * aResolution);
aWidth = (int)Math.round(aWidth * aResolution);
aHeight = (int)Math.round(aHeight * aResolution);
aX = Math.round(aX * aResolution);
aY = Math.round(aY * aResolution);
aWidth = Math.round(aWidth * aResolution);
aHeight = Math.round(aHeight * aResolution);
return new PluginLayoutParams(aX, aY, aWidth, aHeight, aResolution);
}
@ -2398,10 +2407,10 @@ class PluginLayoutParams extends AbsoluteLayout.LayoutParams
}
public void reset(int aX, int aY, int aWidth, int aHeight, float aResolution) {
x = mOriginalX = (int)Math.round(aX * aResolution);
y = mOriginalY = (int)Math.round(aY * aResolution);
width = mOriginalWidth = (int)Math.round(aWidth * aResolution);
height = mOriginalHeight = (int)Math.round(aHeight * aResolution);
x = mOriginalX = Math.round(aX * aResolution);
y = mOriginalY = Math.round(aY * aResolution);
width = mOriginalWidth = Math.round(aWidth * aResolution);
height = mOriginalHeight = Math.round(aHeight * aResolution);
mLastResolution = mOriginalResolution = aResolution;
clampToMaxSize();
@ -2416,8 +2425,8 @@ class PluginLayoutParams extends AbsoluteLayout.LayoutParams
if (!FloatUtils.fuzzyEquals(mLastResolution, aResolution)) {
float scaleFactor = aResolution / mOriginalResolution;
width = (int)Math.round(scaleFactor * mOriginalWidth);
height = (int)Math.round(scaleFactor * mOriginalHeight);
width = Math.round(scaleFactor * mOriginalWidth);
height = Math.round(scaleFactor * mOriginalHeight);
mLastResolution = aResolution;
clampToMaxSize();
@ -2428,8 +2437,8 @@ class PluginLayoutParams extends AbsoluteLayout.LayoutParams
PointF targetOrigin = targetViewport.getOrigin();
PointF hostOrigin = hostViewport.getOrigin();
Point offset = new Point((int)Math.round(hostOrigin.x - targetOrigin.x),
(int)Math.round(hostOrigin.y - targetOrigin.y));
Point offset = new Point(Math.round(hostOrigin.x - targetOrigin.x),
Math.round(hostOrigin.y - targetOrigin.y));
reposition(offset, hostViewport.getZoomFactor());
}

View File

@ -302,17 +302,19 @@ public class GeckoAppShell
// libxul will depend on. Not ideal.
GeckoApp geckoApp = GeckoApp.mAppContext;
String homeDir;
sHomeDir = GeckoDirProvider.getFilesDir(geckoApp);
homeDir = sHomeDir.getPath();
// handle the application being moved to phone from sdcard
File profileDir = new File(homeDir, "mozilla");
File oldHome = new File("/data/data/" +
GeckoApp.mAppContext.getPackageName() + "/mozilla");
if (oldHome.exists())
moveDir(oldHome, profileDir);
if (Build.VERSION.SDK_INT < 8 ||
geckoApp.getApplication().getPackageResourcePath().startsWith("/data") ||
geckoApp.getApplication().getPackageResourcePath().startsWith("/system")) {
sHomeDir = geckoApp.getFilesDir();
homeDir = sHomeDir.getPath();
// handle the application being moved to phone from sdcard
File profileDir = new File(homeDir, "mozilla");
File oldHome = new File("/data/data/" +
GeckoApp.mAppContext.getPackageName() + "/mozilla");
if (oldHome.exists())
moveDir(oldHome, profileDir);
if (Build.VERSION.SDK_INT >= 8) {
File extHome = geckoApp.getExternalFilesDir(null);
File extProf = new File (extHome, "mozilla");
@ -320,15 +322,6 @@ public class GeckoAppShell
moveDir(extProf, profileDir);
}
} else {
sHomeDir = geckoApp.getExternalFilesDir(null);
homeDir = sHomeDir.getPath();
// handle the application being moved to phone from sdcard
File profileDir = new File(homeDir, "mozilla");
File oldHome = new File("/data/data/" +
GeckoApp.mAppContext.getPackageName() + "/mozilla");
if (oldHome.exists())
moveDir(oldHome, profileDir);
File intHome = geckoApp.getFilesDir();
File intProf = new File(intHome, "mozilla");
if (intHome != null && intProf != null && intProf.exists())

View File

@ -0,0 +1,215 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009-2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Wes Johnston <wjohnston@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import java.io.File;
import java.io.FileFilter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.Void;
import java.util.Date;
import java.util.Random;
import java.util.Map;
import java.util.HashMap;
abstract public class GeckoDirProvider
{
private static final String LOGTAG = "GeckoDirProvider";
private static HashMap<String, File> mProfileDirs = new HashMap<String, File>();
/**
* Get the default Mozilla profile directory for a given Activity instance.
*
* @param aContext
* The context for the activity. Must not be null
* @return
* The profile directory.
*/
static public File getProfileDir(final Context aContext)
throws IllegalArgumentException, IOException {
// XXX: TO-DO read profiles.ini to get the default profile. bug 71530
return getProfileDir(aContext, "default");
}
/**
* Get a particular profile directory for a given Activity.
* If no profile directory currently exists, will create and return a profile directory.
* Otherwise will return null;
*
* @param aContext
* The context for the Activity we want a profile for. Must not be null.
* @param aProfileName
* The name of the profile to open. Must be a non-empty string
* @return
* The profile directory.
*/
static public File getProfileDir(final Context aContext, final String aProfileName)
throws IllegalArgumentException, IOException {
if (aContext == null)
throw new IllegalArgumentException("Must provide a valid context");
if (aProfileName == null || aProfileName.trim().equals(""))
throw new IllegalArgumentException("Profile name: '" + aProfileName + "' is not valid");
Log.i(LOGTAG, "Get profile dir for " + aProfileName);
synchronized (mProfileDirs) {
File profileDir = mProfileDirs.get(aProfileName);
if (profileDir != null)
return profileDir;
// we do not want to call File.exists on startup, so we first don't
// attempt to create the mozilla directory.
File mozDir = GeckoDirProvider.ensureMozillaDirectory(aContext);
profileDir = GeckoDirProvider.getProfileDir(mozDir, aProfileName);
if (profileDir == null) {
// Throws if cannot create.
profileDir = GeckoDirProvider.createProfileDir(mozDir, aProfileName);
}
mProfileDirs.put(aProfileName, profileDir);
return profileDir;
}
}
private static File getProfileDir(final File aRoot, final String aProfileName)
throws IllegalArgumentException {
if (aRoot == null)
throw new IllegalArgumentException("Invalid root directory");
File[] profiles = aRoot.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.getName().endsWith("." + aProfileName);
}
});
if (profiles != null && profiles.length > 0)
return profiles[0];
return null;
}
private static File ensureMozillaDirectory(final Context aContext)
throws IOException, IllegalArgumentException {
if (aContext == null)
throw new IllegalArgumentException("Must provide a valid context");
File filesDir = GeckoDirProvider.getFilesDir(aContext);
File mozDir = new File(filesDir, "mozilla");
if (!mozDir.exists()) {
if (!mozDir.mkdir())
throw new IOException("Unable to create mozilla directory at " + mozDir.getPath());
}
return mozDir;
}
static final char kTable[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
private static File createProfileDir(final File aRootDir, final String aProfileName)
throws IOException, IllegalArgumentException {
if (aRootDir == null)
throw new IllegalArgumentException("Must provide a valid root directory");
if (aProfileName == null || aProfileName.trim().equals(""))
throw new IllegalArgumentException("Profile name: '" + aProfileName + "' is not valid");
// XXX: TO-DO If we already have an ini file, we should append the
// new profile information to it. For now we just throw an exception.
// see bug 715391
final File profileIni = new File(aRootDir, "profiles.ini");
if (profileIni.exists())
throw new IOException("Can't create new profiles");
String saltedName = saltProfileName(aProfileName);
File profile = new File(aRootDir, saltedName);
while (profile.exists()) {
saltedName = saltProfileName(aProfileName);
profile = new File(aRootDir, saltedName);
}
if (!profile.mkdir())
throw new IOException("Unable to create profile at " + profile.getPath());
Log.i(LOGTAG, "Creating new profile at " + profile.getPath());
final String fSaltedName = saltedName;
FileWriter outputStream = new FileWriter(profileIni, true);
outputStream.write("[General]\n" +
"StartWithLastProfile=1\n" +
"\n" +
"[Profile0]\n" +
"Name=" + aProfileName + "\n" +
"IsRelative=1\n" +
"Path=" + fSaltedName + "\n" +
"Default=1\n");
outputStream.close();
return profile;
}
private static String saltProfileName(final String aName) {
Random randomGenerator = new Random(System.nanoTime());
StringBuilder salt = new StringBuilder();
int i;
for (i = 0; i < 8; ++i)
salt.append(kTable[randomGenerator.nextInt(kTable.length)]);
salt.append(".");
return salt.append(aName).toString();
}
public static File getFilesDir(final Context aContext) {
if (aContext == null)
throw new IllegalArgumentException("Must provide a valid context");
if (Build.VERSION.SDK_INT < 8 ||
aContext.getPackageResourcePath().startsWith("/data") ||
aContext.getPackageResourcePath().startsWith("/system")) {
return aContext.getFilesDir();
}
return aContext.getExternalFilesDir(null);
}
}

View File

@ -50,14 +50,14 @@ DIST_FILES = package-name.txt
SYNC_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/java-sources.mn | tr '\n' ' ';)
SYNC_PP_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/preprocess-sources.mn | tr '\n' ' ';)
SYNC_THIRDPARTY_JAVA_FILES=$(shell cat $(topsrcdir)/mobile/android/sync/java-third-party-sources.mn | tr '\n' ' ';)
SYNC_RES_DRAWABLE=$(shell cat $(topsrcdir)/mobile/android/sync/android-drawable-resources.mn | tr '\n' ' ';)
SYNC_RES_LAYOUT=$(shell cat $(topsrcdir)/mobile/android/sync/android-layout-resources.mn | tr '\n' ' ';)
SYNC_RES_VALUES=$(shell cat $(topsrcdir)/mobile/android/sync/android-values-resources.mn | tr '\n' ' ';)
SYNC_RES_XML=res/xml/sync_authenticator.xml
SYNC_PP_RES_XML=res/xml/sync_syncadapter.xml
JAVAFILES = \
$(SYNC_JAVA_FILES) \
FENNEC_JAVA_FILES = \
AboutHomeContent.java \
AlertNotification.java \
AutoCompletePopup.java \
@ -78,6 +78,7 @@ JAVAFILES = \
GeckoAsyncTask.java \
GeckoBatteryManager.java \
GeckoConnectivityReceiver.java \
GeckoDirProvider.java \
GeckoEvent.java \
GeckoEventListener.java \
GeckoInputConnection.java \
@ -123,8 +124,7 @@ JAVAFILES = \
ui/PanZoomController.java \
$(NULL)
PROCESSEDJAVAFILES = \
$(SYNC_PP_JAVA_FILES) \
FENNEC_PP_JAVA_FILES = \
App.java \
LauncherShortcuts.java \
NotificationHandler.java \
@ -159,7 +159,8 @@ DEFINES += \
GARBAGE += \
AndroidManifest.xml \
classes.dex \
$(PROCESSEDJAVAFILES) \
$(FENNEC_PP_JAVA_FILES) \
$(SYNC_PP_JAVA_FILES) \
gecko.ap_ \
res/values/strings.xml \
R.java \
@ -195,6 +196,7 @@ endif
RES_LAYOUT = \
$(SYNC_RES_LAYOUT) \
res/layout/autocomplete_list_item.xml \
res/layout/awesomebar.xml \
res/layout/awesomebar_header_row.xml \
res/layout/awesomebar_row.xml \
res/layout/awesomebar_search.xml \
@ -221,10 +223,8 @@ RES_LAYOUT = \
$(NULL)
RES_LAYOUT_V11 = \
res/layout-v11/awesomebar_search.xml \
res/layout-v11/awesomebar_search_actionbar.xml \
res/layout-v11/awesomebar.xml \
res/layout-v11/gecko_app.xml \
res/layout-v11/gecko_app_actionbar.xml \
$(NULL)
RES_VALUES = \
@ -467,7 +467,7 @@ RES_MENU = \
JAVA_CLASSPATH = $(ANDROID_SDK)/android.jar
ifdef MOZ_CRASHREPORTER
PROCESSEDJAVAFILES += CrashReporter.java
FENNEC_PP_JAVA_FILES += CrashReporter.java
MOZ_ANDROID_DRAWABLES += mobile/android/base/resources/drawable/crash_reporter.png
RES_LAYOUT += res/layout/crash_reporter.xml
endif
@ -558,9 +558,10 @@ include $(topsrcdir)/config/android-common.mk
# Sync dependencies are provided in a single jar. Sync classes themselves are delivered as source,
# because Android resource classes must be compiled together in order to avoid overlapping resource
# indices.
classes.dex: $(JAVAFILES) $(PROCESSEDJAVAFILES) R.java
classes.dex: $(FENNEC_JAVA_FILES) $(FENNEC_PP_JAVA_FILES) $(SYNC_JAVA_FILES) $(SYNC_PP_JAVA_FILES) $(SYNC_THIRDPARTY_JAVA_FILES) R.java
$(NSINSTALL) -D classes
$(JAVAC) $(JAVAC_FLAGS) -Xlint:unchecked -Xlint:deprecation -d classes $(addprefix $(srcdir)/,$(JAVAFILES)) $(PROCESSEDJAVAFILES) R.java
$(JAVAC) $(JAVAC_FLAGS) -d classes $(addprefix $(srcdir)/,$(SYNC_THIRDPARTY_JAVA_FILES))
$(JAVAC) $(JAVAC_FLAGS) -Xlint:all,-deprecation,-fallthrough -d classes -classpath classes $(addprefix $(srcdir)/,$(FENNEC_JAVA_FILES)) $(FENNEC_PP_JAVA_FILES) $(addprefix $(srcdir)/,$(SYNC_JAVA_FILES)) $(SYNC_PP_JAVA_FILES) R.java
$(DX) --dex --output=$@ classes
PP_RES_XML=$(SYNC_PP_RES_XML)
@ -569,7 +570,7 @@ $(PP_RES_XML): $(subst res/,$(srcdir)/resources/, $(PP_RES_XML).in)
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
AndroidManifest.xml $(PROCESSEDJAVAFILES) package-name.txt: % : %.in
AndroidManifest.xml $(FENNEC_PP_JAVA_FILES) $(SYNC_PP_JAVA_FILES) package-name.txt: % : %.in
mkdir -p db sync/repositories/android
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@

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