Merge jsdbg2 to mozilla-inbound. See bug 672829.

This commit is contained in:
Jason Orendorff 2011-08-13 13:29:18 -05:00
commit ee1e3d9a60
187 changed files with 5249 additions and 1865 deletions

View File

@ -1,8 +1,8 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1311096050000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1311891123000">
<emItems>
<emItem blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
<versionRange minVersion="0.1" maxVersion="4.3.0.00" severity="1">
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
</versionRange>
</emItem>
<emItem blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}">
@ -30,7 +30,7 @@
</versionRange>
</emItem>
<emItem blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}">
<versionRange minVersion="0.1" maxVersion="4.3.0.00" severity="1">
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
</versionRange>
</emItem>
<emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
@ -61,7 +61,7 @@
</versionRange>
</emItem>
<emItem blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
<versionRange minVersion="0.1" maxVersion="4.3.0.00" severity="1">
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
</versionRange>
</emItem>
<emItem blockID="i23" id="firefox@bandoo.com">

View File

@ -74,6 +74,11 @@ pref("extensions.blocklist.itemURL", "https://addons.mozilla.org/%LOCALE%/%APP%/
pref("extensions.update.autoUpdateDefault", true);
// Disable add-ons installed into the shared user and shared system areas by
// default. This does not include the application directory. See the SCOPE
// constants in AddonManager.jsm for values to use here
pref("extensions.autoDisableScopes", 10);
// Dictionary download preference
pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/firefox/dictionaries/");

View File

@ -588,6 +588,7 @@ function startTest() {
iframe = subwindow.document.getElementById("test-iframe");
textarea = subwindow.document.getElementById("test-textarea");
contenteditable = subwindow.document.getElementById("test-contenteditable");
contenteditable.focus(); // content editable needs to be focused to enable spellcheck
inputspell = subwindow.document.getElementById("test-input-spellcheck");
pagemenu = subwindow.document.getElementById("test-pagemenu");

View File

@ -51,6 +51,7 @@ const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
Cu.import("resource://gre/modules/NetUtil.jsm");
@ -399,6 +400,21 @@ BrowserGlue.prototype = {
// been warned about them yet, open the plugins update page.
if (Services.prefs.getBoolPref(PREF_PLUGINS_NOTIFYUSER))
this._showPluginUpdatePage();
// For any add-ons that were installed disabled and can be enabled offer
// them to the user
var win = this.getMostRecentBrowserWindow();
var browser = win.gBrowser;
var changedIDs = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED);
AddonManager.getAddonsByIDs(changedIDs, function(aAddons) {
aAddons.forEach(function(aAddon) {
// If the add-on isn't user disabled or can't be enabled then skip it
if (!aAddon.userDisabled || !(aAddon.permissions & AddonManager.PERM_CAN_ENABLE))
return;
browser.selectedTab = browser.addTab("about:newaddon?id=" + aAddon.id);
})
});
},
_onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {

View File

@ -741,7 +741,6 @@ toolbar[mode="icons"] #zoom-out-button {
toolbar[mode="icons"] #zoom-in-button {
-moz-border-start: none;
-moz-margin-start: 0;
height: 16px;
}
#zoom-out-button:-moz-locale-dir(ltr),

View File

@ -1081,6 +1081,7 @@ endif
ifdef DTRACE_PROBE_OBJ
EXTRA_DEPS += $(DTRACE_PROBE_OBJ)
OBJS += $(DTRACE_PROBE_OBJ)
endif
$(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
@ -1121,8 +1122,8 @@ ifdef HAVE_DTRACE
ifndef XP_MACOSX
ifdef DTRACE_PROBE_OBJ
ifndef DTRACE_LIB_DEPENDENT
$(DTRACE_PROBE_OBJ): $(OBJS)
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(OBJS)
$(DTRACE_PROBE_OBJ):
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ)
endif
endif
endif
@ -1144,7 +1145,7 @@ endif
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
@$(RM) $(DTRACE_PROBE_OBJ)
else # ! DTRACE_LIB_DEPENDENT
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
endif # DTRACE_LIB_DEPENDENT
@$(call CHECK_STDCXX,$@)

View File

@ -7593,6 +7593,18 @@ if test -n "$JS_GC_ZEAL"; then
AC_DEFINE(JS_GC_ZEAL)
fi
dnl ========================================================
dnl JS opt-mode assertions and minidump instrumentation
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(js-diagnostics,
[ --enable-js-diagnostics
Enable JS diagnostic assertions and breakpad data],
JS_CRASH_DIAGNOSTICS=1,
JS_CRASH_DIAGNOSTICS= )
if test -n "$JS_CRASH_DIAGNOSTICS"; then
AC_DEFINE(JS_CRASH_DIAGNOSTICS)
fi
dnl ======================================================
dnl = Enable compiling with ccache
dnl ======================================================

View File

@ -944,6 +944,31 @@ public:
*/
nsIContent* GetEditingHost();
/**
* Determing language. Look at the nearest ancestor element that has a lang
* attribute in the XML namespace or is an HTML element and has a lang in
* no namespace attribute.
*/
void GetLang(nsAString& aResult) const {
for (const nsIContent* content = this; content; content = content->GetParent()) {
if (content->GetAttrCount() > 0) {
// xml:lang has precedence over lang on HTML elements (see
// XHTML1 section C.7).
PRBool hasAttr = content->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang,
aResult);
if (!hasAttr && content->IsHTML()) {
hasAttr = content->GetAttr(kNameSpaceID_None, nsGkAtoms::lang,
aResult);
}
NS_ASSERTION(hasAttr || aResult.IsEmpty(),
"GetAttr that returns false should not make string non-empty");
if (hasAttr) {
return;
}
}
}
}
// Overloaded from nsINode
virtual already_AddRefed<nsIURI> GetBaseURI() const;

View File

@ -90,6 +90,8 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::ALLOW_SCRIPT },
{ "addons", "chrome://mozapps/content/extensions/extensions.xul",
nsIAboutModule::ALLOW_SCRIPT },
{ "newaddon", "chrome://mozapps/content/extensions/newaddon.xul",
nsIAboutModule::ALLOW_SCRIPT },
{ "support", "chrome://global/content/aboutSupport.xhtml",
nsIAboutModule::ALLOW_SCRIPT }
};

View File

@ -212,6 +212,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "memory", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "newaddon", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "support", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_URI_LOADER_CONTRACTID, &kNS_URI_LOADER_CID },
{ NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &kNS_DOCUMENTLOADER_SERVICE_CID },

View File

@ -88,6 +88,11 @@ EXPORTS = \
nsDOMMemoryReporter.h \
$(NULL)
EXPORTS_NAMESPACES = mozilla/dom
EXPORTS_mozilla/dom = \
StructuredCloneTags.h \
$(NULL)
CPPSRCS = \
nsBarProps.cpp \
nsDOMException.cpp \

View File

@ -0,0 +1,55 @@
/* ***** 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 Structured Clone Code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Kyle Huey <me@kylehuey.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 ***** */
#ifndef StructuredCloneTags_h__
#define StructuredCloneTags_h__
#include "jsapi.h"
namespace mozilla {
namespace dom {
enum StructuredCloneTags {
SCTAG_BASE = JS_SCTAG_USER_MIN,
SCTAG_DOM_BLOB,
SCTAG_DOM_FILELIST,
SCTAG_DOM_MAX
};
} // namespace dom
} // namespace mozilla
#endif // StructuredCloneTags_h__

View File

@ -179,6 +179,7 @@
#include "nsCSSProps.h"
#include "nsFileDataProtocolHandler.h"
#include "nsIDOMFile.h"
#include "nsIDOMFileList.h"
#include "nsIURIFixup.h"
#include "mozilla/FunctionTimer.h"
#include "nsCDefaultURIFixup.h"
@ -240,6 +241,8 @@
#include "mozilla/dom/indexedDB/IDBFactory.h"
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "nsRefreshDriver.h"
#include "mozAutoDocUpdate.h"
@ -5911,7 +5914,6 @@ nsGlobalWindow::CallerInnerWindow()
return static_cast<nsGlobalWindow*>(win.get());
}
/**
* Class used to represent events generated by calls to Window.postMessage,
* which asynchronously creates and dispatches events.
@ -5949,6 +5951,12 @@ class PostMessageEvent : public nsRunnable
aBuffer.steal(&mMessage, &mMessageLen);
}
bool StoreISupports(nsISupports* aSupports)
{
mSupportsArray.AppendElement(aSupports);
return true;
}
private:
nsRefPtr<nsGlobalWindow> mSource;
nsString mCallerOrigin;
@ -5957,8 +5965,102 @@ class PostMessageEvent : public nsRunnable
nsRefPtr<nsGlobalWindow> mTargetWindow;
nsCOMPtr<nsIURI> mProvidedOrigin;
PRBool mTrustedCaller;
nsTArray<nsCOMPtr<nsISupports> > mSupportsArray;
};
namespace {
struct StructuredCloneInfo {
PostMessageEvent* event;
PRBool subsumes;
};
static JSObject*
PostMessageReadStructuredClone(JSContext* cx,
JSStructuredCloneReader* reader,
uint32 tag,
uint32 data,
void* closure)
{
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
NS_ASSERTION(scInfo, "Must have scInfo!");
if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
NS_ASSERTION(!data, "Data should be empty");
nsISupports* supports;
if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
JSObject* global = JS_GetGlobalForObject(cx, JS_GetScopeChain(cx));
if (global) {
jsval val;
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports,
&val,
getter_AddRefs(wrapper)))) {
return JSVAL_TO_OBJECT(val);
}
}
}
}
const JSStructuredCloneCallbacks* runtimeCallbacks =
cx->runtime->structuredCloneCallbacks;
if (runtimeCallbacks) {
return runtimeCallbacks->read(cx, reader, tag, data, nsnull);
}
return JS_FALSE;
}
static JSBool
PostMessageWriteStructuredClone(JSContext* cx,
JSStructuredCloneWriter* writer,
JSObject* obj,
void *closure)
{
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
NS_ASSERTION(scInfo, "Must have scInfo!");
nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
nsContentUtils::XPConnect()->
GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
if (wrappedNative) {
PRUint32 scTag = 0;
nsISupports* supports = wrappedNative->Native();
nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
if (blob && scInfo->subsumes)
scTag = SCTAG_DOM_BLOB;
nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
if (list && scInfo->subsumes)
scTag = SCTAG_DOM_FILELIST;
if (scTag)
return JS_WriteUint32Pair(writer, scTag, 0) &&
JS_WriteBytes(writer, &supports, sizeof(supports)) &&
scInfo->event->StoreISupports(supports);
}
const JSStructuredCloneCallbacks* runtimeCallbacks =
cx->runtime->structuredCloneCallbacks;
if (runtimeCallbacks) {
return runtimeCallbacks->write(cx, writer, obj, nsnull);
}
return JS_FALSE;
}
JSStructuredCloneCallbacks kPostMessageCallbacks = {
PostMessageReadStructuredClone,
PostMessageWriteStructuredClone,
nsnull
};
} // anonymous namespace
NS_IMETHODIMP
PostMessageEvent::Run()
{
@ -6046,8 +6148,10 @@ PostMessageEvent::Run()
jsval messageData;
{
JSAutoRequest ar(cx);
StructuredCloneInfo scInfo;
scInfo.event = this;
if (!buffer.read(cx, &messageData, nsnull))
if (!buffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo))
return NS_ERROR_DOM_DATA_CLONE_ERR;
}
@ -6173,8 +6277,14 @@ nsGlobalWindow::PostMessageMoz(const jsval& aMessage,
// We *must* clone the data here, or the jsval could be modified
// by script
JSAutoStructuredCloneBuffer buffer;
StructuredCloneInfo scInfo;
scInfo.event = event;
if (!buffer.write(aCx, aMessage, nsnull, nsnull))
nsIPrincipal* principal = GetPrincipal();
if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)))
return NS_ERROR_DOM_DATA_CLONE_ERR;
if (!buffer.write(aCx, aMessage, &kPostMessageCallbacks, &scInfo))
return NS_ERROR_DOM_DATA_CLONE_ERR;
event->SetJSData(buffer);

View File

@ -42,11 +42,15 @@
#include "nsEditorSpellCheck.h"
#include "nsStyleUtil.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsITextServicesDocument.h"
#include "nsISpellChecker.h"
#include "nsISelection.h"
#include "nsIDOMRange.h"
#include "nsIEditor.h"
#include "nsIHTMLEditor.h"
#include "nsIComponentManager.h"
#include "nsServiceManagerUtils.h"
@ -54,6 +58,7 @@
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsITextServicesFilter.h"
#include "nsUnicharUtils.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
@ -183,61 +188,9 @@ nsEditorSpellCheck::InitSpellChecker(nsIEditor* aEditor, PRBool aEnableSelection
rv = mSpellChecker->SetDocument(tsDoc, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
// Tell the spellchecker what dictionary to use:
nsAdoptingString dictName =
Preferences::GetLocalizedString("spellchecker.dictionary");
if (dictName.IsEmpty())
{
// Prefs didn't give us a dictionary name, so just get the current
// locale and use that as the default dictionary name!
nsCOMPtr<nsIXULChromeRegistry> packageRegistry =
mozilla::services::GetXULChromeRegistryService();
if (packageRegistry) {
nsCAutoString utf8DictName;
rv = packageRegistry->GetSelectedLocale(NS_LITERAL_CSTRING("global"),
utf8DictName);
AppendUTF8toUTF16(utf8DictName, dictName);
}
}
PRBool setDictionary = PR_FALSE;
if (NS_SUCCEEDED(rv) && !dictName.IsEmpty()) {
rv = SetCurrentDictionary(dictName.get());
// fall back to "en-US" if the current locale doesn't have a dictionary.
if (NS_FAILED(rv)) {
rv = SetCurrentDictionary(NS_LITERAL_STRING("en-US").get());
}
if (NS_SUCCEEDED(rv))
setDictionary = PR_TRUE;
}
// If there was no dictionary specified by spellchecker.dictionary and setting it to the
// locale dictionary didn't work, try to use the first dictionary we find. This helps when
// the first dictionary is installed
if (! setDictionary) {
nsTArray<nsString> dictList;
rv = mSpellChecker->GetDictionaryList(&dictList);
NS_ENSURE_SUCCESS(rv, rv);
if (dictList.Length() > 0) {
rv = SetCurrentDictionary(dictList[0].get());
if (NS_SUCCEEDED(rv))
SaveDefaultDictionary();
}
}
// If an error was thrown while checking the dictionary pref, just
// fail silently so that the spellchecker dialog is allowed to come
// up. The user can manually reset the language to their choice on
// the dialog if it is wrong.
DeleteSuggestedWordList();
// do not fail if UpdateCurrentDictionary fails because this method may
// succeed later.
UpdateCurrentDictionary(aEditor);
return NS_OK;
}
@ -439,14 +392,6 @@ nsEditorSpellCheck::UninitSpellChecker()
{
NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED);
// we preserve the last selected language, but ignore errors so we continue
// to uninitialize
#ifdef DEBUG
nsresult rv =
#endif
SaveDefaultDictionary();
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to set default dictionary");
// Cleanup - kill the spell checker
DeleteSuggestedWordList();
mDictionaryList.Clear();
@ -489,3 +434,124 @@ nsEditorSpellCheck::DeleteSuggestedWordList()
mSuggestedWordIndex = 0;
return NS_OK;
}
NS_IMETHODIMP
nsEditorSpellCheck::UpdateCurrentDictionary(nsIEditor* aEditor)
{
nsresult rv;
// Tell the spellchecker what dictionary to use:
nsAutoString dictName;
// First, try to get language with html5 algorithm
nsAutoString editorLang;
nsCOMPtr<nsIContent> rootContent;
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
if (htmlEditor) {
rootContent = htmlEditor->GetActiveEditingHost();
} else {
nsCOMPtr<nsIDOMElement> rootElement;
rv = aEditor->GetRootElement(getter_AddRefs(rootElement));
NS_ENSURE_SUCCESS(rv, rv);
rootContent = do_QueryInterface(rootElement);
}
NS_ENSURE_TRUE(rootContent, NS_ERROR_FAILURE);
rootContent->GetLang(editorLang);
if (editorLang.IsEmpty()) {
nsCOMPtr<nsIDocument> doc = rootContent->GetCurrentDoc();
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
doc->GetContentLanguage(editorLang);
}
if (!editorLang.IsEmpty()) {
dictName.Assign(editorLang);
}
// otherwise, get language from preferences
if (dictName.IsEmpty()) {
dictName.Assign(Preferences::GetLocalizedString("spellchecker.dictionary"));
}
if (dictName.IsEmpty())
{
// Prefs didn't give us a dictionary name, so just get the current
// locale and use that as the default dictionary name!
nsCOMPtr<nsIXULChromeRegistry> packageRegistry =
mozilla::services::GetXULChromeRegistryService();
if (packageRegistry) {
nsCAutoString utf8DictName;
rv = packageRegistry->GetSelectedLocale(NS_LITERAL_CSTRING("global"),
utf8DictName);
AppendUTF8toUTF16(utf8DictName, dictName);
}
}
SetCurrentDictionary(NS_LITERAL_STRING("").get());
if (NS_SUCCEEDED(rv) && !dictName.IsEmpty()) {
rv = SetCurrentDictionary(dictName.get());
if (NS_FAILED(rv)) {
// required dictionary was not available. Try to get a dictionary
// matching at least language part of dictName: If required dictionary is
// "aa-bb", we try "aa", then we try any available dictionary aa-XX
nsAutoString langCode;
PRInt32 dashIdx = dictName.FindChar('-');
if (dashIdx != -1) {
langCode.Assign(Substring(dictName, 0, dashIdx));
// try to use langCode
rv = SetCurrentDictionary(langCode.get());
} else {
langCode.Assign(dictName);
}
if (NS_FAILED(rv)) {
// loop over avaible dictionaries; if we find one with required
// language, use it
nsTArray<nsString> dictList;
rv = mSpellChecker->GetDictionaryList(&dictList);
NS_ENSURE_SUCCESS(rv, rv);
nsDefaultStringComparator comparator;
PRInt32 i, count = dictList.Length();
for (i = 0; i < count; i++) {
nsAutoString dictStr(dictList.ElementAt(i));
if (nsStyleUtil::DashMatchCompare(dictStr, langCode, comparator) &&
NS_SUCCEEDED(SetCurrentDictionary(dictStr.get()))) {
break;
}
}
}
}
}
// If we have not set dictionary, and the editable element doesn't have a
// lang attribute, we try to get a dictionary. First try, en-US. If it does
// not work, pick the first one.
if (editorLang.IsEmpty()) {
nsAutoString currentDictonary;
rv = mSpellChecker->GetCurrentDictionary(currentDictonary);
if (NS_FAILED(rv) || currentDictonary.IsEmpty()) {
rv = SetCurrentDictionary(NS_LITERAL_STRING("en-US").get());
if (NS_FAILED(rv)) {
nsTArray<nsString> dictList;
rv = mSpellChecker->GetDictionaryList(&dictList);
if (NS_SUCCEEDED(rv) && dictList.Length() > 0) {
SetCurrentDictionary(dictList[0].get());
}
}
}
}
// If an error was thrown while setting the dictionary, just
// fail silently so that the spellchecker dialog is allowed to come
// up. The user can manually reset the language to their choice on
// the dialog if it is wrong.
DeleteSuggestedWordList();
return NS_OK;
}

View File

@ -41,7 +41,7 @@
interface nsIEditor;
interface nsITextServicesFilter;
[scriptable, uuid(90c93610-c116-44ab-9793-62dccb9f43ce)]
[scriptable, uuid(803ff0dd-07f2-4438-b3a6-ab9c2fe4e1dd)]
interface nsIEditorSpellCheck : nsISupports
{
@ -188,4 +188,10 @@ interface nsIEditorSpellCheck : nsISupports
*/
boolean CheckCurrentWordNoSuggest(in wstring suggestedWord);
/**
* Update the dictionary in use to be sure it corresponds to what the editor
* needs.
*/
void UpdateCurrentDictionary(in nsIEditor editor);
};

View File

@ -42,6 +42,7 @@
#include "domstubs.idl"
interface nsIAtom;
interface nsIContent;
interface nsISupportsArray;
interface nsISelection;
interface nsIContentFilter;
@ -51,7 +52,7 @@ interface nsIContentFilter;
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1)
%}
[scriptable, uuid(c964b8b0-e9e8-11df-9492-0800200c9a66)]
[scriptable, uuid(d58f35a7-c269-4292-b9aa-a79e200a7c99)]
interface nsIHTMLEditor : nsISupports
{
@ -613,5 +614,11 @@ interface nsIHTMLEditor : nsISupports
* Checks whether a BR node is visible to the user.
*/
boolean breakIsVisible(in nsIDOMNode aNode);
/**
* Get an active editor's editing host in DOM window. If this editor isn't
* active in the DOM window, this returns NULL.
*/
[noscript, notxpcom] nsIContent GetActiveEditingHost();
};

View File

@ -5311,3 +5311,12 @@ nsEditor::BeginKeypressHandling(nsIDOMNSEvent* aEvent)
mLastKeypressEventWasTrusted = isTrusted ? eTriTrue : eTriFalse;
}
}
void
nsEditor::OnFocus(nsIDOMEventTarget* aFocusEventTarget)
{
InitializeSelection(aFocusEventTarget);
if (mInlineSpellChecker) {
mInlineSpellChecker->UpdateCurrentDictionary();
}
}

View File

@ -719,6 +719,11 @@ public:
// nothing.
nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget);
// This method has to be called by nsEditorEventListener::Focus.
// All actions that have to be done when the editor is focused needs to be
// added here.
void OnFocus(nsIDOMEventTarget* aFocusEventTarget);
protected:
PRUint32 mModCount; // number of modifications (for undo/redo stack)

View File

@ -818,7 +818,7 @@ nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
}
}
mEditor->InitializeSelection(target);
mEditor->OnFocus(target);
return NS_OK;
}

View File

@ -185,27 +185,26 @@ mDocChangeRange(nsnull)
,mUtilRange(nsnull)
,mJoinOffset(0)
{
nsString emptyString;
// populate mCachedStyles
mCachedStyles[0] = StyleCache(nsEditProperty::b, emptyString, emptyString);
mCachedStyles[1] = StyleCache(nsEditProperty::i, emptyString, emptyString);
mCachedStyles[2] = StyleCache(nsEditProperty::u, emptyString, emptyString);
mCachedStyles[3] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("face"), emptyString);
mCachedStyles[4] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("size"), emptyString);
mCachedStyles[5] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("color"), emptyString);
mCachedStyles[6] = StyleCache(nsEditProperty::tt, emptyString, emptyString);
mCachedStyles[7] = StyleCache(nsEditProperty::em, emptyString, emptyString);
mCachedStyles[8] = StyleCache(nsEditProperty::strong, emptyString, emptyString);
mCachedStyles[9] = StyleCache(nsEditProperty::dfn, emptyString, emptyString);
mCachedStyles[10] = StyleCache(nsEditProperty::code, emptyString, emptyString);
mCachedStyles[11] = StyleCache(nsEditProperty::samp, emptyString, emptyString);
mCachedStyles[12] = StyleCache(nsEditProperty::var, emptyString, emptyString);
mCachedStyles[13] = StyleCache(nsEditProperty::cite, emptyString, emptyString);
mCachedStyles[14] = StyleCache(nsEditProperty::abbr, emptyString, emptyString);
mCachedStyles[15] = StyleCache(nsEditProperty::acronym, emptyString, emptyString);
mCachedStyles[16] = StyleCache(nsEditProperty::cssBackgroundColor, emptyString, emptyString);
mCachedStyles[17] = StyleCache(nsEditProperty::sub, emptyString, emptyString);
mCachedStyles[18] = StyleCache(nsEditProperty::sup, emptyString, emptyString);
mCachedStyles[0] = StyleCache(nsEditProperty::b, EmptyString(), EmptyString());
mCachedStyles[1] = StyleCache(nsEditProperty::i, EmptyString(), EmptyString());
mCachedStyles[2] = StyleCache(nsEditProperty::u, EmptyString(), EmptyString());
mCachedStyles[3] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("face"), EmptyString());
mCachedStyles[4] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("size"), EmptyString());
mCachedStyles[5] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("color"), EmptyString());
mCachedStyles[6] = StyleCache(nsEditProperty::tt, EmptyString(), EmptyString());
mCachedStyles[7] = StyleCache(nsEditProperty::em, EmptyString(), EmptyString());
mCachedStyles[8] = StyleCache(nsEditProperty::strong, EmptyString(), EmptyString());
mCachedStyles[9] = StyleCache(nsEditProperty::dfn, EmptyString(), EmptyString());
mCachedStyles[10] = StyleCache(nsEditProperty::code, EmptyString(), EmptyString());
mCachedStyles[11] = StyleCache(nsEditProperty::samp, EmptyString(), EmptyString());
mCachedStyles[12] = StyleCache(nsEditProperty::var, EmptyString(), EmptyString());
mCachedStyles[13] = StyleCache(nsEditProperty::cite, EmptyString(), EmptyString());
mCachedStyles[14] = StyleCache(nsEditProperty::abbr, EmptyString(), EmptyString());
mCachedStyles[15] = StyleCache(nsEditProperty::acronym, EmptyString(), EmptyString());
mCachedStyles[16] = StyleCache(nsEditProperty::cssBackgroundColor, EmptyString(), EmptyString());
mCachedStyles[17] = StyleCache(nsEditProperty::sub, EmptyString(), EmptyString());
mCachedStyles[18] = StyleCache(nsEditProperty::sup, EmptyString(), EmptyString());
}
nsHTMLEditRules::~nsHTMLEditRules()

View File

@ -458,9 +458,6 @@ protected:
// @return If the editor has focus, this returns the focused node.
// Otherwise, returns null.
already_AddRefed<nsINode> GetFocusedNode();
// Get an active editor's editing host in DOM window. If this editor isn't
// active in the DOM window, this returns NULL.
nsIContent* GetActiveEditingHost();
// Return TRUE if aElement is a table-related elemet and caret was set
PRBool SetCaretInTableCell(nsIDOMElement* aElement);

View File

@ -45,7 +45,6 @@ function append(str) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var edit = document.getElementById("edit");
edit.focus();
var editor = getEditor();
var sel = editor.selection;
sel.selectAllChildren(edit);
@ -58,16 +57,19 @@ function append(str) {
function runTest() {
gMisspeltWords = ["haz", "cheezburger"];
is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for.");
var edit = document.getElementById("edit");
append(" becaz I'm a lolcat!");
edit.focus();
SimpleTest.executeSoon(function() {
gMisspeltWords.push("becaz");
gMisspeltWords.push("lolcat");
is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for.");
is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for.");
SimpleTest.finish();
append(" becaz I'm a lolcat!");
SimpleTest.executeSoon(function() {
gMisspeltWords.push("becaz");
gMisspeltWords.push("lolcat");
is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for.");
SimpleTest.finish();
});
});
}

View File

@ -221,11 +221,16 @@ nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
nsnull, 0, nsnull, 0);
NS_ENSURE_SUCCESS(res, res);
// if only trailing <br> remaining remove it
res = RemoveRedundantTrailingBR();
if (NS_FAILED(res))
return res;
// detect empty doc
res = CreateBogusNodeIfNeeded(selection);
NS_ENSURE_SUCCESS(res, res);
// insure trailing br node
// ensure trailing br node
res = CreateTrailingBRIfNeeded();
NS_ENSURE_SUCCESS(res, res);
@ -1045,6 +1050,66 @@ nsTextEditRules::DidOutputText(nsISelection *aSelection, nsresult aResult)
return NS_OK;
}
nsresult
nsTextEditRules::RemoveRedundantTrailingBR()
{
// If the bogus node exists, we have no work to do
if (mBogusNode)
return NS_OK;
// Likewise, nothing to be done if we could never have inserted a trailing br
if (IsSingleLineEditor())
return NS_OK;
nsIDOMNode* body = mEditor->GetRoot();
if (!body)
return NS_ERROR_NULL_POINTER;
PRBool hasChildren;
nsresult res = body->HasChildNodes(&hasChildren);
NS_ENSURE_SUCCESS(res, res);
if (hasChildren) {
nsCOMPtr<nsIDOMNodeList> childList;
res = body->GetChildNodes(getter_AddRefs(childList));
NS_ENSURE_SUCCESS(res, res);
if (!childList)
return NS_ERROR_NULL_POINTER;
PRUint32 childCount;
res = childList->GetLength(&childCount);
NS_ENSURE_SUCCESS(res, res);
// The trailing br is redundant if it is the only remaining child node
if (childCount != 1)
return NS_OK;
nsCOMPtr<nsIDOMNode> child;
res = body->GetFirstChild(getter_AddRefs(child));
NS_ENSURE_SUCCESS(res, res);
if (nsTextEditUtils::IsMozBR(child)) {
// Rather than deleting this node from the DOM tree we should instead
// morph this br into the bogus node
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(child);
if (elem) {
elem->RemoveAttribute(NS_LITERAL_STRING("type"));
NS_ENSURE_SUCCESS(res, res);
// set mBogusNode to be this <br>
mBogusNode = elem;
// give it the bogus node attribute
nsCOMPtr<nsIContent> content = do_QueryInterface(elem);
content->SetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
kMOZEditorBogusNodeValue, PR_FALSE);
}
}
}
return NS_OK;
}
nsresult
nsTextEditRules::CreateTrailingBRIfNeeded()
{

View File

@ -205,6 +205,9 @@ protected:
// helper functions
/** check for and replace a redundant trailing break */
nsresult RemoveRedundantTrailingBR();
/** creates a trailing break in the text doc if there is not one already */
nsresult CreateTrailingBRIfNeeded();

View File

@ -73,6 +73,7 @@ _TEST_FILES += \
endif
_CHROME_TEST_FILES = \
test_bug483651.html \
test_bug636465.xul \
$(NULL)

View File

@ -0,0 +1,92 @@
<!DOCTYPE HTML>
<!-- ***** 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 Plaintext Editor Test code
-
- The Initial Developer of the Original Code is
- Graeme McCutcheon <graememcc_firefox@graeme-online.co.uk>.
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
-
-
- 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 ***** -->
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=483651
-->
<head>
<title>Test for Bug 483651</title>
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body onload="doTest();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=483651">Mozilla Bug 483651</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 483651 **/
SimpleTest.waitForExplicitFinish();
function doTest() {
var t1 = $("t1");
var editor = null;
if (t1 instanceof Components.interfaces.nsIDOMNSEditableElement)
editor = t1.editor;
ok(editor, "able to get editor for the element");
t1.focus();
synthesizeKey("A", {});
synthesizeKey("VK_BACK_SPACE", {});
try {
// Was the trailing br removed?
is(editor.documentIsEmpty, true, "trailing <br> correctly removed");
} catch (e) {
ok(false, "test failed with error "+e);
}
SimpleTest.finish();
}
</script>
</pre>
<textarea id="t1" rows="2" columns="80"></textarea>
</body>
</html>

View File

@ -43,7 +43,7 @@ interface nsISelection;
interface nsIEditor;
interface nsIEditorSpellCheck;
[scriptable, uuid(07be036a-2355-4a92-b150-5c9b7e9fdf2f)]
[scriptable, uuid(f456dda1-965d-470c-8c55-e51b38e45212)]
interface nsIInlineSpellChecker : nsISupports
{
@ -71,6 +71,7 @@ interface nsIInlineSpellChecker : nsISupports
void ignoreWord(in AString aWord);
void ignoreWords([array, size_is(aCount)] in wstring aWordsToIgnore, in unsigned long aCount);
void updateCurrentDictionary();
};
%{C++

View File

@ -142,7 +142,8 @@ public:
/**
* Tells the spellchecker to use a specific dictionary.
* @param aDictionary a string that is in the list returned
* by GetDictionaryList().
* by GetDictionaryList() or an empty string. If aDictionary is
* empty string, spellchecker will be disabled.
*/
NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) = 0;
};

View File

@ -1384,6 +1384,9 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
PRBool isMisspelled;
aWordUtil.NormalizeWord(wordText);
rv = mSpellCheck->CheckCurrentWordNoSuggest(wordText.get(), &isMisspelled);
if (NS_FAILED(rv))
continue;
if (isMisspelled) {
// misspelled words count extra toward the max
wordsSinceTimeCheck += MISSPELLED_WORD_COUNT_PENALTY;
@ -1441,6 +1444,23 @@ mozInlineSpellChecker::ResumeCheck(mozInlineSpellStatus* aStatus)
nsCOMPtr<nsISelection> spellCheckSelection;
rv = GetSpellCheckSelection(getter_AddRefs(spellCheckSelection));
NS_ENSURE_SUCCESS(rv, rv);
PRUnichar *currentDictionary = nsnull;
rv = mSpellCheck->GetCurrentDictionary(&currentDictionary);
if (NS_FAILED(rv)) {
// no active dictionary
PRInt32 count;
spellCheckSelection->GetRangeCount(&count);
for (PRInt32 index = count - 1; index >= 0; index--) {
nsCOMPtr<nsIDOMRange> checkRange;
spellCheckSelection->GetRangeAt(index, getter_AddRefs(checkRange));
if (checkRange) {
RemoveRange(spellCheckSelection, checkRange);
}
}
return NS_OK;
}
CleanupRangesInSelection(spellCheckSelection);
rv = aStatus->FinishInitOnEvent(wordUtil);
@ -1733,3 +1753,38 @@ nsresult mozInlineSpellChecker::KeyPress(nsIDOMEvent* aKeyEvent)
return NS_OK;
}
NS_IMETHODIMP mozInlineSpellChecker::UpdateCurrentDictionary()
{
if (!mSpellCheck) {
return NS_OK;
}
PRUnichar *previousDictionary = nsnull;
nsDependentString previousDictionaryStr;
if (NS_SUCCEEDED(mSpellCheck->GetCurrentDictionary(&previousDictionary))) {
previousDictionaryStr.Assign(previousDictionary);
}
nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
nsresult rv = mSpellCheck->UpdateCurrentDictionary(editor);
PRUnichar *currentDictionary = nsnull;
nsDependentString currentDictionaryStr;
if (NS_SUCCEEDED(mSpellCheck->GetCurrentDictionary(&currentDictionary))) {
currentDictionaryStr.Assign(currentDictionary);
}
if (!previousDictionary || !currentDictionary || !previousDictionaryStr.Equals(currentDictionaryStr)) {
rv = SpellCheckRange(nsnull);
}
if (previousDictionary) {
nsMemory::Free(previousDictionary);
}
if (currentDictionary) {
nsMemory::Free(currentDictionary);
}
return rv;
}

View File

@ -369,6 +369,12 @@ mozSpellChecker::SetCurrentDictionary(const nsAString &aDictionary)
nsresult rv;
nsCString *contractId;
if (aDictionary.IsEmpty()) {
mCurrentEngineContractId = nsnull;
mSpellCheckingEngine = nsnull;
return NS_OK;
}
if (!mDictionariesMap.Get(aDictionary, &contractId)){
NS_WARNING("Dictionary not found");
return NS_ERROR_NOT_AVAILABLE;

View File

@ -44,7 +44,7 @@ struct {
{ HB_TAG('c','u','r','s'), DEFAULT_PRIORITY },
{ HB_TAG('k','e','r','n'), DEFAULT_PRIORITY },
{ HB_TAG('l','i','g','a'), DEFAULT_PRIORITY },
{ HB_TAG('l','o','c','l'), DEFAULT_PRIORITY },
{ HB_TAG('l','o','c','l'), FIRST_PRIORITY },
{ HB_TAG('m','a','r','k'), DEFAULT_PRIORITY },
{ HB_TAG('m','k','m','k'), DEFAULT_PRIORITY },
{ HB_TAG('r','l','i','g'), DEFAULT_PRIORITY }

View File

@ -94,7 +94,7 @@ inline nscoord NSToCoordRound(float aValue)
#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
return NS_lroundup30(aValue);
#else
return nscoord(NS_floorf(aValue + 0.5f));
return nscoord(floorf(aValue + 0.5f));
#endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
}
@ -103,7 +103,7 @@ inline nscoord NSToCoordRound(double aValue)
#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__)
return NS_lroundup30((float)aValue);
#else
return nscoord(NS_floor(aValue + 0.5f));
return nscoord(floor(aValue + 0.5f));
#endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
}
@ -360,12 +360,12 @@ inline float NSCoordToFloat(nscoord aCoord) {
*/
inline nscoord NSToCoordFloor(float aValue)
{
return nscoord(NS_floorf(aValue));
return nscoord(floorf(aValue));
}
inline nscoord NSToCoordFloor(double aValue)
{
return nscoord(NS_floor(aValue));
return nscoord(floor(aValue));
}
inline nscoord NSToCoordFloorClamped(float aValue)
@ -388,12 +388,12 @@ inline nscoord NSToCoordFloorClamped(float aValue)
inline nscoord NSToCoordCeil(float aValue)
{
return nscoord(NS_ceilf(aValue));
return nscoord(ceilf(aValue));
}
inline nscoord NSToCoordCeil(double aValue)
{
return nscoord(NS_ceil(aValue));
return nscoord(ceil(aValue));
}
inline nscoord NSToCoordCeilClamped(float aValue)
@ -437,12 +437,12 @@ inline nscoord NSToCoordCeilClamped(double aValue)
*/
inline PRInt32 NSToIntFloor(float aValue)
{
return PRInt32(NS_floorf(aValue));
return PRInt32(floorf(aValue));
}
inline PRInt32 NSToIntCeil(float aValue)
{
return PRInt32(NS_ceilf(aValue));
return PRInt32(ceilf(aValue));
}
inline PRInt32 NSToIntRound(float aValue)
@ -457,12 +457,12 @@ inline PRInt32 NSToIntRound(double aValue)
inline PRInt32 NSToIntRoundUp(float aValue)
{
return PRInt32(NS_floorf(aValue + 0.5f));
return PRInt32(floorf(aValue + 0.5f));
}
inline PRInt32 NSToIntRoundUp(double aValue)
{
return PRInt32(NS_floor(aValue + 0.5));
return PRInt32(floor(aValue + 0.5));
}
/*

View File

@ -147,7 +147,7 @@ nsFontMetrics::Destroy()
// XXXTODO get rid of this macro
#define ROUND_TO_TWIPS(x) (nscoord)floor(((x) * mP2A) + 0.5)
#define CEIL_TO_TWIPS(x) (nscoord)NS_ceil((x) * mP2A)
#define CEIL_TO_TWIPS(x) (nscoord)ceil((x) * mP2A)
const gfxFont::Metrics& nsFontMetrics::GetMetrics() const
{
@ -194,15 +194,15 @@ nsFontMetrics::GetUnderline(nscoord& aOffset, nscoord& aSize)
static gfxFloat ComputeMaxDescent(const gfxFont::Metrics& aMetrics,
gfxFontGroup* aFontGroup)
{
gfxFloat offset = NS_floor(-aFontGroup->GetUnderlineOffset() + 0.5);
gfxFloat offset = floor(-aFontGroup->GetUnderlineOffset() + 0.5);
gfxFloat size = NS_round(aMetrics.underlineSize);
gfxFloat minDescent = NS_floor(offset + size + 0.5);
gfxFloat minDescent = floor(offset + size + 0.5);
return NS_MAX(minDescent, aMetrics.maxDescent);
}
static gfxFloat ComputeMaxAscent(const gfxFont::Metrics& aMetrics)
{
return NS_floor(aMetrics.maxAscent + 0.5);
return floor(aMetrics.maxAscent + 0.5);
}
nscoord

View File

@ -114,7 +114,7 @@ gfxCachedTempSurface::Get(gfxASurface::gfxContentType aContentType,
PRBool cleared = PR_FALSE;
if (!mSurface) {
mSize = gfxIntSize(PRInt32(NS_ceil(aRect.width)), PRInt32(NS_ceil(aRect.height)));
mSize = gfxIntSize(PRInt32(ceil(aRect.width)), PRInt32(ceil(aRect.height)));
mSurface = aSimilarTo->CreateSimilarSurface(aContentType, mSize);
if (!mSurface)
return nsnull;

View File

@ -70,11 +70,11 @@ ScaleRoundDesignUnits(FT_Short aDesignMetric, FT_Fixed aScale)
static void
SnapLineToPixels(gfxFloat& aOffset, gfxFloat& aSize)
{
gfxFloat snappedSize = NS_MAX(NS_floor(aSize + 0.5), 1.0);
gfxFloat snappedSize = NS_MAX(floor(aSize + 0.5), 1.0);
// Correct offset for change in size
gfxFloat offset = aOffset - 0.5 * (aSize - snappedSize);
// Snap offset
aOffset = NS_floor(offset + 0.5);
aOffset = floor(offset + 0.5);
aSize = snappedSize;
}
@ -281,16 +281,16 @@ gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics,
// internalLeading + externalLeading, but first each of these is rounded
// to layout units. To ensure that the result is an integer number of
// pixels, round each of the components to pixels.
aMetrics->emHeight = NS_floor(emHeight + 0.5);
aMetrics->emHeight = floor(emHeight + 0.5);
// maxHeight will normally be an integer, but round anyway in case
// FreeType is configured differently.
aMetrics->internalLeading =
NS_floor(aMetrics->maxHeight - aMetrics->emHeight + 0.5);
floor(aMetrics->maxHeight - aMetrics->emHeight + 0.5);
// Text input boxes currently don't work well with lineHeight
// significantly less than maxHeight (with Verdana, for example).
lineHeight = NS_floor(NS_MAX(lineHeight, aMetrics->maxHeight) + 0.5);
lineHeight = floor(NS_MAX(lineHeight, aMetrics->maxHeight) + 0.5);
aMetrics->externalLeading =
lineHeight - aMetrics->internalLeading - aMetrics->emHeight;

View File

@ -651,15 +651,12 @@ void gfxFontFamily::LocalizedName(nsAString& aLocalizedName)
void
gfxFontFamily::FindFontForChar(FontSearch *aMatchData)
{
if (!mHasStyles) {
if (!mHasStyles)
FindStyleVariations();
}
if (!TestCharacterMap(aMatchData->mCh)) {
// none of the faces in the family support the required char,
// so bail out immediately
return;
}
// xxx - optimization point - keep a bit vector with the union of supported unicode ranges
// by all fonts for this family and bail immediately if the character is not in any of
// this family's cmaps
// iterate over fonts
PRUint32 numFonts = mAvailableFonts.Length();
@ -1594,7 +1591,7 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID, PRBool aNeed
extents.y_bearing >= -fontMetrics.maxAscent &&
extents.height + extents.y_bearing <= fontMetrics.maxDescent) {
PRUint32 appUnitsWidth =
PRUint32(NS_ceil((extents.x_bearing + extents.width)*appUnitsPerDevUnit));
PRUint32(ceil((extents.x_bearing + extents.width)*appUnitsPerDevUnit));
if (appUnitsWidth < gfxGlyphExtents::INVALID_WIDTH) {
aExtents->SetContainedGlyphWidthAppUnits(aGlyphID, PRUint16(appUnitsWidth));
return;
@ -1713,9 +1710,9 @@ RoundToNearestMultiple(double aValue, double aFraction)
void gfxFont::CalculateDerivedMetrics(Metrics& aMetrics)
{
aMetrics.maxAscent =
NS_ceil(RoundToNearestMultiple(aMetrics.maxAscent, 1/1024.0));
ceil(RoundToNearestMultiple(aMetrics.maxAscent, 1/1024.0));
aMetrics.maxDescent =
NS_ceil(RoundToNearestMultiple(aMetrics.maxDescent, 1/1024.0));
ceil(RoundToNearestMultiple(aMetrics.maxDescent, 1/1024.0));
if (aMetrics.xHeight <= 0) {
// only happens if we couldn't find either font metrics
@ -1828,13 +1825,13 @@ gfxFont::SanitizeMetrics(gfxFont::Metrics *aMetrics, PRBool aIsBadUnderlineFont)
// If strikeout line is overflowed from the ascent, the line should be resized and moved for
// that being in the ascent space.
// Note that the strikeoutOffset is *middle* of the strikeout line position.
gfxFloat halfOfStrikeoutSize = NS_floor(aMetrics->strikeoutSize / 2.0 + 0.5);
gfxFloat halfOfStrikeoutSize = floor(aMetrics->strikeoutSize / 2.0 + 0.5);
if (halfOfStrikeoutSize + aMetrics->strikeoutOffset > aMetrics->maxAscent) {
if (aMetrics->strikeoutSize > aMetrics->maxAscent) {
aMetrics->strikeoutSize = NS_MAX(aMetrics->maxAscent, 1.0);
halfOfStrikeoutSize = NS_floor(aMetrics->strikeoutSize / 2.0 + 0.5);
halfOfStrikeoutSize = floor(aMetrics->strikeoutSize / 2.0 + 0.5);
}
gfxFloat ascent = NS_floor(aMetrics->maxAscent + 0.5);
gfxFloat ascent = floor(aMetrics->maxAscent + 0.5);
aMetrics->strikeoutOffset = NS_MAX(halfOfStrikeoutSize, ascent / 2.0);
}
@ -2544,7 +2541,7 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
gfxFloat wid = mainFont->SynthesizeSpaceWidth(ch);
if (wid >= 0.0) {
nscoord advance =
aTextRun->GetAppUnitsPerDevUnit() * NS_floor(wid + 0.5);
aTextRun->GetAppUnitsPerDevUnit() * floor(wid + 0.5);
gfxTextRun::CompressedGlyph g;
if (gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance)) {
aTextRun->SetSimpleGlyph(index,
@ -2614,8 +2611,11 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
return font.forget();
}
// check other faces of the family
// XXX optimization point: give the family a charmap that is the union
// of the char maps of all its faces, so we can quickly test whether
// it's worth doing this search
gfxFontFamily *family = font->GetFontEntry()->Family();
if (family && family->TestCharacterMap(aCh)) {
if (family) {
FontSearch matchData(aCh, font);
family->FindFontForChar(&matchData);
gfxFontEntry *fe = matchData.mBestMatch;

View File

@ -482,8 +482,7 @@ public:
mFaceNamesInitialized(PR_FALSE),
mHasStyles(PR_FALSE),
mIsSimpleFamily(PR_FALSE),
mIsBadUnderlineFamily(PR_FALSE),
mCharacterMapInitialized(PR_FALSE)
mIsBadUnderlineFamily(PR_FALSE)
{ }
virtual ~gfxFontFamily() { }
@ -545,28 +544,10 @@ public:
// read in cmaps for all the faces
void ReadCMAP() {
PRUint32 i, numFonts = mAvailableFonts.Length();
for (i = 0; i < numFonts; i++) {
gfxFontEntry *fe = mAvailableFonts[i];
if (!fe) {
continue;
}
fe->ReadCMAP();
mCharacterMap.Union(fe->mCharacterMap);
}
mCharacterMap.Compact();
mCharacterMapInitialized = PR_TRUE;
}
PRBool TestCharacterMap(PRUint32 aCh) {
if (!mCharacterMapInitialized) {
ReadCMAP();
}
return mCharacterMap.test(aCh);
}
void ResetCharacterMap() {
mCharacterMap.reset();
mCharacterMapInitialized = PR_FALSE;
// called from RunLoader BEFORE CheckForSimpleFamily so that there cannot
// be any NULL entries in mAvailableFonts
for (i = 0; i < numFonts; i++)
mAvailableFonts[i]->ReadCMAP();
}
// mark this family as being in the "bad" underline offset blacklist
@ -609,14 +590,12 @@ protected:
nsString mName;
nsTArray<nsRefPtr<gfxFontEntry> > mAvailableFonts;
gfxSparseBitSet mCharacterMap;
PRPackedBool mOtherFamilyNamesInitialized;
PRPackedBool mHasOtherFamilyNames;
PRPackedBool mFaceNamesInitialized;
PRPackedBool mHasStyles;
PRPackedBool mIsSimpleFamily;
PRPackedBool mIsBadUnderlineFamily;
PRPackedBool mCharacterMapInitialized;
enum {
// for "simple" families, the faces are stored in mAvailableFonts

View File

@ -313,7 +313,7 @@ gfxFontUtils::ReadCMAPTableFormat12(const PRUint8 *aBuf, PRUint32 aLength,
prevEndCharCode = endCharCode;
}
aCharacterMap.Compact();
aCharacterMap.mBlocks.Compact();
return NS_OK;
}
@ -391,7 +391,7 @@ gfxFontUtils::ReadCMAPTableFormat4(const PRUint8 *aBuf, PRUint32 aLength,
}
}
aCharacterMap.Compact();
aCharacterMap.mBlocks.Compact();
return NS_OK;
}

View File

@ -165,6 +165,8 @@ public:
Block *block = mBlocks[blockIndex];
if (!block) {
block = new Block;
if (NS_UNLIKELY(!block)) // OOM
return;
mBlocks[blockIndex] = block;
}
block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)] |= 1 << (aIndex & 0x7);
@ -199,6 +201,9 @@ public:
fullBlock = PR_TRUE;
block = new Block(fullBlock ? 0xFF : 0);
if (NS_UNLIKELY(!block)) // OOM
return;
mBlocks[i] = block;
if (fullBlock)
@ -274,44 +279,7 @@ public:
for (i = 0; i < mBlocks.Length(); i++)
mBlocks[i] = nsnull;
}
// set this bitset to the union of its current contents and another
void Union(const gfxSparseBitSet& aBitset) {
// ensure mBlocks is large enough
PRUint32 blockCount = aBitset.mBlocks.Length();
if (blockCount > mBlocks.Length()) {
PRUint32 needed = blockCount - mBlocks.Length();
nsAutoPtr<Block> *blocks = mBlocks.AppendElements(needed);
if (NS_UNLIKELY(!blocks)) { // OOM
return;
}
}
// for each block that may be present in aBitset...
for (PRUint32 i = 0; i < blockCount; ++i) {
// if it is missing (implicitly empty), just skip
if (!aBitset.mBlocks[i]) {
continue;
}
// if the block is missing in this set, just copy the other
if (!mBlocks[i]) {
mBlocks[i] = new Block(*aBitset.mBlocks[i]);
continue;
}
// else set existing block to the union of both
PRUint32 *dst = reinterpret_cast<PRUint32*>(mBlocks[i]->mBits);
const PRUint32 *src =
reinterpret_cast<const PRUint32*>(aBitset.mBlocks[i]->mBits);
for (PRUint32 j = 0; j < BLOCK_SIZE / 4; ++j) {
dst[j] |= src[j];
}
}
}
void Compact() {
mBlocks.Compact();
}
private:
nsTArray< nsAutoPtr<Block> > mBlocks;
};

View File

@ -1128,7 +1128,7 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
hb_position_t x_advance = posInfo[glyphStart].x_advance;
nscoord advance =
roundX ? dev2appUnits * FixedToIntRound(x_advance)
: NS_floor(hb2appUnits * x_advance + 0.5);
: floor(hb2appUnits * x_advance + 0.5);
if (glyphsInClump == 1 &&
gfxTextRun::CompressedGlyph::IsSimpleGlyphID(ginfo[glyphStart].codepoint) &&
@ -1158,18 +1158,18 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
hb_position_t x_offset = posInfo[glyphStart].x_offset;
details->mXOffset =
roundX ? dev2appUnits * FixedToIntRound(x_offset)
: NS_floor(hb2appUnits * x_offset + 0.5);
: floor(hb2appUnits * x_offset + 0.5);
hb_position_t y_offset = posInfo[glyphStart].y_offset;
details->mYOffset = yPos -
(roundY ? dev2appUnits * FixedToIntRound(y_offset)
: NS_floor(hb2appUnits * y_offset + 0.5));
: floor(hb2appUnits * y_offset + 0.5));
details->mAdvance = advance;
hb_position_t y_advance = posInfo[glyphStart].y_advance;
if (y_advance != 0) {
yPos -=
roundY ? dev2appUnits * FixedToIntRound(y_advance)
: NS_floor(hb2appUnits * y_advance + 0.5);
: floor(hb2appUnits * y_advance + 0.5);
}
if (++glyphStart >= glyphEnd) {
break;
@ -1177,7 +1177,7 @@ gfxHarfBuzzShaper::SetGlyphsFromRun(gfxContext *aContext,
x_advance = posInfo[glyphStart].x_advance;
advance =
roundX ? dev2appUnits * FixedToIntRound(x_advance)
: NS_floor(hb2appUnits * x_advance + 0.5);
: floor(hb2appUnits * x_advance + 0.5);
}
gfxTextRun::CompressedGlyph g;

View File

@ -194,8 +194,8 @@ public:
*/
PRBool HasNonIntegerTranslation() const {
return HasNonTranslation() ||
!FuzzyEqual(x0, NS_floor(x0 + 0.5)) ||
!FuzzyEqual(y0, NS_floor(y0 + 0.5));
!FuzzyEqual(x0, floor(x0 + 0.5)) ||
!FuzzyEqual(y0, floor(y0 + 0.5));
}
/**
@ -291,8 +291,8 @@ public:
* Returns true if the matrix has non-integer scale
*/
PRBool HasNonIntegerScale() const {
return !FuzzyEqual(xx, NS_floor(xx + 0.5)) ||
!FuzzyEqual(yy, NS_floor(yy + 0.5));
return !FuzzyEqual(xx, floor(xx + 0.5)) ||
!FuzzyEqual(yy, floor(yy + 0.5));
}
private:

View File

@ -127,11 +127,11 @@ static void FillMetricsDefaults(gfxFont::Metrics *aMetrics)
// line as close to the original position as possible.
static void SnapLineToPixels(gfxFloat& aOffset, gfxFloat& aSize)
{
gfxFloat snappedSize = NS_MAX(NS_floor(aSize + 0.5), 1.0);
gfxFloat snappedSize = NS_MAX(floor(aSize + 0.5), 1.0);
// Correct offset for change in size
gfxFloat offset = aOffset - 0.5 * (aSize - snappedSize);
// Snap offset
aOffset = NS_floor(offset + 0.5);
aOffset = floor(offset + 0.5);
aSize = snappedSize;
}
@ -155,7 +155,7 @@ const gfxFont::Metrics& gfxOS2Font::GetMetrics()
// round size to integer pixels, this is to get full pixels for layout
// together with internal/external leading (see below)
mMetrics->emHeight = NS_floor(GetStyle()->size + 0.5);
mMetrics->emHeight = floor(GetStyle()->size + 0.5);
cairo_scaled_font_t* scaledFont = CairoScaledFont();
if (!scaledFont) {
@ -274,9 +274,9 @@ const gfxFont::Metrics& gfxOS2Font::GetMetrics()
// leadings are not available directly (only for WinFNTs);
// better compute them on our own, to get integer values and make
// layout happy (see // LockedFTFace::GetMetrics in gfxPangoFonts.cpp)
mMetrics->internalLeading = NS_floor(mMetrics->maxHeight
mMetrics->internalLeading = floor(mMetrics->maxHeight
- mMetrics->emHeight + 0.5);
gfxFloat lineHeight = NS_floor(mMetrics->maxHeight + 0.5);
gfxFloat lineHeight = floor(mMetrics->maxHeight + 0.5);
mMetrics->externalLeading = lineHeight
- mMetrics->internalLeading - mMetrics->emHeight;

View File

@ -69,8 +69,8 @@ struct THEBES_API gfxPoint : public mozilla::gfx::BasePoint<gfxFloat, gfxPoint>
// And if you need similar method which is using NS_round(), you should
// create new |RoundAwayFromZero()| method.
gfxPoint& Round() {
x = NS_floor(x + 0.5);
y = NS_floor(y + 0.5);
x = floor(x + 0.5);
y = floor(y + 0.5);
return *this;
}
};

View File

@ -59,10 +59,10 @@ void
gfxRect::Round()
{
// Note that don't use NS_round here. See the comment for this method in gfxRect.h
gfxFloat x0 = NS_floor(X() + 0.5);
gfxFloat y0 = NS_floor(Y() + 0.5);
gfxFloat x1 = NS_floor(XMost() + 0.5);
gfxFloat y1 = NS_floor(YMost() + 0.5);
gfxFloat x0 = floor(X() + 0.5);
gfxFloat y0 = floor(Y() + 0.5);
gfxFloat x1 = floor(XMost() + 0.5);
gfxFloat y1 = floor(YMost() + 0.5);
x = x0;
y = y0;
@ -74,10 +74,10 @@ gfxRect::Round()
void
gfxRect::RoundIn()
{
gfxFloat x0 = NS_ceil(X());
gfxFloat y0 = NS_ceil(Y());
gfxFloat x1 = NS_floor(XMost());
gfxFloat y1 = NS_floor(YMost());
gfxFloat x0 = ceil(X());
gfxFloat y0 = ceil(Y());
gfxFloat x1 = floor(XMost());
gfxFloat y1 = floor(YMost());
x = x0;
y = y0;
@ -89,10 +89,10 @@ gfxRect::RoundIn()
void
gfxRect::RoundOut()
{
gfxFloat x0 = NS_floor(X());
gfxFloat y0 = NS_floor(Y());
gfxFloat x1 = NS_ceil(XMost());
gfxFloat y1 = NS_ceil(YMost());
gfxFloat x0 = floor(X());
gfxFloat y0 = floor(Y());
gfxFloat x1 = ceil(XMost());
gfxFloat y1 = ceil(YMost());
x = x0;
y = y0;

View File

@ -106,12 +106,10 @@ public:
virtual ~gfxMixedFontFamily() { }
void AddFontEntry(gfxFontEntry *aFontEntry)
{
void AddFontEntry(gfxFontEntry *aFontEntry) {
nsRefPtr<gfxFontEntry> fe = aFontEntry;
mAvailableFonts.AppendElement(fe);
aFontEntry->SetFamily(this);
ResetCharacterMap();
}
void ReplaceFontEntry(gfxFontEntry *aOldFontEntry, gfxFontEntry *aNewFontEntry)
@ -125,10 +123,9 @@ public:
// other reference to it except from its family
mAvailableFonts[i] = aNewFontEntry;
aNewFontEntry->SetFamily(this);
break;
return;
}
}
ResetCharacterMap();
}
void RemoveFontEntry(gfxFontEntry *aFontEntry)
@ -139,10 +136,9 @@ public:
if (fe == aFontEntry) {
aFontEntry->SetFamily(nsnull);
mAvailableFonts.RemoveElementAt(i);
break;
return;
}
}
ResetCharacterMap();
}
// temp method to determine if all proxies are loaded

View File

@ -489,7 +489,7 @@ gfxUtils::ClampToScaleFactor(gfxFloat aVal)
if (fabs(power - NS_round(power)) < 1e-6) {
power = NS_round(power);
} else {
power = NS_ceil(power);
power = ceil(power);
}
return pow(kScaleResolution, power);

View File

@ -138,8 +138,8 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
// There's probably a better fix, but I haven't figured out
// the root cause of the problem.
mTempSurfaceSize =
gfxIntSize((PRInt32) NS_ceil(mNativeRect.Width() + 1),
(PRInt32) NS_ceil(mNativeRect.Height() + 1));
gfxIntSize((PRInt32) ceil(mNativeRect.Width() + 1),
(PRInt32) ceil(mNativeRect.Height() + 1));
} else {
// figure out the scale factors
mScale = m.ScaleFactors(PR_TRUE);
@ -153,8 +153,8 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
// See comment above about "+1"
mTempSurfaceSize =
gfxIntSize((PRInt32) NS_ceil(mNativeRect.Width() * mScale.width + 1),
(PRInt32) NS_ceil(mNativeRect.Height() * mScale.height + 1));
gfxIntSize((PRInt32) ceil(mNativeRect.Width() * mScale.width + 1),
(PRInt32) ceil(mNativeRect.Height() * mScale.height + 1));
}
}
}

View File

@ -677,7 +677,7 @@ check-malloc-function-usage: $(filter-out %jsalloc.h %jscntxt.h %jsutil.h, $(ALL
# We desire these numbers to go down, not up. See "User guide to memory
# management within SpiderMonkey" in jsutil.h.
$(srcdir)/config/check_source_count.py OffTheBooks:: 59 \
"in Makefile.in" "{cx,rt}->{new_,new_array,malloc_,calloc_,realloc_}" $^
"in Makefile.in" "{cx,rt}->{new_,array_new,malloc_,calloc_,realloc_}" $^
# This should go to zero, if possible.
$(srcdir)/config/check_source_count.py UnwantedForeground:: 31 \
"in Makefile.in" "{cx,rt}->{free_,delete_,array_delete}" $^

View File

@ -1081,6 +1081,7 @@ endif
ifdef DTRACE_PROBE_OBJ
EXTRA_DEPS += $(DTRACE_PROBE_OBJ)
OBJS += $(DTRACE_PROBE_OBJ)
endif
$(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
@ -1121,8 +1122,8 @@ ifdef HAVE_DTRACE
ifndef XP_MACOSX
ifdef DTRACE_PROBE_OBJ
ifndef DTRACE_LIB_DEPENDENT
$(DTRACE_PROBE_OBJ): $(OBJS)
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(OBJS)
$(DTRACE_PROBE_OBJ):
dtrace -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ)
endif
endif
endif
@ -1144,7 +1145,7 @@ endif
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
@$(RM) $(DTRACE_PROBE_OBJ)
else # ! DTRACE_LIB_DEPENDENT
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
endif # DTRACE_LIB_DEPENDENT
@$(call CHECK_STDCXX,$@)

View File

@ -5022,6 +5022,18 @@ if test -n "$JS_GC_ZEAL"; then
AC_DEFINE(JS_GC_ZEAL)
fi
dnl ========================================================
dnl JS opt-mode assertions and minidump instrumentation
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(js-diagnostics,
[ --enable-js-diagnostics
Enable JS diagnostic assertions and breakpad data],
JS_CRASH_DIAGNOSTICS=1,
JS_CRASH_DIAGNOSTICS= )
if test -n "$JS_CRASH_DIAGNOSTICS"; then
AC_DEFINE(JS_CRASH_DIAGNOSTICS)
fi
dnl ======================================================
dnl = Enable compiling with ccache
dnl ======================================================

View File

@ -11277,7 +11277,7 @@ case "$host" in
powerpc-*-aix* | rs6000-*-aix*)
TARGET=POWERPC_AIX; TARGETDIR=powerpc
;;
powerpc-*-freebsd*)
powerpc-*-freebsd* | powerpc-*-openbsd*)
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
;;
powerpc*-*-rtems*)

View File

@ -0,0 +1,3 @@
var g = newGlobal('new-compartment');
g.eval("function f(n) { for (var i = 0; i < n; i++) f(0); }");
g.f(RUNLOOP + 1);

View File

@ -51,15 +51,18 @@ CPPSRCS = \
selfTest.cpp \
testArgumentsObject.cpp \
testBug604087.cpp \
testChromeBuffer.cpp \
testClassGetter.cpp \
testCloneScript.cpp \
testConservativeGC.cpp \
testContexts.cpp \
testCustomIterator.cpp \
testDebugger.cpp \
testDeepFreeze.cpp \
testDefineGetterSetterNonEnumerable.cpp \
testDefineProperty.cpp \
testExtendedEq.cpp \
testExternalStrings.cpp \
testFuncCallback.cpp \
testFunctionProperties.cpp \
testGCChunkAlloc.cpp \
@ -84,9 +87,6 @@ CPPSRCS = \
testUTF8.cpp \
testVersion.cpp \
testXDR.cpp \
testCustomIterator.cpp \
testExternalStrings.cpp \
testChromeBuffer.cpp \
$(NULL)
# Disabled: an entirely unrelated test seems to cause this to fail. Moreover,

View File

@ -7,43 +7,50 @@
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsnum.h"
#include "jsstr.h"
#include "vm/String-inl.h"
template<size_t N> JSFlatString *
NewString(JSContext *cx, const jschar (&chars)[N])
{
return js_NewStringCopyN(cx, chars, N);
}
static const struct TestPair {
uint32 num;
const char *expected;
} tests[] = {
{ 0, "0" },
{ 1, "1" },
{ 2, "2" },
{ 9, "9" },
{ 10, "10" },
{ 15, "15" },
{ 16, "16" },
{ 17, "17" },
{ 99, "99" },
{ 100, "100" },
{ 255, "255" },
{ 256, "256" },
{ 257, "257" },
{ 999, "999" },
{ 1000, "1000" },
{ 4095, "4095" },
{ 4096, "4096" },
{ 9999, "9999" },
{ 1073741823, "1073741823" },
{ 1073741824, "1073741824" },
{ 1073741825, "1073741825" },
{ 2147483647, "2147483647" },
{ 2147483648, "2147483648" },
{ 2147483649, "2147483649" },
{ 4294967294, "4294967294" },
{ 4294967295, "4294967295" },
};
BEGIN_TEST(testIndexToString)
{
const struct TestPair {
uint32 num;
const char *expected;
} tests[] = {
{ 0, "0" },
{ 1, "1" },
{ 2, "2" },
{ 9, "9" },
{ 10, "10" },
{ 15, "15" },
{ 16, "16" },
{ 17, "17" },
{ 99, "99" },
{ 100, "100" },
{ 255, "255" },
{ 256, "256" },
{ 257, "257" },
{ 999, "999" },
{ 1000, "1000" },
{ 4095, "4095" },
{ 4096, "4096" },
{ 9999, "9999" },
{ 1073741823, "1073741823" },
{ 1073741824, "1073741824" },
{ 1073741825, "1073741825" },
{ 2147483647, "2147483647" },
{ 2147483648, "2147483648" },
{ 2147483649, "2147483649" },
{ 4294967294, "4294967294" },
{ 4294967295, "4294967295" },
};
for (size_t i = 0, sz = JS_ARRAY_LENGTH(tests); i < sz; i++) {
uint32 u = tests[i].num;
JSString *str = js::IndexToString(cx, u);
@ -60,3 +67,45 @@ BEGIN_TEST(testIndexToString)
return true;
}
END_TEST(testIndexToString)
BEGIN_TEST(testStringIsElement)
{
for (size_t i = 0, sz = JS_ARRAY_LENGTH(tests); i < sz; i++) {
uint32 u = tests[i].num;
JSFlatString *str = js::IndexToString(cx, u);
CHECK(str);
uint32 n;
CHECK(str->isElement(&n));
CHECK(u == n);
}
return true;
}
END_TEST(testStringIsElement)
BEGIN_TEST(testStringToPropertyName)
{
uint32 index;
static const jschar hiChars[] = { 'h', 'i' };
JSFlatString *hiStr = NewString(cx, hiChars);
CHECK(hiStr);
CHECK(!hiStr->isElement(&index));
CHECK(hiStr->toPropertyName(cx) != NULL);
static const jschar maxChars[] = { '4', '2', '9', '4', '9', '6', '7', '2', '9', '5' };
JSFlatString *maxStr = NewString(cx, maxChars);
CHECK(maxStr);
CHECK(maxStr->isElement(&index));
CHECK(index == UINT32_MAX);
static const jschar maxPlusOneChars[] = { '4', '2', '9', '4', '9', '6', '7', '2', '9', '6' };
JSFlatString *maxPlusOneStr = NewString(cx, maxPlusOneChars);
CHECK(maxPlusOneStr);
CHECK(!maxPlusOneStr->isElement(&index));
CHECK(maxPlusOneStr->toPropertyName(cx) != NULL);
return true;
}
END_TEST(testStringToPropertyName)

View File

@ -2712,9 +2712,9 @@ JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
case JSGC_MODE:
return uint32(rt->gcMode);
case JSGC_UNUSED_CHUNKS:
return uint32(rt->gcChunksWaitingToExpire);
return uint32(rt->gcEmptyChunkCount);
case JSGC_TOTAL_CHUNKS:
return uint32(rt->gcUserChunkSet.count() + rt->gcSystemChunkSet.count());
return uint32(rt->gcChunkSet.count() + rt->gcEmptyChunkCount);
default:
JS_ASSERT(key == JSGC_NUMBER);
return rt->gcNumber;

View File

@ -169,13 +169,6 @@ struct JSAtomMap {
namespace js {
/* N.B. must correspond to boolean tagging behavior. */
enum InternBehavior
{
DoNotInternAtom = false,
InternAtom = true
};
typedef TaggedPointerEntry<JSAtom> AtomStateEntry;
struct AtomHasher
@ -507,13 +500,6 @@ js_InitCommonAtoms(JSContext *cx);
extern void
js_FinishCommonAtoms(JSContext *cx);
/*
* Find or create the atom for a string. Return null on failure to allocate
* memory.
*/
extern JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
extern JSAtom *
js_Atomize(JSContext *cx, const char *bytes, size_t length,
js::InternBehavior ib = js::DoNotInternAtom,

View File

@ -135,12 +135,10 @@ js_Int32ToId(JSContext* cx, int32 index, jsid* id)
namespace js {
static const size_t UINT32_CHAR_BUFFER_LENGTH = sizeof("4294967295") - 1;
/*
* Write out character representing |index| to the memory just before |end|.
* Thus |*end| is not touched, but |end[-1]| and earlier are modified as
* appropriate. There must be at least UINT32_CHAR_BUFFER_LENGTH elements
* appropriate. There must be at least js::UINT32_CHAR_BUFFER_LENGTH elements
* before |end| to avoid buffer underflow. The start of the characters written
* is returned and is necessarily before |end|.
*/

View File

@ -138,7 +138,7 @@ struct GSNCache {
void purge();
};
inline GSNCache *
GetGSNCache(JSContext *cx);
@ -212,7 +212,7 @@ struct ThreadData {
~ThreadData();
bool init();
void mark(JSTracer *trc) {
stackSpace.mark(trc);
}
@ -263,7 +263,7 @@ struct JSThread {
suspendCount(0)
# ifdef DEBUG
, checkRequestDepth(0)
# endif
# endif
{
JS_INIT_CLIST(&contextList);
}
@ -390,8 +390,31 @@ struct JSRuntime
uint32 protoHazardShape;
/* Garbage collector state, used by jsgc.c. */
js::GCChunkSet gcUserChunkSet;
js::GCChunkSet gcSystemChunkSet;
/*
* Set of all GC chunks with at least one allocated thing. The
* conservative GC uses it to quickly check if a possible GC thing points
* into an allocated chunk.
*/
js::GCChunkSet gcChunkSet;
/*
* Doubly-linked lists of chunks from user and system compartments. The GC
* allocates its arenas from the corresponding list and when all arenas
* in the list head are taken, then the chunk is removed from the list.
* During the GC when all arenas in a chunk become free, that chunk is
* removed from the list and scheduled for release.
*/
js::gc::Chunk *gcSystemAvailableChunkListHead;
js::gc::Chunk *gcUserAvailableChunkListHead;
/*
* Singly-linked list of empty chunks and its length. We use the list not
* to release empty chunks immediately so they can be used for future
* allocations. This avoids very high overhead of chunk release/allocation.
*/
js::gc::Chunk *gcEmptyChunkListHead;
size_t gcEmptyChunkCount;
js::RootedValueMap gcRootsHash;
js::GCLocks gcLocksHash;
@ -401,7 +424,6 @@ struct JSRuntime
size_t gcLastBytes;
size_t gcMaxBytes;
size_t gcMaxMallocBytes;
size_t gcChunksWaitingToExpire;
uint32 gcEmptyArenaPoolLifespan;
uint32 gcNumber;
js::GCMarker *gcMarkingTracer;
@ -673,7 +695,7 @@ struct JSRuntime
return infoEnabled;
}
/*
/*
* Circular buffer with GC data.
* count may grow >= INFO_LIMIT, which would indicate data loss.
*/

View File

@ -130,7 +130,6 @@ JSCompartment::~JSCompartment()
bool
JSCompartment::init()
{
chunk = NULL;
for (unsigned i = 0; i < FINALIZE_LIMIT; i++)
arenas[i].init();
freeLists.init();
@ -470,8 +469,6 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
void
JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
{
chunk = NULL;
/* Remove dead wrappers from the table. */
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
JS_ASSERT_IF(IsAboutToBeFinalized(cx, e.front().key.toGCThing()) &&
@ -569,8 +566,6 @@ JSCompartment::purge(JSContext *cx)
#endif
#ifdef JS_METHODJIT
js::CheckCompartmentScripts(this);
for (JSScript *script = (JSScript *)scripts.next;
&script->links != &scripts;
script = (JSScript *)script->links.next) {

View File

@ -391,7 +391,6 @@ typedef HashSet<ScriptFilenameEntry *,
struct JS_FRIEND_API(JSCompartment) {
JSRuntime *rt;
JSPrincipals *principals;
js::gc::Chunk *chunk;
js::gc::ArenaList arenas[js::gc::FINALIZE_LIMIT];
js::gc::FreeLists freeLists;

View File

@ -245,37 +245,37 @@ static Stack gGCStack(JS_CRASH_STACK_GC);
static Stack gErrorStack(JS_CRASH_STACK_ERROR);
static Ring gRingBuffer(JS_CRASH_RING);
void
SnapshotGCStack()
{
if (gInitialized)
gGCStack.snapshot();
}
void
SnapshotErrorStack()
{
if (gInitialized)
gErrorStack.snapshot();
}
void
SaveCrashData(uint64 tag, void *ptr, size_t size)
{
if (gInitialized)
gRingBuffer.push(tag, ptr, size);
}
} /* namespace crash */
} /* namespace js */
using namespace js;
using namespace js::crash;
JS_FRIEND_API(void)
js_SnapshotGCStack()
{
if (gInitialized)
gGCStack.snapshot();
}
JS_FRIEND_API(void)
js_SnapshotErrorStack()
{
if (gInitialized)
gErrorStack.snapshot();
}
JS_FRIEND_API(void)
js_SaveCrashData(uint64 tag, void *ptr, size_t size)
{
if (gInitialized)
gRingBuffer.push(tag, ptr, size);
}
JS_PUBLIC_API(void)
JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback)
{
#if 1
#ifdef JS_CRASH_DIAGNOSTICS
if (!gInitialized) {
gInitialized = true;
(*callback)(&gGCStack, sizeof(gGCStack));

View File

@ -42,18 +42,46 @@
#define jscrashreport_h___
#include "jstypes.h"
#include "jsutil.h"
JS_BEGIN_EXTERN_C
namespace js {
namespace crash {
JS_FRIEND_API(void)
js_SnapshotGCStack();
void
SnapshotGCStack();
JS_FRIEND_API(void)
js_SnapshotErrorStack();
void
SnapshotErrorStack();
JS_FRIEND_API(void)
js_SaveCrashData(uint64 tag, void *ptr, size_t size);
void
SaveCrashData(uint64 tag, void *ptr, size_t size);
JS_END_EXTERN_C
template<size_t size, char marker>
class StackBuffer {
private:
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
volatile char buffer[size + 4];
public:
StackBuffer(void *data JS_GUARD_OBJECT_NOTIFIER_PARAM) {
JS_GUARD_OBJECT_NOTIFIER_INIT;
buffer[0] = marker;
buffer[1] = '[';
for (size_t i = 0; i < size; i++) {
if (data)
buffer[i + 2] = ((char *)data)[i];
else
buffer[i + 2] = 0;
}
buffer[size - 2] = ']';
buffer[size - 1] = marker;
}
};
} /* namespace crash */
} /* namespace js */
#endif /* jscrashreport_h___ */

View File

@ -242,7 +242,7 @@ Arena::finalize(JSContext *cx)
if (!newFreeSpanStart)
newFreeSpanStart = thing;
t->finalize(cx);
memset(t, JS_FREE_PATTERN, sizeof(T));
JS_POISON(t, JS_FREE_PATTERN, sizeof(T));
}
}
}
@ -338,27 +338,49 @@ Chunk::init(JSRuntime *rt)
for (size_t i = 0; i != JS_ARRAY_LENGTH(markingDelay); ++i)
markingDelay[i].init();
/*
* The rest of info fields is initailzied in PickChunk. We do not clear
* the mark bitmap as that is done at the start of the next GC.
*/
}
bool
Chunk::unused()
inline Chunk **
GetAvailableChunkList(JSCompartment *comp)
{
return info.numFree == ArenasPerChunk;
JSRuntime *rt = comp->rt;
return comp->isSystemCompartment
? &rt->gcSystemAvailableChunkListHead
: &rt->gcUserAvailableChunkListHead;
}
bool
Chunk::hasAvailableArenas()
inline void
Chunk::addToAvailableList(JSCompartment *comp)
{
return info.numFree > 0;
Chunk **listHeadp = GetAvailableChunkList(comp);
JS_ASSERT(!info.prevp);
JS_ASSERT(!info.next);
info.prevp = listHeadp;
Chunk *head = *listHeadp;
if (head) {
JS_ASSERT(head->info.prevp == listHeadp);
head->info.prevp = &info.next;
}
info.next = head;
*listHeadp = this;
}
bool
Chunk::withinArenasRange(Cell *cell)
inline void
Chunk::removeFromAvailableList()
{
uintptr_t addr = uintptr_t(cell);
if (addr >= uintptr_t(&arenas[0]) && addr < uintptr_t(&arenas[ArenasPerChunk]))
return true;
return false;
JS_ASSERT(info.prevp);
*info.prevp = info.next;
if (info.next) {
JS_ASSERT(info.next->info.prevp == &info.next);
info.next->info.prevp = info.prevp;
}
info.prevp = NULL;
info.next = NULL;
}
template <size_t thingSize>
@ -372,6 +394,9 @@ Chunk::allocateArena(JSContext *cx, unsigned thingKind)
aheader->init(comp, thingKind, thingSize);
--info.numFree;
if (!hasAvailableArenas())
removeFromAvailableList();
JSRuntime *rt = info.runtime;
Probes::resizeHeap(comp, rt->gcBytes, rt->gcBytes + ArenaSize);
JS_ATOMIC_ADD(&rt->gcBytes, ArenaSize);
@ -410,8 +435,27 @@ Chunk::releaseArena(ArenaHeader *aheader)
aheader->next = info.emptyArenaListHead;
info.emptyArenaListHead = aheader;
++info.numFree;
if (unused())
if (info.numFree == 1) {
JS_ASSERT(!info.prevp);
JS_ASSERT(!info.next);
addToAvailableList(aheader->compartment);
} else if (!unused()) {
JS_ASSERT(info.prevp);
} else {
rt->gcChunkSet.remove(this);
removeFromAvailableList();
/*
* We keep empty chunks until we are done with finalization to allow
* calling IsAboutToBeFinalized/Cell::isMarked for finalized GC things
* in empty chunks. So we add the chunk to the empty set even during
* GC_SHRINK.
*/
info.age = 0;
info.next = rt->gcEmptyChunkListHead;
rt->gcEmptyChunkListHead = this;
rt->gcEmptyChunkCount++;
}
}
inline Chunk *
@ -438,100 +482,71 @@ ReleaseGCChunk(JSRuntime *rt, Chunk *p)
inline Chunk *
PickChunk(JSContext *cx)
{
Chunk *chunk = cx->compartment->chunk;
if (chunk && chunk->hasAvailableArenas())
JSCompartment *comp = cx->compartment;
JSRuntime *rt = comp->rt;
Chunk **listHeadp = GetAvailableChunkList(comp);
Chunk *chunk = *listHeadp;
if (chunk)
return chunk;
JSRuntime *rt = cx->runtime;
bool isSystemCompartment = cx->compartment->isSystemCompartment;
/*
* The chunk used for the last allocation is full, search all chunks for
* free arenas.
* We do not have available chunks, either get one from the empty set or
* allocate one.
*/
GCChunkSet::Range
r(isSystemCompartment ? rt->gcSystemChunkSet.all() : rt->gcUserChunkSet.all());
for (; !r.empty(); r.popFront()) {
chunk = r.front();
if (chunk->hasAvailableArenas()) {
cx->compartment->chunk = chunk;
return chunk;
}
}
chunk = AllocateGCChunk(rt);
if (!chunk) {
/* Our last chance is to find an empty chunk in the other chunk set. */
GCChunkSet::Enum e(isSystemCompartment ? rt->gcUserChunkSet : rt->gcSystemChunkSet);
for (; !e.empty(); e.popFront()) {
if (e.front()->info.numFree == ArenasPerChunk) {
chunk = e.front();
e.removeFront();
break;
}
}
chunk = rt->gcEmptyChunkListHead;
if (chunk) {
JS_ASSERT(chunk->unused());
JS_ASSERT(!rt->gcChunkSet.has(chunk));
JS_ASSERT(rt->gcEmptyChunkCount >= 1);
rt->gcEmptyChunkListHead = chunk->info.next;
rt->gcEmptyChunkCount--;
} else {
chunk = AllocateGCChunk(rt);
if (!chunk)
return NULL;
chunk->init(rt);
rt->gcChunkAllocationSinceLastGC = true;
}
/*
* FIXME bug 583732 - chunk is newly allocated and cannot be present in
* the table so using ordinary lookupForAdd is suboptimal here.
*/
GCChunkSet::AddPtr p = isSystemCompartment ?
rt->gcSystemChunkSet.lookupForAdd(chunk) :
rt->gcUserChunkSet.lookupForAdd(chunk);
GCChunkSet::AddPtr p = rt->gcChunkSet.lookupForAdd(chunk);
JS_ASSERT(!p);
if (isSystemCompartment) {
if (!rt->gcSystemChunkSet.add(p, chunk)) {
ReleaseGCChunk(rt, chunk);
return NULL;
}
} else {
if (!rt->gcUserChunkSet.add(p, chunk)) {
ReleaseGCChunk(rt, chunk);
return NULL;
}
if (!rt->gcChunkSet.add(p, chunk)) {
ReleaseGCChunk(rt, chunk);
return NULL;
}
chunk->init(rt);
cx->compartment->chunk = chunk;
rt->gcChunkAllocationSinceLastGC = true;
chunk->info.prevp = NULL;
chunk->info.next = NULL;
chunk->addToAvailableList(comp);
return chunk;
}
static void
ExpireGCChunks(JSRuntime *rt, JSGCInvocationKind gckind)
{
static const size_t MaxAge = 3;
/* Remove unused chunks. */
AutoLockGC lock(rt);
rt->gcChunksWaitingToExpire = 0;
for (GCChunkSet::Enum e(rt->gcUserChunkSet); !e.empty(); e.popFront()) {
Chunk *chunk = e.front();
JS_ASSERT(chunk->info.runtime == rt);
if (chunk->unused()) {
if (gckind == GC_SHRINK || chunk->info.age++ > MaxAge) {
e.removeFront();
ReleaseGCChunk(rt, chunk);
continue;
}
rt->gcChunksWaitingToExpire++;
}
}
for (GCChunkSet::Enum e(rt->gcSystemChunkSet); !e.empty(); e.popFront()) {
Chunk *chunk = e.front();
JS_ASSERT(chunk->info.runtime == rt);
if (chunk->unused()) {
if (gckind == GC_SHRINK || chunk->info.age++ > MaxAge) {
e.removeFront();
ReleaseGCChunk(rt, chunk);
continue;
}
rt->gcChunksWaitingToExpire++;
/* Return old empty chunks to the system. */
for (Chunk **chunkp = &rt->gcEmptyChunkListHead; *chunkp; ) {
JS_ASSERT(rt->gcEmptyChunkCount);
Chunk *chunk = *chunkp;
JS_ASSERT(chunk->unused());
JS_ASSERT(!rt->gcChunkSet.has(chunk));
JS_ASSERT(chunk->info.age <= MAX_EMPTY_CHUNK_AGE);
if (gckind == GC_SHRINK || chunk->info.age == MAX_EMPTY_CHUNK_AGE) {
*chunkp = chunk->info.next;
--rt->gcEmptyChunkCount;
ReleaseGCChunk(rt, chunk);
} else {
/* Keep the chunk but increase its age. */
++chunk->info.age;
chunkp = &chunk->info.next;
}
}
}
@ -571,14 +586,7 @@ static const int64 JIT_SCRIPT_EIGHTH_LIFETIME = 120 * 1000 * 1000;
JSBool
js_InitGC(JSRuntime *rt, uint32 maxbytes)
{
/*
* Make room for at least 16 chunks so the table would not grow before
* the browser starts up.
*/
if (!rt->gcUserChunkSet.init(16))
return false;
if (!rt->gcSystemChunkSet.init(16))
if (!rt->gcChunkSet.init(INITIAL_CHUNK_CAPACITY))
return false;
if (!rt->gcRootsHash.init(256))
@ -720,8 +728,7 @@ MarkIfGCThingWord(JSTracer *trc, jsuword w)
Chunk *chunk = Chunk::fromAddress(addr);
if (!trc->context->runtime->gcUserChunkSet.has(chunk) &&
!trc->context->runtime->gcSystemChunkSet.has(chunk))
if (!trc->context->runtime->gcChunkSet.has(chunk))
return CGCT_NOTCHUNK;
/*
@ -928,12 +935,18 @@ js_FinishGC(JSRuntime *rt)
rt->compartments.clear();
rt->atomsCompartment = NULL;
for (GCChunkSet::Range r(rt->gcUserChunkSet.all()); !r.empty(); r.popFront())
rt->gcSystemAvailableChunkListHead = NULL;
rt->gcUserAvailableChunkListHead = NULL;
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
ReleaseGCChunk(rt, r.front());
for (GCChunkSet::Range r(rt->gcSystemChunkSet.all()); !r.empty(); r.popFront())
ReleaseGCChunk(rt, r.front());
rt->gcUserChunkSet.clear();
rt->gcSystemChunkSet.clear();
rt->gcChunkSet.clear();
for (Chunk *chunk = rt->gcEmptyChunkListHead; chunk; ) {
Chunk *next = chunk->info.next;
ReleaseGCChunk(rt, chunk);
chunk = next;
}
rt->gcEmptyChunkListHead = NULL;
rt->gcEmptyChunkCount = 0;
#ifdef JS_THREADSAFE
rt->gcHelperThread.finish(rt);
@ -1089,7 +1102,7 @@ JSRuntime::setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind)
{
gcLastBytes = lastBytes;
size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, GC_ARENA_ALLOCATION_TRIGGER);
size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, GC_ALLOCATION_THRESHOLD);
float trigger = float(base) * GC_HEAP_GROWTH_FACTOR;
gcTriggerBytes = size_t(Min(float(gcMaxBytes), trigger));
}
@ -1098,7 +1111,7 @@ void
JSRuntime::reduceGCTriggerBytes(uint32 amount) {
JS_ASSERT(amount > 0);
JS_ASSERT(gcTriggerBytes - amount >= 0);
if (gcTriggerBytes - amount < GC_ARENA_ALLOCATION_TRIGGER * GC_HEAP_GROWTH_FACTOR)
if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * GC_HEAP_GROWTH_FACTOR)
return;
gcTriggerBytes -= amount;
}
@ -1108,7 +1121,7 @@ JSCompartment::setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind)
{
gcLastBytes = lastBytes;
size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, GC_ARENA_ALLOCATION_TRIGGER);
size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, GC_ALLOCATION_THRESHOLD);
float trigger = float(base) * GC_HEAP_GROWTH_FACTOR;
gcTriggerBytes = size_t(Min(float(rt->gcMaxBytes), trigger));
}
@ -1117,7 +1130,7 @@ void
JSCompartment::reduceGCTriggerBytes(uint32 amount) {
JS_ASSERT(amount > 0);
JS_ASSERT(gcTriggerBytes - amount >= 0);
if (gcTriggerBytes - amount < GC_ARENA_ALLOCATION_TRIGGER * GC_HEAP_GROWTH_FACTOR)
if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * GC_HEAP_GROWTH_FACTOR)
return;
gcTriggerBytes -= amount;
}
@ -1932,7 +1945,7 @@ MaybeGC(JSContext *cx)
*/
int64 now = PRMJ_Now();
if (rt->gcNextFullGCTime && rt->gcNextFullGCTime <= now) {
if (rt->gcChunkAllocationSinceLastGC || rt->gcChunksWaitingToExpire) {
if (rt->gcChunkAllocationSinceLastGC || rt->gcEmptyChunkListHead) {
GCREASON(MAYBEGC);
js_GC(cx, NULL, GC_SHRINK);
} else {
@ -2258,10 +2271,7 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
JS_ASSERT(gcmarker.getMarkColor() == BLACK);
rt->gcMarkingTracer = &gcmarker;
for (GCChunkSet::Range r(rt->gcUserChunkSet.all()); !r.empty(); r.popFront())
r.front()->bitmap.clear();
for (GCChunkSet::Range r(rt->gcSystemChunkSet.all()); !r.empty(); r.popFront())
for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
r.front()->bitmap.clear();
if (comp) {
@ -2402,9 +2412,6 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
printf("GC HEAP SIZE %lu\n", (unsigned long)rt->gcBytes);
}
#endif
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
js::CheckCompartmentScripts(*c);
}
#ifdef JS_THREADSAFE
@ -2696,7 +2703,7 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
GCCrashData crashData;
crashData.isRegen = rt->shapeGen & SHAPE_OVERFLOW_BIT;
crashData.isCompartment = !!comp;
js_SaveCrashData(crash::JS_CRASH_TAG_GC, &crashData, sizeof(crashData));
crash::SaveCrashData(crash::JS_CRASH_TAG_GC, &crashData, sizeof(crashData));
GCTIMER_BEGIN(rt, comp);
@ -2747,7 +2754,7 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
rt->gcChunkAllocationSinceLastGC = false;
GCTIMER_END(gckind == GC_LAST_CONTEXT);
js_SnapshotGCStack();
crash::SnapshotGCStack();
}
namespace js {

View File

@ -514,8 +514,9 @@ struct MarkingDelay {
/* The chunk header (located at the end of the chunk to preserve arena alignment). */
struct ChunkInfo {
Chunk *link;
JSRuntime *runtime;
Chunk *next;
Chunk **prevp;
ArenaHeader *emptyArenaListHead;
size_t age;
size_t numFree;
@ -613,10 +614,24 @@ struct Chunk {
return (addr & GC_CHUNK_MASK) >> ArenaShift;
}
uintptr_t address() const {
uintptr_t addr = reinterpret_cast<uintptr_t>(this);
JS_ASSERT(!(addr & GC_CHUNK_MASK));
return addr;
}
void init(JSRuntime *rt);
bool unused();
bool hasAvailableArenas();
bool withinArenasRange(Cell *cell);
bool unused() const {
return info.numFree == ArenasPerChunk;
}
bool hasAvailableArenas() const {
return info.numFree > 0;
}
inline void addToAvailableList(JSCompartment *compartment);
inline void removeFromAvailableList();
template <size_t thingSize>
ArenaHeader *allocateArena(JSContext *cx, unsigned thingKind);
@ -750,13 +765,12 @@ Cell::compartment() const
/*
* Lower limit after which we limit the heap growth
*/
const size_t GC_ARENA_ALLOCATION_TRIGGER = 30 * js::GC_CHUNK_SIZE;
const size_t GC_ALLOCATION_THRESHOLD = 30 * 1024 * 1024;
/*
* A GC is triggered once the number of newly allocated arenas
* is GC_HEAP_GROWTH_FACTOR times the number of live arenas after
* the last GC starting after the lower limit of
* GC_ARENA_ALLOCATION_TRIGGER.
* A GC is triggered once the number of newly allocated arenas is
* GC_HEAP_GROWTH_FACTOR times the number of live arenas after the last GC
* starting after the lower limit of GC_ALLOCATION_THRESHOLD.
*/
const float GC_HEAP_GROWTH_FACTOR = 3.0f;
@ -998,9 +1012,17 @@ struct FreeLists {
extern void *
RefillFinalizableFreeList(JSContext *cx, unsigned thingKind);
} /* namespace gc */
/*
* Initial allocation size for data structures holding chunks is set to hold
* chunks with total capacity of 16MB to avoid buffer resizes during browser
* startup.
*/
const size_t INITIAL_CHUNK_CAPACITY = 16 * 1024 * 1024 / GC_CHUNK_SIZE;
typedef Vector<gc::Chunk *, 32, SystemAllocPolicy> GCChunks;
/* The number of GC cycles an empty chunk can survive before been released. */
const size_t MAX_EMPTY_CHUNK_AGE = 4;
} /* namespace gc */
struct GCPtrHasher
{

View File

@ -100,13 +100,6 @@ PushMarkStack(GCMarker *gcmarker, JSShortString *thing);
static inline void
PushMarkStack(GCMarker *gcmarker, JSString *thing);
static void
volatile_memcpy(volatile unsigned char *dst, const void *src, size_t n)
{
for (size_t i = 0; i < n; i++)
dst[i] = ((char *)src)[i];
}
template<typename T>
void
Mark(JSTracer *trc, T *thing)
@ -122,15 +115,9 @@ Mark(JSTracer *trc, T *thing)
JS_ASSERT(thing->compartment());
JS_ASSERT(thing->compartment()->rt == rt);
if (rt->gcCheckCompartment && thing->compartment() != rt->gcCheckCompartment &&
thing->compartment() != rt->atomsCompartment)
{
volatile unsigned char dbg[sizeof(T) + 2];
dbg[0] = 0xab;
dbg[1] = 0xcd;
volatile_memcpy(dbg + 2, thing, sizeof(T));
JS_Assert("compartment mismatch in GC", __FILE__, __LINE__);
}
JS_OPT_ASSERT_IF(rt->gcCheckCompartment,
thing->compartment() == rt->gcCheckCompartment ||
thing->compartment() == rt->atomsCompartment);
/*
* Don't mark things outside a compartment if we are in a per-compartment

View File

@ -156,6 +156,19 @@ js::GetBlockChain(JSContext *cx, StackFrame *fp)
JSScript *script = fp->script();
jsbytecode *start = script->code;
/*
* If the debugger asks for the scope chain at a pc where we are about to
* fix it up, advance target past the fixup. See bug 672804.
*/
JSOp op = js_GetOpcode(cx, script, target);
while (op == JSOP_NOP || op == JSOP_INDEXBASE || op == JSOP_INDEXBASE1 ||
op == JSOP_INDEXBASE2 || op == JSOP_INDEXBASE3 ||
op == JSOP_BLOCKCHAIN || op == JSOP_NULLBLOCKCHAIN)
{
target += js_CodeSpec[op].length;
op = js_GetOpcode(cx, script, target);
}
JS_ASSERT(target >= start && target < start + script->length);
JSObject *blockChain = NULL;

View File

@ -3494,24 +3494,6 @@ CopySlots(JSContext *cx, JSObject *from, JSObject *to)
return true;
}
static void
CheckProxy(JSObject *obj)
{
if (!obj->isProxy())
return;
JSProxyHandler *handler = obj->getProxyHandler();
if (handler->isCrossCompartment())
return;
Value priv = obj->getProxyPrivate();
if (!priv.isObject())
return;
if (priv.toObject().compartment() != obj->compartment())
JS_Assert("compartment mismatch in proxy object", __FILE__, __LINE__);
}
JSObject *
JSObject::clone(JSContext *cx, JSObject *proto, JSObject *parent)
{
@ -3549,8 +3531,6 @@ JSObject::clone(JSContext *cx, JSObject *proto, JSObject *parent)
return NULL;
}
CheckProxy(clone);
return clone;
}
@ -3663,11 +3643,6 @@ JSObject::swap(JSContext *cx, JSObject *other)
TradeGuts(this, otherClone);
TradeGuts(other, thisClone);
CheckProxy(this);
CheckProxy(other);
CheckProxy(thisClone);
CheckProxy(otherClone);
return true;
}

View File

@ -350,14 +350,14 @@ inline uint32
JSObject::getArrayLength() const
{
JS_ASSERT(isArray());
return (uint32)(size_t) getPrivate();
return (uint32)(uintptr_t) getPrivate();
}
inline void
JSObject::setArrayLength(uint32 length)
{
JS_ASSERT(isArray());
setPrivate((void*)(size_t)length);
setPrivate((void*)(uintptr_t) length);
}
inline uint32

View File

@ -4965,14 +4965,16 @@ CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc)
pn->pn_link = dn->dn_uses;
dn->dn_uses = pn;
} else if (opn->pn_defn) {
/* We copied some definition-specific state into pn. Clear it out. */
} else {
pn->pn_expr = NULL;
pn->pn_cookie.makeFree();
pn->pn_dflags &= ~PND_BOUND;
pn->pn_defn = false;
if (opn->pn_defn) {
/* We copied some definition-specific state into pn. Clear it out. */
pn->pn_cookie.makeFree();
pn->pn_dflags &= ~PND_BOUND;
pn->pn_defn = false;
LinkUseToDef(pn, (JSDefinition *) opn, tc);
LinkUseToDef(pn, (JSDefinition *) opn, tc);
}
}
return pn;
}

View File

@ -1171,11 +1171,6 @@ NewProxyObject(JSContext *cx, JSProxyHandler *handler, const Value &priv, JSObje
else
clasp = handler->isOuterWindow() ? &OuterWindowProxyClass : &ObjectProxyClass;
if (!handler->isCrossCompartment() && priv.isObject()) {
if (priv.toObject().compartment() != cx->compartment)
JS_Assert("compartment mismatch in proxy object", __FILE__, __LINE__);
}
JSObject *obj = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
if (!obj || !obj->ensureInstanceReservedSlots(cx, 0))
return NULL;

View File

@ -92,10 +92,6 @@ class JS_FRIEND_API(JSProxyHandler) {
return false;
}
virtual bool isCrossCompartment() {
return false;
}
inline void *family() {
return mFamily;
}

View File

@ -166,6 +166,7 @@ typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
typedef struct JSPropertyName JSPropertyName;
#ifdef __cplusplus
typedef class JSWrapper JSWrapper;

View File

@ -2131,8 +2131,6 @@ TokenStream::getTokenInternal()
return tt;
error:
JS_ASSERT(cx->isExceptionPending());
/*
* For erroneous multi-line tokens we won't have changed end.lineno (it'll
* still be equal to begin.lineno) so we revert end.index to be equal to

View File

@ -46,6 +46,7 @@
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h"
#include "jscrashreport.h"
#include "jsprf.h"
#include "jsapi.h"
#include "jsatom.h"
@ -288,44 +289,26 @@ Bindings::trace(JSTracer *trc)
} /* namespace js */
static void
volatile_memcpy(volatile char *dst, void *src, size_t n)
{
for (size_t i = 0; i < n; i++)
dst[i] = ((char *)src)[i];
}
static void
CheckScript(JSScript *script, JSScript *prev)
{
volatile char dbg1[sizeof(JSScript)], dbg2[sizeof(JSScript)];
#ifdef JS_CRASH_DIAGNOSTICS
if (script->cookie1 != JS_SCRIPT_COOKIE || script->cookie2 != JS_SCRIPT_COOKIE) {
volatile_memcpy(dbg1, script, sizeof(JSScript));
if (prev)
volatile_memcpy(dbg2, prev, sizeof(JSScript));
crash::StackBuffer<sizeof(JSScript), 0x87> buf1(script);
crash::StackBuffer<sizeof(JSScript), 0x88> buf2(prev);
JS_OPT_ASSERT(false);
}
JS_OPT_ASSERT(script->cookie1 == JS_SCRIPT_COOKIE && script->cookie2 == JS_SCRIPT_COOKIE);
#endif
}
static void
CheckScriptOwner(JSScript *script, JSObject *owner)
{
if (script->ownerObject != owner) {
volatile char scriptData[sizeof(JSScript)];
volatile char owner1Data[sizeof(JSObject)], owner2Data[sizeof(JSObject)];
volatile char savedOwner[sizeof(JSObject *)];
volatile_memcpy(scriptData, script, sizeof(JSScript));
volatile_memcpy(savedOwner, &owner, sizeof(JSObject *));
if (script->ownerObject != JS_NEW_SCRIPT && script->ownerObject != JS_CACHED_SCRIPT)
volatile_memcpy(owner1Data, script->ownerObject, sizeof(JSObject));
if (owner != JS_NEW_SCRIPT && owner != JS_CACHED_SCRIPT)
volatile_memcpy(owner2Data, owner, sizeof(JSObject));
}
#ifdef JS_CRASH_DIAGNOSTICS
JS_OPT_ASSERT(script->ownerObject == owner);
if (owner != JS_NEW_SCRIPT && owner != JS_CACHED_SCRIPT)
JS_OPT_ASSERT(script->compartment == owner->compartment());
#endif
}
#if JS_HAS_XDR
@ -982,8 +965,10 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom
return NULL;
PodZero(script);
#ifdef JS_CRASH_DIAGNOSTICS
script->cookie1 = script->cookie2 = JS_SCRIPT_COOKIE;
script->ownerObject = JS_NEW_SCRIPT;
#endif
script->length = length;
script->version = version;
new (&script->bindings) Bindings(cx, emptyCallShape);
@ -1306,8 +1291,10 @@ JSScript::totalSize()
void
JSScript::setOwnerObject(JSObject *owner)
{
#ifdef JS_CRASH_DIAGNOSTICS
CheckScriptOwner(this, JS_NEW_SCRIPT);
ownerObject = owner;
#endif
}
/*
@ -1349,22 +1336,6 @@ js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
JS_ClearScriptTraps(cx, script);
}
namespace js {
void
CheckCompartmentScripts(JSCompartment *comp)
{
JSScript *prev = NULL;
for (JSScript *script = (JSScript *)comp->scripts.next;
&script->links != &comp->scripts;
prev = script, script = (JSScript *)script->links.next)
{
CheckScript(script, prev);
}
}
} /* namespace js */
static void
DestroyScript(JSContext *cx, JSScript *script, JSObject *owner, uint32 caller)
{
@ -1429,7 +1400,7 @@ DestroyScript(JSContext *cx, JSScript *script, JSObject *owner, uint32 caller)
if (script->sourceMap)
cx->free_(script->sourceMap);
memset(script, 0xdb, script->totalSize());
JS_POISON(script, 0xdb, sizeof(JSScript));
*(uint32 *)script = caller;
cx->free_(script);
}
@ -1464,9 +1435,10 @@ js_TraceScript(JSTracer *trc, JSScript *script, JSObject *owner)
if (owner)
CheckScriptOwner(script, owner);
#ifdef JS_CRASH_DIAGNOSTICS
JSRuntime *rt = trc->context->runtime;
if (rt->gcCheckCompartment && script->compartment != rt->gcCheckCompartment)
JS_Assert("compartment mismatch in GC", __FILE__, __LINE__);
JS_OPT_ASSERT_IF(rt->gcCheckCompartment, script->compartment == rt->gcCheckCompartment);
#endif
JSAtomMap *map = &script->atomMap;
MarkAtomRange(trc, map->length, map->vector, "atomMap");

View File

@ -449,7 +449,9 @@ struct JSScript {
jsbytecode *code; /* bytecodes and their immediate operands */
uint32 length; /* length of code vector */
#ifdef JS_CRASH_DIAGNOSTICS
uint32 cookie1;
#endif
private:
uint16 version; /* JS version under which script was compiled */
@ -507,7 +509,9 @@ struct JSScript {
JSPrincipals *principals;/* principals for this script */
jschar *sourceMap; /* source map file or null */
#ifdef JS_CRASH_DIAGNOSTICS
JSObject *ownerObject;
#endif
void setOwnerObject(JSObject *owner);
@ -535,7 +539,9 @@ struct JSScript {
/* array of execution counters for every JSOp in the script, by runmode */
JSPCCounters pcCounters;
#ifdef JS_CRASH_DIAGNOSTICS
uint32 cookie2;
#endif
public:
#ifdef JS_METHODJIT
@ -742,19 +748,6 @@ js_DestroyScriptFromGC(JSContext *cx, JSScript *script, JSObject *owner);
extern void
js_DestroyCachedScript(JSContext *cx, JSScript *script);
namespace js {
/*
* This diagnostic function checks that a compartment's list of scripts
* contains only valid scripts. It also searches for the target script
* in the list. If expected is true, it asserts that the target script
* is found. If expected is false, it asserts that it's not found.
*/
void
CheckCompartmentScripts(JSCompartment *comp);
} /* namespace js */
extern void
js_TraceScript(JSTracer *trc, JSScript *script, JSObject *owner);

View File

@ -1535,11 +1535,8 @@ MatchCallback(JSContext *cx, RegExpStatics *res, size_t count, void *p)
}
Value v;
if (!res->createLastMatch(cx, &v))
return false;
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
return !!arrayobj->setProperty(cx, INT_TO_JSID(count), &v, false);
return res->createLastMatch(cx, &v) &&
arrayobj->defineProperty(cx, INT_TO_JSID(count), v);
}
static JSBool

View File

@ -10467,7 +10467,10 @@ TraceRecorder::record_EnterFrame()
/* Try inlining one level in case this recursion doesn't go too deep. */
if (fp->script() == fp->prev()->script() &&
fp->prev()->prev() && fp->prev()->prev()->script() == fp->script()) {
fp->prev()->prev() &&
fp->prev()->prev()->isScriptFrame() &&
fp->prev()->prev()->script() == fp->script())
{
RETURN_STOP_A("recursion started inlining");
}

View File

@ -45,7 +45,6 @@
#define jsutil_h___
#include "jstypes.h"
#include "jscrashreport.h"
#include "mozilla/Util.h"
#include <stdlib.h>
#include <string.h>
@ -62,12 +61,24 @@ JS_BEGIN_EXTERN_C
#define JS_FREE_PATTERN 0xDA
#ifdef JS_CRASH_DIAGNOSTICS
#define JS_POISON(p, val, size) memset((p), (val), (size))
#define JS_OPT_ASSERT(expr) \
((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
#define JS_OPT_ASSERT_IF(cond, expr) \
((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
#else
#define JS_POISON(p, val, size) ((void) 0)
#define JS_OPT_ASSERT(expr) ((void) 0)
#define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
#endif /* JS_CRASH_DIAGNOSTICS */
#ifdef DEBUG
#define JS_ASSERT(expr) \
@ -227,12 +238,6 @@ extern JS_PUBLIC_DATA(JSUint32) OOM_counter; /* data race, who cares. */
#define JS_OOM_POSSIBLY_FAIL() do {} while(0)
#endif
static JS_INLINE void *js_record_oom(void *p) {
if (!p)
js_SnapshotErrorStack();
return p;
}
/*
* SpiderMonkey code should not be calling these allocation functions directly.
* Instead, all calls should go through JSRuntime, JSContext or OffTheBooks.
@ -240,17 +245,17 @@ static JS_INLINE void *js_record_oom(void *p) {
*/
static JS_INLINE void* js_malloc(size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
return js_record_oom(malloc(bytes));
return malloc(bytes);
}
static JS_INLINE void* js_calloc(size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
return js_record_oom(calloc(bytes, 1));
return calloc(bytes, 1);
}
static JS_INLINE void* js_realloc(void* p, size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
return js_record_oom(realloc(p, bytes));
return realloc(p, bytes);
}
static JS_INLINE void js_free(void* p) {
@ -271,13 +276,13 @@ JS_END_EXTERN_C
*
* Allocation:
* - Prefer to allocate using JSContext:
* cx->{malloc_,realloc_,calloc_,new_,new_array}
* cx->{malloc_,realloc_,calloc_,new_,array_new}
*
* - If no JSContext is available, use a JSRuntime:
* rt->{malloc_,realloc_,calloc_,new_,new_array}
* rt->{malloc_,realloc_,calloc_,new_,array_new}
*
* - As a last resort, use unaccounted allocation ("OffTheBooks"):
* js::OffTheBooks::{malloc_,realloc_,calloc_,new_,new_array}
* js::OffTheBooks::{malloc_,realloc_,calloc_,new_,array_new}
*
* Deallocation:
* - When the deallocation occurs on a slow path, use:

View File

@ -956,6 +956,8 @@ typedef void
class AutoIdVector;
class PropertyName;
/*
* Prepare to make |obj| non-extensible; in particular, fully resolve its properties.
* On error, return false.
@ -983,6 +985,9 @@ static inline JSCheckAccessOp Jsvalify(CheckAccessOp f) { return (JSChec
static inline EqualityOp Valueify(JSEqualityOp f); /* Same type as JSHasInstanceOp */
static inline JSEqualityOp Jsvalify(EqualityOp f); /* Same type as HasInstanceOp */
static inline PropertyName *Valueify(JSPropertyName *n) { return (PropertyName *)n; }
static inline JSPropertyName *Jsvalify(PropertyName *n) { return (JSPropertyName *)n; }
static const PropertyOp PropertyStub = (PropertyOp)JS_PropertyStub;
static const StrictPropertyOp StrictPropertyStub = (StrictPropertyOp)JS_StrictPropertyStub;
static const JSEnumerateOp EnumerateStub = JS_EnumerateStub;

View File

@ -413,7 +413,7 @@ ForceFrame::enter()
JSObject *scopeChain = target->getGlobal();
JS_ASSERT(scopeChain->isNative());
return context->stack.pushDummyFrame(context, *scopeChain, frame);
return context->stack.pushDummyFrame(context, REPORT_ERROR, *scopeChain, frame);
}
AutoCompartment::AutoCompartment(JSContext *cx, JSObject *target)
@ -442,8 +442,21 @@ AutoCompartment::enter()
JS_ASSERT(scopeChain->isNative());
frame.construct();
if (!context->stack.pushDummyFrame(context, *scopeChain, &frame.ref()))
/*
* Set the compartment eagerly so that pushDummyFrame associates the
* resource allocation request with 'destination' instead of 'origin'.
* (This is important when content has overflowed the stack and chrome
* is preparing to run JS to throw up a slow script dialog.) However,
* if an exception is thrown, we need it to be in origin's compartment
* so be careful to only report after restoring.
*/
context->compartment = destination;
if (!context->stack.pushDummyFrame(context, DONT_REPORT_ERROR, *scopeChain, &frame.ref())) {
context->compartment = origin;
js_ReportOverRecursed(context);
return false;
}
if (context->isExceptionPending())
context->wrapPendingException();

View File

@ -155,10 +155,6 @@ class JS_FRIEND_API(JSCrossCompartmentWrapper) : public JSWrapper {
virtual void trace(JSTracer *trc, JSObject *wrapper);
virtual bool isCrossCompartment() {
return true;
}
static JSCrossCompartmentWrapper singleton;
};

View File

@ -3,6 +3,7 @@ script 15.5.4.2.js
script 15.5.4.7.js
script 15.5.4.11-01.js
script defaultvalue.js
script match-defines-match-elements.js
script split-01.js
script split-undefined-separator.js
script split-xregexp.js

View File

@ -0,0 +1,47 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var BUGNUMBER = 677820;
var summary =
"String.prototype.match must define matches on the returned array, not set " +
"them";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var called = false;
function setterFunction(v) { called = true; }
function getterFunction(v) { return "getter"; }
Object.defineProperty(Array.prototype, 1,
{ get: getterFunction, set: setterFunction });
assertEq(called, false);
var matches = "abcdef".match(/./g);
assertEq(called, false);
assertEq(matches.length, 6);
assertEq(matches[0], "a");
assertEq(matches[1], "b");
assertEq(matches[2], "c");
assertEq(matches[3], "d");
assertEq(matches[4], "e");
assertEq(matches[5], "f");
var desc = Object.getOwnPropertyDescriptor(Array.prototype, 1);
assertEq(desc.get, getterFunction);
assertEq(desc.set, setterFunction);
assertEq(desc.enumerable, false);
assertEq(desc.configurable, false);
assertEq([][1], "getter");
assertEq(called, false);
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

View File

@ -53,5 +53,8 @@ script weakmap.js
script regress-645160.js
script regress-650753.js
script regress-668438.js
require-or(debugMode,skip) script regress-672804-1.js
require-or(debugMode,skip) script regress-672804-2.js
require-or(debugMode,skip) script regress-672804-3.js
skip-if(!xulRuntime.shell) script regress-677589.js
script regress-677924.js

View File

@ -0,0 +1,12 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var a = 0;
function f() {
let (a = let (x = 1) x) {}
}
trap(f, 3, 'assertEq(evalInFrame(1, "a"), 0)');
f();
reportCompare(0, 0, 'ok');

View File

@ -0,0 +1,12 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var a = 0;
function f() {
let (a = let (x = 1) x) {}
}
trap(f, 4, 'assertEq(evalInFrame(1, "a"), 0)');
f();
reportCompare(0, 0, 'ok');

View File

@ -0,0 +1,11 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var e = [], x = {b: []};
function f() {
let (a = [[] for (x in e)], {b: []} = x) {}
}
trap(f, 4, '');
f();
reportCompare(0, 0, 'ok');

View File

@ -109,6 +109,7 @@ script regress-646820-3.js
script regress-665355.js
script regress-666599.js
script regress-667047.js
script regress-672892.js
script regress-673070-1.js
script regress-673070-2.js
script regress-673070-3.js

View File

@ -0,0 +1,8 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
with (0)
for (var b = 0 in 0) // don't assert in parser
;
reportCompare(0, 0, 'ok');

View File

@ -388,8 +388,7 @@ StackSpace::ensureEnoughSpaceToEnterTrace(JSContext *cx)
STATIC_POSTCONDITION(!return || ubound(from) >= nvals)
JS_ALWAYS_INLINE bool
StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals,
JSCompartment *dest) const
StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals) const
{
assertInvariants();
JS_ASSERT(from >= firstUnused());
@ -397,16 +396,10 @@ StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptr
JS_ASSERT(from <= commitEnd_);
#endif
if (JS_UNLIKELY(conservativeEnd_ - from < nvals))
return ensureSpaceSlow(cx, report, from, nvals, dest);
return ensureSpaceSlow(cx, report, from, nvals);
return true;
}
bool
StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals) const
{
return ensureSpace(cx, report, from, nvals, cx->compartment);
}
inline Value *
StackSpace::getStackLimit(JSContext *cx, MaybeReportError report)
{

View File

@ -414,13 +414,13 @@ StackSpace::mark(JSTracer *trc)
}
JS_FRIEND_API(bool)
StackSpace::ensureSpaceSlow(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals,
JSCompartment *dest) const
StackSpace::ensureSpaceSlow(JSContext *cx, MaybeReportError report,
Value *from, ptrdiff_t nvals) const
{
assertInvariants();
JS_ASSERT_IF(dest, cx);
bool trusted = !dest || dest->principals == cx->runtime->trustedPrincipals();
bool trusted = !cx->compartment ||
cx->compartment->principals == cx->runtime->trustedPrincipals();
Value *end = trusted ? trustedEnd_ : defaultEnd_;
/*
@ -548,17 +548,17 @@ ContextStack::containsSlow(const StackFrame *target) const
*/
Value *
ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, uintN nvars,
MaybeExtend extend, bool *pushedSeg, JSCompartment *dest)
MaybeExtend extend, bool *pushedSeg)
{
Value *firstUnused = space().firstUnused();
if (onTop() && extend) {
if (!space().ensureSpace(cx, report, firstUnused, nvars, dest))
if (!space().ensureSpace(cx, report, firstUnused, nvars))
return NULL;
return firstUnused;
}
if (!space().ensureSpace(cx, report, firstUnused, VALUES_PER_STACK_SEGMENT + nvars, dest))
if (!space().ensureSpace(cx, report, firstUnused, VALUES_PER_STACK_SEGMENT + nvars))
return NULL;
FrameRegs *regs;
@ -577,13 +577,6 @@ ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, uintN nvars,
return seg_->slotsBegin();
}
Value *
ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, uintN nvars,
MaybeExtend extend, bool *pushedSeg)
{
return ensureOnTop(cx, report, nvars, extend, pushedSeg, cx->compartment);
}
void
ContextStack::popSegment()
{
@ -703,12 +696,11 @@ ContextStack::pushExecuteFrame(JSContext *cx, JSScript *script, const Value &thi
}
bool
ContextStack::pushDummyFrame(JSContext *cx, JSObject &scopeChain, DummyFrameGuard *dfg)
ContextStack::pushDummyFrame(JSContext *cx, MaybeReportError report, JSObject &scopeChain,
DummyFrameGuard *dfg)
{
JSCompartment *dest = scopeChain.compartment();
uintN nvars = VALUES_PER_STACK_FRAME;
Value *firstUnused = ensureOnTop(cx, REPORT_ERROR, nvars, CAN_EXTEND, &dfg->pushedSeg_, dest);
Value *firstUnused = ensureOnTop(cx, report, nvars, CAN_EXTEND, &dfg->pushedSeg_);
if (!firstUnused)
return NULL;
@ -716,7 +708,6 @@ ContextStack::pushDummyFrame(JSContext *cx, JSObject &scopeChain, DummyFrameGuar
fp->initDummyFrame(cx, scopeChain);
dfg->regs_.initDummyFrame(*fp);
cx->compartment = dest;
dfg->prevRegs_ = seg_->pushRegs(dfg->regs_);
JS_ASSERT(space().firstUnused() == dfg->regs_.sp);
dfg->setPushed(*this);
@ -799,11 +790,24 @@ ContextStack::popGeneratorFrame(const GeneratorFrameGuard &gfg)
bool
ContextStack::saveFrameChain()
{
JSCompartment *dest = NULL;
/*
* The StackSpace uses the context's current compartment to determine
* whether to allow access to the privileged end-of-stack buffer.
* However, we always want saveFrameChain to have access to this privileged
* buffer since it gets used to prepare calling trusted JS. To force this,
* we clear the current compartment (which is interpreted by ensureSpace as
* 'trusted') and either restore it on OOM or let resetCompartment()
* clobber it.
*/
JSCompartment *original = cx_->compartment;
cx_->compartment = NULL;
bool pushedSeg;
if (!ensureOnTop(cx_, REPORT_ERROR, 0, CANT_EXTEND, &pushedSeg, dest))
if (!ensureOnTop(cx_, DONT_REPORT_ERROR, 0, CANT_EXTEND, &pushedSeg)) {
cx_->compartment = original;
js_ReportOverRecursed(cx_);
return false;
}
JS_ASSERT(pushedSeg);
JS_ASSERT(!hasfp());

View File

@ -44,7 +44,6 @@
#include "jsfun.h"
struct JSContext;
struct JSCompartment;
namespace js {
@ -1330,15 +1329,10 @@ class StackSpace
friend class ContextStack;
friend class StackFrame;
inline bool ensureSpace(JSContext *cx, MaybeReportError report,
Value *from, ptrdiff_t nvals,
JSCompartment *dest) const;
inline bool ensureSpace(JSContext *cx, MaybeReportError report,
Value *from, ptrdiff_t nvals) const;
JS_FRIEND_API(bool) ensureSpaceSlow(JSContext *cx, MaybeReportError report,
Value *from, ptrdiff_t nvals,
JSCompartment *dest) const;
Value *from, ptrdiff_t nvals) const;
StackSegment &findContainingSegment(const StackFrame *target) const;
public:
@ -1426,9 +1420,6 @@ class ContextStack
/* Implementation details of push* public interface. */
StackSegment *pushSegment(JSContext *cx);
enum MaybeExtend { CAN_EXTEND = true, CANT_EXTEND = false };
Value *ensureOnTop(JSContext *cx, MaybeReportError report, uintN nvars,
MaybeExtend extend, bool *pushedSeg,
JSCompartment *dest);
Value *ensureOnTop(JSContext *cx, MaybeReportError report, uintN nvars,
MaybeExtend extend, bool *pushedSeg);
@ -1511,16 +1502,9 @@ class ContextStack
*/
bool pushGeneratorFrame(JSContext *cx, JSGenerator *gen, GeneratorFrameGuard *gfg);
/*
* When changing the compartment of a cx, it is necessary to immediately
* change the scope chain to a global in the right compartment since any
* amount of general VM code can run before the first scripted frame is
* pushed (if at all). This is currently and hackily accomplished by
* pushing a "dummy frame" with the correct scope chain. On success, this
* function will change the compartment to 'scopeChain.compartment()' and
* push a dummy frame for 'scopeChain'. On failure, nothing is changed.
*/
bool pushDummyFrame(JSContext *cx, JSObject &scopeChain, DummyFrameGuard *dfg);
/* Pushes a "dummy" frame; should be removed one day. */
bool pushDummyFrame(JSContext *cx, MaybeReportError report, JSObject &scopeChain,
DummyFrameGuard *dfg);
/*
* An "inline frame" may only be pushed from within the top, active

View File

@ -89,6 +89,21 @@ JSDependentString::new_(JSContext *cx, JSLinearString *base, const jschar *chars
return str;
}
inline js::PropertyName *
JSFlatString::toPropertyName(JSContext *cx)
{
#ifdef DEBUG
uint32 dummy;
JS_ASSERT(!isElement(&dummy));
#endif
if (isAtom())
return asAtom().asPropertyName();
JSAtom *atom = js_AtomizeString(cx, this);
if (!atom)
return NULL;
return atom->asPropertyName();
}
JS_ALWAYS_INLINE void
JSFixedString::init(const jschar *chars, size_t length)
{

View File

@ -38,9 +38,12 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/RangedPtr.h"
#include "String.h"
#include "String-inl.h"
using namespace mozilla;
using namespace js;
bool
@ -317,3 +320,52 @@ JSDependentString::undepend(JSContext *cx)
JSStringFinalizeOp JSExternalString::str_finalizers[JSExternalString::TYPE_LIMIT] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
bool
JSFlatString::isElement(uint32 *indexp) const
{
const jschar *s = charsZ();
jschar ch = *s;
if (!JS7_ISDEC(ch))
return false;
size_t n = length();
if (n > UINT32_CHAR_BUFFER_LENGTH)
return false;
/*
* Make sure to account for the '\0' at the end of characters, dereferenced
* in the loop below.
*/
RangedPtr<const jschar> cp(s, n + 1);
const RangedPtr<const jschar> end(s + n, s, n + 1);
uint32 index = JS7_UNDEC(*cp++);
uint32 oldIndex = 0;
uint32 c = 0;
if (index != 0) {
while (JS7_ISDEC(*cp)) {
oldIndex = index;
c = JS7_UNDEC(*cp);
index = 10 * index + c;
cp++;
}
}
/* It's not an element if there are characters after the number. */
if (cp != end)
return false;
/*
* Look out for "4294967296" and larger-number strings that fit in
* UINT32_CHAR_BUFFER_LENGTH: only unsigned 32-bit integers shall pass.
*/
if (oldIndex < UINT32_MAX / 10 || (oldIndex == UINT32_MAX / 10 && c <= (UINT32_MAX % 10))) {
*indexp = index;
return true;
}
return false;
}

View File

@ -43,6 +43,7 @@
#include "jscell.h"
class JSString;
class JSDependentString;
class JSExtensibleString;
class JSExternalString;
@ -52,6 +53,29 @@ class JSStaticAtom;
class JSRope;
class JSAtom;
namespace js {
class PropertyName;
/* The buffer length required to contain any unsigned 32-bit integer. */
static const size_t UINT32_CHAR_BUFFER_LENGTH = sizeof("4294967295") - 1;
/* N.B. must correspond to boolean tagging behavior. */
enum InternBehavior
{
DoNotInternAtom = false,
InternAtom = true
};
} /* namespace js */
/*
* Find or create the atom for a string. Return null on failure to allocate
* memory.
*/
extern JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
/*
* JavaScript strings
*
@ -474,6 +498,21 @@ class JSFlatString : public JSLinearString
return chars();
}
/*
* Returns true if this string's characters store an unsigned 32-bit
* integer value, initializing *indexp to that value if so. (Thus if
* calling isElement returns true, js::IndexToString(cx, *indexp) will be a
* string equal to this string.)
*/
bool isElement(uint32 *indexp) const;
/*
* Returns a property name represented by this string, or null on failure.
* You must verify that this is not an element per isElement before calling
* this method.
*/
inline js::PropertyName *toPropertyName(JSContext *cx);
/* Only called by the GC for strings with the FINALIZE_STRING kind. */
inline void finalize(JSRuntime *rt);
@ -678,6 +717,9 @@ class JSAtom : public JSFixedString
/* Return null if no static atom exists for the given (chars, length). */
static inline JSStaticAtom *lookupStatic(const jschar *chars, size_t length);
/* Returns the PropertyName for this. isElement() must be false. */
inline js::PropertyName *asPropertyName();
inline void finalize(JSRuntime *rt);
};
@ -708,7 +750,21 @@ class JSStaticAtom : public JSAtom
JS_STATIC_ASSERT(sizeof(JSStaticAtom) == sizeof(JSString));
/* Avoid requring vm/String-inl.h just to call getChars. */
namespace js {
/*
* Represents an atomized string which does not contain an unsigned 32-bit
* value. That is, it is never the case that for a PropertyName propname,
* ToString(ToUint32(propname)) is equal to propname.
*/
class PropertyName : public JSAtom
{};
JS_STATIC_ASSERT(sizeof(PropertyName) == sizeof(JSString));
} /* namespace js */
/* Avoid requiring vm/String-inl.h just to call getChars. */
JS_ALWAYS_INLINE const jschar *
JSString::getChars(JSContext *cx)
@ -758,4 +814,14 @@ JSString::ensureFixed(JSContext *cx)
return &asFixed();
}
inline js::PropertyName *
JSAtom::asPropertyName()
{
#ifdef DEBUG
uint32 dummy;
JS_ASSERT(!isElement(&dummy));
#endif
return static_cast<js::PropertyName *>(this);
}
#endif

View File

@ -4646,8 +4646,8 @@ nsCSSFrameConstructor::FindMathMLData(Element* aElement,
SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmsupFrame),
SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmsubFrame),
SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmsubsupFrame),
SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderFrame),
SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmoverFrame),
SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame),
SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame),
SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame),
SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmphantomFrame),
SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame),

View File

@ -1943,7 +1943,7 @@ static nscoord
FindTileStart(nscoord aDirtyCoord, nscoord aTilePos, nscoord aTileDim)
{
NS_ASSERTION(aTileDim > 0, "Non-positive tile dimension");
double multiples = NS_floor(double(aDirtyCoord - aTilePos)/aTileDim);
double multiples = floor(double(aDirtyCoord - aTilePos)/aTileDim);
return NSToCoordRound(multiples*aTileDim + aTilePos);
}
@ -2050,7 +2050,7 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
// try to do anything in that case. We certainly need to avoid
// dividing by zero.
if (stopDelta >= 1e-6) {
double instanceCount = NS_ceil(-firstStop/stopDelta);
double instanceCount = ceil(-firstStop/stopDelta);
// Advance stops by instanceCount multiples of the period of the
// repeating gradient.
double offset = instanceCount*stopDelta;
@ -3607,15 +3607,15 @@ nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt,
PRBool canLiftUnderline = aDescentLimit >= 0.0;
const gfxFloat left = NS_floor(aPt.x + 0.5),
right = NS_floor(aPt.x + aLineSize.width + 0.5);
const gfxFloat left = floor(aPt.x + 0.5),
right = floor(aPt.x + aLineSize.width + 0.5);
gfxRect r(left, 0, right - left, 0);
gfxFloat lineHeight = NS_round(aLineSize.height);
lineHeight = NS_MAX(lineHeight, 1.0);
gfxFloat ascent = NS_round(aAscent);
gfxFloat descentLimit = NS_floor(aDescentLimit);
gfxFloat descentLimit = floor(aDescentLimit);
gfxFloat suggestedMaxRectHeight = NS_MAX(NS_MIN(ascent, descentLimit), 1.0);
r.height = lineHeight;
@ -3671,7 +3671,7 @@ nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt,
}
}
gfxFloat baseline = NS_floor(aPt.y + aAscent + 0.5);
gfxFloat baseline = floor(aPt.y + aAscent + 0.5);
gfxFloat offset = 0.0;
switch (aDecoration) {
case NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE:
@ -3692,7 +3692,7 @@ nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt,
offset = aOffset - lineHeight + r.Height();
break;
case NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH: {
gfxFloat extra = NS_floor(r.Height() / 2.0 + 0.5);
gfxFloat extra = floor(r.Height() / 2.0 + 0.5);
extra = NS_MAX(extra, lineHeight);
offset = aOffset - lineHeight + extra;
break;
@ -3700,7 +3700,7 @@ nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt,
default:
NS_ERROR("Invalid decoration value!");
}
r.y = baseline - NS_floor(offset + 0.5);
r.y = baseline - floor(offset + 0.5);
return r;
}

View File

@ -2766,7 +2766,7 @@ AdvanceToNextTab(gfxFloat aX, nsIFrame* aFrame,
// Advance aX to the next multiple of *aCachedTabWidth. We must advance
// by at least 1 appunit.
// XXX should we make this 1 CSS pixel?
return NS_ceil((aX + 1)/(*aCachedTabWidth))*(*aCachedTabWidth);
return ceil((aX + 1)/(*aCachedTabWidth))*(*aCachedTabWidth);
}
void
@ -4517,7 +4517,7 @@ ComputeSelectionUnderlineHeight(nsPresContext* aPresContext,
gfxFloat fontSize = NS_MIN(gfxFloat(defaultFontSize),
aFontMetrics.emHeight);
fontSize = NS_MAX(fontSize, 1.0);
return NS_ceil(fontSize / 20);
return ceil(fontSize / 20);
}
default:
NS_WARNING("Requested underline style is not valid");

View File

@ -76,8 +76,6 @@ CPPSRCS = nsMathMLChar.cpp \
nsMathMLmsubsupFrame.cpp \
nsMathMLmmultiscriptsFrame.cpp \
nsMathMLmtableFrame.cpp \
nsMathMLmunderFrame.cpp \
nsMathMLmoverFrame.cpp \
nsMathMLmunderoverFrame.cpp \
nsMathMLmpaddedFrame.cpp \
nsMathMLmspaceFrame.cpp \

View File

@ -56,8 +56,6 @@ nsIFrame* NS_NewMathMLmfracFrame(nsIPresShell* aPresShell, nsStyleContext* aCont
nsIFrame* NS_NewMathMLmsubFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* NS_NewMathMLmsupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* NS_NewMathMLmsubsupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* NS_NewMathMLmunderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* NS_NewMathMLmoverFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* NS_NewMathMLmunderoverFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* NS_NewMathMLmmultiscriptsFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
nsIFrame* NS_NewMathMLmstyleFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);

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