Merge mozilla-central and mozilla-inbound

This commit is contained in:
Marco Bonardo 2011-11-29 13:03:03 +01:00
commit c77ee84007
135 changed files with 1753 additions and 2157 deletions

1
aclocal.m4 vendored
View File

@ -12,6 +12,7 @@ builtin(include, build/autoconf/codeset.m4)dnl
builtin(include, build/autoconf/altoptions.m4)dnl
builtin(include, build/autoconf/mozprog.m4)dnl
builtin(include, build/autoconf/mozheader.m4)dnl
builtin(include, build/autoconf/mozcommonheader.m4)dnl
builtin(include, build/autoconf/acwinpaths.m4)dnl
builtin(include, build/autoconf/lto.m4)dnl
builtin(include, build/autoconf/gcc-pr49911.m4)dnl

View File

@ -340,6 +340,9 @@ var MigrationWizard = {
case "safari":
source = "sourceNameSafari";
break;
case "chrome":
source = "sourceNameChrome";
break;
}
// semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places

View File

@ -79,6 +79,7 @@
#endif
<radio id="opera" label="&importFromOpera.label;" accesskey="&importFromOpera.accesskey;"/>
#endif
<radio id="chrome" label="&importFromChrome.label;" accesskey="&importFromChrome.accesskey;"/>
<radio id="fromfile" label="&importFromHTMLFile.label;" accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
<radio id="nothing" label="&importFromNothing.label;" accesskey="&importFromNothing.accesskey;" hidden="true"/>
</radiogroup>

View File

@ -0,0 +1,2 @@
component {4cec1de4-1671-4fc3-a53e-6c539dc77a26} ChromeProfileMigrator.js
contract @mozilla.org/profile/migrator;1?app=browser&type=chrome {4cec1de4-1671-4fc3-a53e-6c539dc77a26}

View File

@ -0,0 +1,532 @@
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 sts=2 et
* ***** 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 the Browser Profile Migrator.
*
* 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):
* Makoto Kato <m_kato@ga2.so-net.ne.jp> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const LOCAL_FILE_CID = "@mozilla.org/file/local;1";
const FILE_INPUT_STREAM_CID = "@mozilla.org/network/file-input-stream;1";
const BUNDLE_MIGRATION = "chrome://browser/locale/migration/migration.properties";
const MIGRATE_ALL = 0x0000;
const MIGRATE_SETTINGS = 0x0001;
const MIGRATE_COOKIES = 0x0002;
const MIGRATE_HISTORY = 0x0004;
const MIGRATE_FORMDATA = 0x0008;
const MIGRATE_PASSWORDS = 0x0010;
const MIGRATE_BOOKMARKS = 0x0020;
const MIGRATE_OTHERDATA = 0x0040;
const S100NS_FROM1601TO1970 = 0x19DB1DED53E8000;
const S100NS_PER_MS = 10;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/PlacesUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyGetter(this, "bookmarksSubfolderTitle", function () {
// get "import from google chrome" string for folder
let strbundle =
Services.strings.createBundle(BUNDLE_MIGRATION);
let sourceNameChrome = strbundle.GetStringFromName("sourceNameChrome");
return strbundle.formatStringFromName("importedBookmarksFolder",
[sourceNameChrome],
1);
});
/*
* Convert Chrome time format to Date object
*
* @param aTime
* Chrome time
* @return converted Date object
* @note Google Chrome uses FILETIME / 10 as time.
* FILETIME is based on same structure of Windows.
*/
function chromeTimeToDate(aTime)
{
return new Date((aTime * S100NS_PER_MS - S100NS_FROM1601TO1970 ) / 10000);
}
/*
* Insert bookmark items into specific folder.
*
* @param aFolderId
* id of folder where items will be inserted
* @param aItems
* bookmark items to be inserted
*/
function insertBookmarkItems(aFolderId, aItems)
{
for (let i = 0; i < aItems.length; i++) {
let item = aItems[i];
try {
if (item.type == "url") {
PlacesUtils.bookmarks.insertBookmark(aFolderId,
NetUtil.newURI(item.url),
PlacesUtils.bookmarks.DEFAULT_INDEX,
item.name);
} else if (item.type == "folder") {
let newFolderId =
PlacesUtils.bookmarks.createFolder(aFolderId,
item.name,
PlacesUtils.bookmarks.DEFAULT_INDEX);
insertBookmarkItems(newFolderId, item.children);
}
} catch (e) {
Cu.reportError(e);
}
}
}
function ChromeProfileMigrator()
{
}
ChromeProfileMigrator.prototype = {
_paths: {
bookmarks : null,
cookies : null,
history : null,
prefs : null,
},
_homepageURL : null,
_replaceBookmarks : false,
/*
* Notify to observers to start migration
*
* @param aType
* notification type such as MIGRATE_BOOKMARKS
*/
_notifyStart : function Chrome_notifyStart(aType)
{
Services.obs.notifyObservers(null, "Migration:ItemBeforeMigrate", aType);
this._pendingCount++;
},
/*
* Notify to observers to finish migration for item
* If all items are finished, it sends migration end notification.
*
* @param aType
* notification type such as MIGRATE_BOOKMARKS
*/
_notifyCompleted : function Chrome_notifyIfCompleted(aType)
{
Services.obs.notifyObservers(null, "Migration:ItemAfterMigrate", aType);
if (--this._pendingCount == 0) {
// All items are migrated, so we have to send end notification.
Services.obs.notifyObservers(null, "Migration:Ended", null);
}
},
/*
* Migrating bookmark items
*/
_migrateBookmarks : function Chrome_migrateBookmarks()
{
this._notifyStart(MIGRATE_BOOKMARKS);
try {
PlacesUtils.bookmarks.runInBatchMode({
_self : this,
runBatched : function (aUserData) {
let migrator = this._self;
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
file.initWithPath(migrator._paths.bookmarks);
NetUtil.asyncFetch(file, function(aInputStream, aResultCode) {
if (!Components.isSuccessCode(aResultCode)) {
migrator._notifyCompleted(MIGRATE_BOOKMARKS);
return;
}
// Parse Chrome bookmark file that is JSON format
let bookmarkJSON = NetUtil.readInputStreamToString(aInputStream,
aInputStream.available(),
{ charset : "UTF-8" });
let roots = JSON.parse(bookmarkJSON).roots;
// Importing bookmark bar items
if (roots.bookmark_bar.children &&
roots.bookmark_bar.children.length > 0) {
// Toolbar
let parentId = PlacesUtils.toolbarFolderId;
if (!migrator._replaceBookmarks) {
parentId =
PlacesUtils.bookmarks.createFolder(parentId,
bookmarksSubfolderTitle,
PlacesUtils.bookmarks.DEFAULT_INDEX);
}
insertBookmarkItems(parentId, roots.bookmark_bar.children);
}
// Importing bookmark menu items
if (roots.other.children &&
roots.other.children.length > 0) {
// Bookmark menu
let parentId = PlacesUtils.bookmarksMenuFolderId;
if (!migrator._replaceBookmarks) {
parentId =
PlacesUtils.bookmarks.createFolder(parentId,
bookmarksSubfolderTitle,
PlacesUtils.bookmarks.DEFAULT_INDEX);
}
insertBookmarkItems(parentId, roots.other.children);
}
migrator._notifyCompleted(MIGRATE_BOOKMARKS);
});
}
}, null);
} catch (e) {
Cu.reportError(e);
this._notifyCompleted(MIGRATE_BOOKMARKS);
}
},
/*
* Migrating history
*/
_migrateHistory : function Chrome_migrateHistory()
{
this._notifyStart(MIGRATE_HISTORY);
try {
PlacesUtils.history.runInBatchMode({
_self : this,
runBatched : function (aUserData) {
// access sqlite3 database of Chrome's history
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
file.initWithPath(this._self._paths.history);
let dbConn = Services.storage.openUnsharedDatabase(file);
let stmt = dbConn.createAsyncStatement(
"SELECT url, title, last_visit_time, typed_count FROM urls WHERE hidden = 0");
stmt.executeAsync({
_asyncHistory : Cc["@mozilla.org/browser/history;1"]
.getService(Ci.mozIAsyncHistory),
_db : dbConn,
_self : this._self,
handleResult : function(aResults) {
let places = [];
for (let row = aResults.getNextRow(); row; row = aResults.getNextRow()) {
try {
// if having typed_count, we changes transition type to typed.
let transType = PlacesUtils.history.TRANSITION_LINK;
if (row.getResultByName("typed_count") > 0)
transType = PlacesUtils.history.TRANSITION_TYPED;
places.push({
uri: NetUtil.newURI(row.getResultByName("url")),
title: row.getResultByName("title"),
visits: [{
transitionType: transType,
visitDate: chromeTimeToDate(
row.getResultByName(
"last_visit_time")) * 1000,
}],
});
} catch (e) {
Cu.reportError(e);
}
}
try {
this._asyncHistory.updatePlaces(places);
} catch (e) {
Cu.reportError(e);
}
},
handleError : function(aError) {
Cu.reportError("Async statement execution returned with '" +
aError.result + "', '" + aError.message + "'");
},
handleCompletion : function(aReason) {
this._db.asyncClose();
this._self._notifyCompleted(MIGRATE_HISTORY);
}
});
stmt.finalize();
}
}, null);
} catch (e) {
Cu.reportError(e);
this._notifyCompleted(MIGRATE_HISTORY);
}
},
/*
* Migrating cookies
*/
_migrateCookies : function Chrome_migrateCookies()
{
this._notifyStart(MIGRATE_COOKIES);
try {
// Access sqlite3 database of Chrome's cookie
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
file.initWithPath(this._paths.cookies);
let dbConn = Services.storage.openUnsharedDatabase(file);
let stmt = dbConn.createAsyncStatement(
"SELECT host_key, path, name, value, secure, httponly, expires_utc FROM cookies");
stmt.executeAsync({
_db : dbConn,
_self : this,
handleResult : function(aResults) {
for (let row = aResults.getNextRow(); row; row = aResults.getNextRow()) {
let host_key = row.getResultByName("host_key");
if (host_key.match(/^\./)) {
// 1st character of host_key may be ".", so we have to remove it
host_key = host_key.substr(1);
}
try {
let expiresUtc =
chromeTimeToDate(row.getResultByName("expires_utc")) / 1000;
Services.cookies.add(host_key,
row.getResultByName("path"),
row.getResultByName("name"),
row.getResultByName("value"),
row.getResultByName("secure"),
row.getResultByName("httponly"),
false,
parseInt(expiresUtc));
} catch (e) {
Cu.reportError(e);
}
}
},
handleError : function(aError) {
Cu.reportError("Async statement execution returned with '" +
aError.result + "', '" + aError.message + "'");
},
handleCompletion : function(aReason) {
this._db.asyncClose();
this._self._notifyCompleted(MIGRATE_COOKIES);
},
});
stmt.finalize();
} catch (e) {
Cu.reportError(e);
this._notifyCompleted(MIGRATE_COOKIES);
}
},
/*
* nsIBrowserProfileMigrator interface implementation
*/
/*
* Let's migrate all items
*
* @param aItems
* list of data items to migrate. but this is unused.
* @param aStartup
* non-null if called during startup.
* @param aProfile
* this is unused due to single profile support only
*/
migrate : function Chrome_migrate(aItems, aStartup, aProfile)
{
if (aStartup) {
aStartup.doStartup();
this._replaceBookmarks = true;
}
Services.obs.notifyObservers(null, "Migration:Started", null);
// Reset panding count. If this count becomes 0, "Migration:Ended"
// notification is sent
this._pendingCount = 1;
if (aItems & MIGRATE_HISTORY)
this._migrateHistory();
if (aItems & MIGRATE_COOKIES)
this._migrateCookies();
if (aItems & MIGRATE_BOOKMARKS)
this._migrateBookmarks();
if (--this._pendingCount == 0) {
// When async imports are immeditelly completed unfortunately,
// this will be called.
// Usually, this notification is sent by _notifyCompleted()
Services.obs.notifyObservers(null, "Migration:Ended", null);
}
},
/*
* return supported migration types
*
* @param aProfile
* this is unused due to single profile support only
* @param aDoingStartup
* non-null if called during startup.
* @return supported migration types
*/
getMigrateData: function Chrome_getMigrateData(aProfile, aDoingStartup)
{
#ifdef XP_WIN
let chromepath = Services.dirsvc.get("LocalAppData", Ci.nsIFile).path +
"\\Google\\Chrome\\User Data\\Default\\";
#elifdef XP_MACOSX
let chromepath = Services.dirsvc.get("Home", Ci.nsIFile).path +
"/Library/Application Support/Google/Chrome/Default/";
#else
let chromepath = Services.dirsvc.get("Home", Ci.nsIFile).path +
"/.config/google-chrome/Default/";
#endif
let result = 0;
// bookmark and preference are JSON format
try {
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
file.initWithPath(chromepath + "Bookmarks");
if (file.exists()) {
this._paths.bookmarks = file.path
result += MIGRATE_BOOKMARKS;
}
} catch (e) {
Cu.reportError(e);
}
if (!this._paths.prefs)
this._paths.prefs = chromepath + "Preferences";
// history and cookies are SQLite database
try {
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
file.initWithPath(chromepath + "History");
if (file.exists()) {
this._paths.history = file.path
result += MIGRATE_HISTORY;
}
} catch (e) {
Cu.reportError(e);
}
try {
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
file.initWithPath(chromepath + "Cookies");
if (file.exists()) {
this._paths.cookies = file.path
result += MIGRATE_COOKIES;
}
} catch (e) {
Cu.reportError(e);
}
return result;
},
/*
* Whether we support migration of Chrome
*
* @return true if supported
*/
sourceExists: function Chrome_sourceExists()
{
let result = this.getMigrateData(null, false);
return result != 0;
},
// Although Chrome supports multi-profiles, there is no way
// to get profile lists.
sourceHasMultipleProfiles: false,
sourceProfiles: null,
/*
* Return home page URL
*
* @return home page URL
*/
sourceHomePageURL: function Chrome_sourceHomePageURL()
{
try {
if (this._homepageURL)
return this._homepageURL;
if (!this._paths.prefs)
this.getMigrateData(null, false);
// XXX reading and parsing JSON is synchronous.
let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
file.initWithPath(this._paths.prefs);
let fstream = Cc[FILE_INPUT_STREAM_CID].
createInstance(Ci.nsIFileInputStream);
fstream.init(file, -1, 0, 0);
this._homepageURL = JSON.parse(
NetUtil.readInputStreamToString(fstream, fstream.available(),
{ charset: "UTF-8" })).homepage;
return this._homepageURL;
} catch (e) {
Cu.reportError(e);
}
return "";
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIBrowserProfileMigrator
]),
classDescription: "Chrome Profile Migrator",
contractID: "@mozilla.org/profile/migrator;1?app=browser&type=chrome",
classID: Components.ID("{4cec1de4-1671-4fc3-a53e-6c539dc77a26}")
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([ChromeProfileMigrator]);

View File

@ -67,5 +67,13 @@ CPPSRCS += nsSafariProfileMigrator.cpp \
$(NULL)
endif
EXTRA_PP_COMPONENTS = \
ChromeProfileMigrator.js \
$(NULL)
EXTRA_COMPONENTS = \
BrowserProfileMigrators.manifest \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -163,6 +163,7 @@ NS_IMPL_ISUPPORTS1(nsProfileMigrator, nsIProfileMigrator)
#define INTERNAL_NAME_IEXPLORE "iexplore"
#define INTERNAL_NAME_MOZILLA_SUITE "apprunner"
#define INTERNAL_NAME_OPERA "opera"
#define INTERNAL_NAME_CHROME "chrome"
#endif
nsresult
@ -246,6 +247,10 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
aKey = "opera";
return NS_OK;
}
else if (internalName.LowerCaseEqualsLiteral(INTERNAL_NAME_CHROME)) {
aKey = "chrome";
return NS_OK;
}
#else
bool exists = false;
@ -262,6 +267,7 @@ nsProfileMigrator::GetDefaultBrowserMigratorKey(nsACString& aKey,
CHECK_MIGRATOR("safari");
#endif
CHECK_MIGRATOR("opera");
CHECK_MIGRATOR("chrome");
#undef CHECK_MIGRATOR
#endif

View File

@ -447,7 +447,6 @@ PlacesController.prototype = {
* "tagChild" node is a child of a tag
* "folder" node is a folder
* "query" node is a query
* "dynamiccontainer" node is a dynamic container
* "separator" node is a separator line
* "host" node is a host
*
@ -490,9 +489,6 @@ PlacesController.prototype = {
}
}
break;
case Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER:
nodeData["dynamiccontainer"] = true;
break;
case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER:
case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT:
nodeData["folder"] = true;

View File

@ -357,6 +357,8 @@
@BINPATH@/components/contentSecurityPolicy.js
@BINPATH@/components/contentAreaDropListener.manifest
@BINPATH@/components/contentAreaDropListener.js
@BINPATH@/components/BrowserProfileMigrators.manifest
@BINPATH@/components/ChromeProfileMigrator.js
#ifdef XP_MACOSX
@BINPATH@/components/libalerts_s.dylib
#endif

View File

@ -15,6 +15,8 @@
<!ENTITY importFromOpera.accesskey "O">
<!ENTITY importFromSafari.label "Safari">
<!ENTITY importFromSafari.accesskey "S">
<!ENTITY importFromChrome.label "Chrome">
<!ENTITY importFromChrome.accesskey "C">
<!ENTITY importFromHTMLFile.label "From an HTML File">
<!ENTITY importFromHTMLFile.accesskey "F">

View File

@ -5,6 +5,7 @@ sourceNameIE=Internet Explorer
sourceNameSeamonkey=Netscape 6/7/Mozilla
sourceNameOpera=Opera
sourceNameSafari=Safari
sourceNameChrome=Google Chrome
importedBookmarksFolder=From %S
importedSearchURLsFolder=Keyword Searches (From %S)
@ -21,34 +22,41 @@ importedOperaSearchUrls=Keyword Searches (From Opera)
1_opera=Preferences
1_seamonkey=Preferences
1_safari=Preferences
1_chrome=Preferences
2_ie=Cookies
2_opera=Cookies
2_seamonkey=Cookies
2_safari=Cookies
2_chrome=Cookies
4_ie=Browsing History
4_opera=Browsing History
4_seamonkey=Browsing History
4_safari=Browsing History
4_chrome=Browsing History
8_ie=Saved Form History
8_opera=Saved Form History
8_seamonkey=Saved Form History
8_safari=Saved Form History
8_chrome=Saved Form History
16_ie=Saved Passwords
16_opera=Saved Passwords
16_seamonkey=Saved Passwords
16_safari=Saved Passwords
16_chrome=Saved Passwords
32_ie=Favorites
32_opera=Bookmarks
32_seamonkey=Bookmarks
32_safari=Bookmarks
32_chrome=Bookmarks
64_ie=Other Data
64_opera=Other Data
64_seamonkey=Other Data
64_safari=Other Data
64_chrome=Other Data

View File

@ -0,0 +1,41 @@
dnl ***** BEGIN LICENSE BLOCK *****
dnl Version: MPL 1.1/GPL 2.0/LGPL 2.1
dnl
dnl The contents of this file are subject to the Mozilla Public License Version
dnl 1.1 (the "License"); you may not use this file except in compliance with
dnl the License. You may obtain a copy of the License at
dnl http://www.mozilla.org/MPL/
dnl
dnl Software distributed under the License is distributed on an "AS IS" basis,
dnl WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
dnl for the specific language governing rights and limitations under the
dnl License.
dnl
dnl The Original Code is mozilla.org code.
dnl
dnl The Initial Developer of the Original Code is the
dnl Mozilla Foundation <http://www.mozilla.org>
dnl
dnl Portions created by the Initial Developer are Copyright (C) 2009
dnl the Initial Developer. All Rights Reserved.
dnl
dnl
dnl Alternatively, the contents of this file may be used under the terms of
dnl either of the GNU General Public License Version 2 or later (the "GPL"),
dnl or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
dnl in which case the provisions of the GPL or the LGPL are applicable instead
dnl of those above. If you wish to allow use of your version of this file only
dnl under the terms of either the GPL or the LGPL, and not to allow others to
dnl use your version of this file under the terms of the MPL, indicate your
dnl decision by deleting the provisions above and replace them with the notice
dnl and other provisions required by the GPL or the LGPL. If you do not delete
dnl the provisions above, a recipient may use your version of this file under
dnl the terms of any one of the MPL, the GPL or the LGPL.
dnl
dnl ***** END LICENSE BLOCK *****
AC_DEFUN(MOZ_CHECK_COMMON_HEADERS,
MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h sys/bitypes.h \
memory.h unistd.h gnu/libc-version.h nl_types.h malloc.h \
X11/XKBlib.h io.h cpuid.h)
)

View File

@ -119,7 +119,6 @@ MOZ_CALLGRIND = @MOZ_CALLGRIND@
MOZ_VTUNE = @MOZ_VTUNE@
MOZ_ETW = @MOZ_ETW@
MOZ_TRACE_JSCALLS = @MOZ_TRACE_JSCALLS@
MOZ_TRACEVIS = @MOZ_TRACEVIS@
DEHYDRA_PATH = @DEHYDRA_PATH@
NS_TRACE_MALLOC = @NS_TRACE_MALLOC@

View File

@ -3409,12 +3409,7 @@ freebsd*|openbsd*)
CPPFLAGS="${CPPFLAGS} ${X_CFLAGS}"
;;
esac
MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h)
MOZ_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h)
MOZ_CHECK_HEADERS(gnu/libc-version.h nl_types.h)
MOZ_CHECK_HEADERS(malloc.h)
MOZ_CHECK_HEADERS(X11/XKBlib.h)
MOZ_CHECK_HEADERS(io.h)
MOZ_CHECK_COMMON_HEADERS
dnl These are all the places some variant of statfs can be hiding.
MOZ_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h)
@ -7325,17 +7320,6 @@ if test -n "$MOZ_TRACE_JSCALLS"; then
AC_DEFINE(MOZ_TRACE_JSCALLS)
fi
dnl ========================================================
dnl = Use TraceVis
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(tracevis,
[ --enable-tracevis Enable TraceVis tracing tool (default=no)],
MOZ_TRACEVIS=1,
MOZ_TRACEVIS= )
if test -n "$MOZ_TRACEVIS"; then
AC_DEFINE(MOZ_TRACEVIS)
fi
dnl ========================================================
dnl = Use incremental GC
dnl ========================================================

View File

@ -64,7 +64,7 @@
#include "nsSMILAnimationController.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocumentEncoder.h"
#include "nsIAnimationFrameListener.h"
#include "nsIFrameRequestCallback.h"
#include "nsEventStates.h"
#include "nsIStructuredCloneContainer.h"
#include "nsIBFCacheEntry.h"
@ -1518,18 +1518,14 @@ public:
*/
virtual Element* LookupImageElement(const nsAString& aElementId) = 0;
void ScheduleBeforePaintEvent(nsIAnimationFrameListener* aListener);
void BeforePaintEventFiring()
{
mHavePendingPaint = false;
}
void ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback);
typedef nsTArray< nsCOMPtr<nsIAnimationFrameListener> > AnimationListenerList;
typedef nsTArray< nsCOMPtr<nsIFrameRequestCallback> > FrameRequestCallbackList;
/**
* Put this documents animation frame listeners into the provided
* Put this document's frame request callbacks into the provided
* list, and forget about them.
*/
void TakeAnimationFrameListeners(AnimationListenerList& aListeners);
void TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks);
// This returns true when the document tree is being teared down.
bool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; }
@ -1746,9 +1742,6 @@ protected:
// True if document has ever had script handling object.
bool mHasHadScriptHandlingObject;
// True if we're waiting for a before-paint event.
bool mHavePendingPaint;
// True if we're an SVG document being used as an image.
bool mIsBeingUsedAsImage;
@ -1812,7 +1805,7 @@ protected:
nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
AnimationListenerList mAnimationFrameListeners;
FrameRequestCallbackList mFrameRequestCallbacks;
// This object allows us to evict ourself from the back/forward cache. The
// pointer is non-null iff we're currently in the bfcache.

View File

@ -1881,9 +1881,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPreloadingImages)
for (PRUint32 i = 0; i < tmp->mAnimationFrameListeners.Length(); ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAnimationFrameListeners[i]");
cb.NoteXPCOMChild(tmp->mAnimationFrameListeners[i]);
for (PRUint32 i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameRequestCallbacks[i]");
cb.NoteXPCOMChild(tmp->mFrameRequestCallbacks[i]);
}
// Traverse animation components
@ -1951,7 +1951,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mSubDocuments = nsnull;
}
tmp->mAnimationFrameListeners.Clear();
tmp->mFrameRequestCallbacks.Clear();
tmp->mRadioGroups.Clear();
@ -3214,19 +3214,16 @@ nsDocument::MaybeRescheduleAnimationFrameNotifications()
}
nsRefreshDriver* rd = mPresShell->GetPresContext()->RefreshDriver();
if (mHavePendingPaint) {
rd->ScheduleBeforePaintEvent(this);
}
if (!mAnimationFrameListeners.IsEmpty()) {
rd->ScheduleAnimationFrameListeners(this);
if (!mFrameRequestCallbacks.IsEmpty()) {
rd->ScheduleFrameRequestCallbacks(this);
}
}
void
nsIDocument::TakeAnimationFrameListeners(AnimationListenerList& aListeners)
nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks)
{
aListeners.AppendElements(mAnimationFrameListeners);
mAnimationFrameListeners.Clear();
aCallbacks.AppendElements(mFrameRequestCallbacks);
mFrameRequestCallbacks.Clear();
}
void
@ -3243,12 +3240,9 @@ nsDocument::DeleteShell()
void
nsDocument::RevokeAnimationFrameNotifications()
{
if (mHavePendingPaint) {
mPresShell->GetPresContext()->RefreshDriver()->RevokeBeforePaintEvent(this);
}
if (!mAnimationFrameListeners.IsEmpty()) {
if (!mFrameRequestCallbacks.IsEmpty()) {
mPresShell->GetPresContext()->RefreshDriver()->
RevokeAnimationFrameListeners(this);
RevokeFrameRequestCallbacks(this);
}
}
@ -8074,30 +8068,14 @@ nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
}
void
nsIDocument::ScheduleBeforePaintEvent(nsIAnimationFrameListener* aListener)
nsIDocument::ScheduleFrameRequestCallback(nsIFrameRequestCallback* aCallback)
{
if (aListener) {
bool alreadyRegistered = !mAnimationFrameListeners.IsEmpty();
if (mAnimationFrameListeners.AppendElement(aListener) &&
!alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
mPresShell->GetPresContext()->RefreshDriver()->
ScheduleAnimationFrameListeners(this);
}
return;
bool alreadyRegistered = !mFrameRequestCallbacks.IsEmpty();
if (mFrameRequestCallbacks.AppendElement(aCallback) &&
!alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
mPresShell->GetPresContext()->RefreshDriver()->
ScheduleFrameRequestCallbacks(this);
}
if (!mHavePendingPaint) {
// We don't want to use GetShell() here, because we want to schedule the
// paint even if we're frozen. Either we'll get unfrozen and then the
// event will fire, or we'll quietly go away at some point.
mHavePendingPaint =
!mPresShell ||
!IsEventHandlingEnabled() ||
mPresShell->GetPresContext()->RefreshDriver()->
ScheduleBeforePaintEvent(this);
}
}
nsresult

View File

@ -311,7 +311,7 @@ nsInProcessTabChildGlobal::InitTabChildGlobal()
JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetVersion(cx, JSVERSION_LATEST);
JS_SetErrorReporter(cx, ContentScriptErrorReporter);

View File

@ -341,6 +341,7 @@ function MediaTestManager() {
this.startTest = startTest;
this.tokens = [];
this.isShutdown = false;
this.numTestsRunning = 0;
// Always wait for explicit finish.
SimpleTest.waitForExplicitFinish();
this.nextTest();
@ -350,6 +351,8 @@ function MediaTestManager() {
// Don't call more than once per token.
this.started = function(token) {
this.tokens.push(token);
this.numTestsRunning++;
is(this.numTestsRunning, this.tokens.length, "[started] Length of array should match number of running tests");
}
// Registers that the test corresponding to 'token' has finished. Call when
@ -362,11 +365,13 @@ function MediaTestManager() {
// Remove the element from the list of running tests.
this.tokens.splice(i, 1);
}
this.numTestsRunning--;
is(this.numTestsRunning, this.tokens.length, "[finished] Length of array should match number of running tests");
if (this.tokens.length < PARALLEL_TESTS) {
this.nextTest();
}
}
// Starts the next batch of tests, or finishes if they're all done.
// Don't call this directly, call finished(token) when you're done.
this.nextTest = function() {

View File

@ -35,9 +35,9 @@ function startTest(test, token) {
is(v.readyState, v.HAVE_CURRENT_DATA, test.name + " checking readyState");
ok(v.readyState != v.NETWORK_LOADED, test.name + " shouldn't report NETWORK_LOADED");
ok(v.ended, test.name + " checking playback has ended");
if (v.ended && v.seenSuspend) {
if (v.parentNode)
v.parentNode.removeChild(v);
if (v.ended && v.seenSuspend && !v.finished) {
v.finished = true;
v.parentNode.removeChild(v);
manager.finished(v.token);
}
}}(test, v);
@ -48,9 +48,9 @@ function startTest(test, token) {
v.seenSuspend = true;
ok(true, test.name + " got suspend");
if (v.ended && v.seenSuspend) {
if (v.parentNode)
v.parentNode.removeChild(v);
if (v.ended && !v.finished) {
v.finished = true;
v.parentNode.removeChild(v);
manager.finished(v.token);
}
}}(test, v);

View File

@ -46,6 +46,13 @@ function ended(e) {
500);
}
var eventsToLog = ["play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
"loadeddata", "playing", "progress", "timeupdate", "ended", "suspend", "error", "stalled", "emptied", "abort",
"waiting", "pause"];
function logEvent(event) {
ok(true, event.target.currentSrc + " got " + event.type);
}
function startTest(test, token) {
var type = /^video/.test(test.type) ? "video" : "audio";
var v = document.createElement(type);
@ -59,6 +66,9 @@ function startTest(test, token) {
v.autoplay = true;
v.addEventListener("ended", ended, false);
v.addEventListener("timeupdate", timeupdate, false);
for (var i = 0; i < eventsToLog.length; ++i) {
v.addEventListener(eventsToLog[i], logEvent, false);
}
document.body.appendChild(v);
}

View File

@ -3957,16 +3957,16 @@ nsGlobalWindow::GetMozPaintCount(PRUint64* aResult)
}
NS_IMETHODIMP
nsGlobalWindow::MozRequestAnimationFrame(nsIAnimationFrameListener* aListener)
nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback)
{
FORWARD_TO_INNER(MozRequestAnimationFrame, (aListener),
FORWARD_TO_INNER(MozRequestAnimationFrame, (aCallback),
NS_ERROR_NOT_INITIALIZED);
if (!mDoc) {
return NS_OK;
}
mDoc->ScheduleBeforePaintEvent(aListener);
mDoc->ScheduleFrameRequestCallback(aCallback);
return NS_OK;
}

View File

@ -194,7 +194,7 @@ nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
if (sGCOnMemoryPressure) {
nsJSContext::GarbageCollectNow();
nsJSContext::GarbageCollectNow(true);
nsJSContext::CycleCollectNow();
}
return NS_OK;
@ -929,8 +929,6 @@ static const char js_zeal_compartment_str[] = JS_OPTIONS_DOT_STR "gczeal.compa
#endif
static const char js_methodjit_content_str[] = JS_OPTIONS_DOT_STR "methodjit.content";
static const char js_methodjit_chrome_str[] = JS_OPTIONS_DOT_STR "methodjit.chrome";
static const char js_profiling_content_str[] = JS_OPTIONS_DOT_STR "jitprofiling.content";
static const char js_profiling_chrome_str[] = JS_OPTIONS_DOT_STR "jitprofiling.chrome";
static const char js_methodjit_always_str[] = JS_OPTIONS_DOT_STR "methodjit_always";
static const char js_typeinfer_str[] = JS_OPTIONS_DOT_STR "typeinference";
static const char js_pccounts_content_str[] = JS_OPTIONS_DOT_STR "pccounts.content";
@ -961,9 +959,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
bool useMethodJIT = Preferences::GetBool(chromeWindow ?
js_methodjit_chrome_str :
js_methodjit_content_str);
bool useProfiling = Preferences::GetBool(chromeWindow ?
js_profiling_chrome_str :
js_profiling_content_str);
bool usePCCounts = Preferences::GetBool(chromeWindow ?
js_pccounts_chrome_str :
js_pccounts_content_str);
@ -976,7 +971,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
xr->GetInSafeMode(&safeMode);
if (safeMode) {
useMethodJIT = false;
useProfiling = false;
usePCCounts = false;
useTypeInference = false;
useMethodJITAlways = true;
@ -989,11 +983,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
else
newDefaultJSOptions &= ~JSOPTION_METHODJIT;
if (useProfiling)
newDefaultJSOptions |= JSOPTION_PROFILING;
else
newDefaultJSOptions &= ~JSOPTION_PROFILING;
if (usePCCounts)
newDefaultJSOptions |= JSOPTION_PCCOUNT;
else
@ -2950,14 +2939,6 @@ static JSFunctionSpec JProfFunctions[] = {
#endif /* defined(MOZ_JPROF) */
#ifdef MOZ_TRACEVIS
static JSFunctionSpec EthogramFunctions[] = {
{"initEthogram", js_InitEthogram, 0, 0},
{"shutdownEthogram", js_ShutdownEthogram, 0, 0},
{nsnull, nsnull, 0, 0}
};
#endif
nsresult
nsJSContext::InitClasses(JSObject* aGlobalObj)
{
@ -2981,11 +2962,6 @@ nsJSContext::InitClasses(JSObject* aGlobalObj)
::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
#endif
#ifdef MOZ_TRACEVIS
// Attempt to initialize Ethogram functions
::JS_DefineFunctions(mContext, aGlobalObj, EthogramFunctions);
#endif
JSOptionChangedCallback(js_options_dot_str, this);
return rv;
@ -3187,7 +3163,7 @@ nsJSContext::ScriptExecuted()
//static
void
nsJSContext::GarbageCollectNow()
nsJSContext::GarbageCollectNow(bool shrinkingGC)
{
NS_TIME_FUNCTION_MIN(1.0);
@ -3203,7 +3179,7 @@ nsJSContext::GarbageCollectNow()
sLoadingInProgress = false;
if (nsContentUtils::XPConnect()) {
nsContentUtils::XPConnect()->GarbageCollect();
nsContentUtils::XPConnect()->GarbageCollect(shrinkingGC);
}
}

View File

@ -182,7 +182,7 @@ public:
static void LoadStart();
static void LoadEnd();
static void GarbageCollectNow();
static void GarbageCollectNow(bool shrinkingGC = false);
static void CycleCollectNow(nsICycleCollectorListener *aListener = nsnull);
static void PokeGC();

View File

@ -55,7 +55,7 @@ SDK_XPIDLSRCS = \
$(NULL)
XPIDLSRCS = \
nsIAnimationFrameListener.idl \
nsIFrameRequestCallback.idl \
nsIBrowserDOMWindow.idl \
nsIContentPermissionPrompt.idl \
nsIContentPrefService.idl \

View File

@ -41,7 +41,7 @@
#include "domstubs.idl"
interface nsIAnimationFrameListener;
interface nsIFrameRequestCallback;
interface nsIControllers;
interface nsIDOMBlob;
interface nsIDOMLocation;
@ -418,7 +418,7 @@ interface nsIDOMWindow : nsISupports
* @see <http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html>
*/
void
mozRequestAnimationFrame([optional] in nsIAnimationFrameListener aListener);
mozRequestAnimationFrame(in nsIFrameRequestCallback aCallback);
/**
* The current animation start time in milliseconds since the epoch.

View File

@ -36,18 +36,16 @@
* ***** END LICENSE BLOCK ***** */
/**
* Interface that represents a listener to be passed to
* mozRequestAnimationFrame
* Interface that represents a callback to be passed to requestAnimationFrame
*/
#include "domstubs.idl"
[scriptable, function, uuid(ba240e38-c15a-4fb2-802a-8a48f09331bd)]
interface nsIAnimationFrameListener : nsISupports
[scriptable, function, uuid(e8d887f0-2ed7-406f-9f1d-edeb2c54c0a2)]
interface nsIFrameRequestCallback : nsISupports
{
/**
* The timestamp is the same as it would be for the a corresponding
* MozBeforePaint event.
* The timestamp is the time to be used for the animation sample.
*/
void onBeforePaint(in DOMTimeStamp timeStamp);
void sample(in DOMTimeStamp timeStamp);
};

View File

@ -915,7 +915,7 @@ TabChild::InitTabChildGlobal()
JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
JS_SetVersion(cx, JSVERSION_LATEST);
JS_SetErrorReporter(cx, ContentScriptErrorReporter);

View File

@ -54,9 +54,9 @@ errUnquotedAttributeLt=“<” in an unquoted attribute value. Probable cause: M
errUnquotedAttributeGrave=“`” in an unquoted attribute value. Probable cause: Using the wrong character as a quote.
errUnquotedAttributeQuote=Quote in an unquoted attribute value. Probable causes: Attributes running together or a URL query string in an unquoted attribute value.
errUnquotedAttributeEquals=“=” in an unquoted attribute value. Probable causes: Attributes running together or a URL query string in an unquoted attribute value.
errSlashNotFollowedByGt=A slash was not immediate followed by “>”.
errSlashNotFollowedByGt=A slash was not immediately followed by “>”.
errNoSpaceBetweenAttributes=No space between attributes.
errUnquotedAttributeStartLt=“<” at the start of an unquoted attribute value. Probable cause: Missing “>” immediately before
errUnquotedAttributeStartLt=“<” at the start of an unquoted attribute value. Probable cause: Missing “>” immediately before.
errUnquotedAttributeStartGrave=“`” at the start of an unquoted attribute value. Probable cause: Using the wrong character as a quote.
errUnquotedAttributeStartEquals=“=” at the start of an unquoted attribute value. Probable cause: Stray duplicate equals sign.
errAttributeValueMissing=Attribute value missing.

View File

@ -3708,6 +3708,7 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
{
PLUGIN_LOG_DEBUG_METHOD;
AssertPluginThread();
*aResult = NPERR_NO_ERROR;
#if defined(OS_WIN)
SetProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty, (HANDLE)1);

View File

@ -80,6 +80,22 @@ DeferNPObjectReleaseRunnable::Run()
namespace mozilla {
namespace plugins {
NPRemoteWindow::NPRemoteWindow() :
window(0), x(0), y(0), width(0), height(0), type(NPWindowTypeDrawable)
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
, visualID(0)
, colormap(0)
#endif /* XP_UNIX */
#if defined(XP_WIN)
,surfaceHandle(0)
#endif
{
clipRect.top = 0;
clipRect.left = 0;
clipRect.bottom = 0;
clipRect.right = 0;
}
RPCChannel::RacyRPCPolicy
MediateRace(const RPCChannel::Message& parent,
const RPCChannel::Message& child)

View File

@ -110,6 +110,7 @@ typedef nsCString Buffer;
struct NPRemoteWindow
{
NPRemoteWindow();
uint64_t window;
int32_t x;
int32_t y;

View File

@ -151,7 +151,6 @@ enum {
PREF_werror,
PREF_relimit,
PREF_methodjit,
PREF_jitprofiling,
PREF_methodjit_always,
#ifdef JS_GC_ZEAL
@ -168,7 +167,6 @@ const char* gPrefsToWatch[] = {
JS_OPTIONS_DOT_STR "werror",
JS_OPTIONS_DOT_STR "relimit",
JS_OPTIONS_DOT_STR "methodjit.content",
JS_OPTIONS_DOT_STR "jitprofiling.content",
JS_OPTIONS_DOT_STR "methodjit_always"
#ifdef JS_GC_ZEAL
@ -202,9 +200,6 @@ PrefCallback(const char* aPrefName, void* aClosure)
if (Preferences::GetBool(gPrefsToWatch[PREF_methodjit])) {
newOptions |= JSOPTION_METHODJIT;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_jitprofiling])) {
newOptions |= JSOPTION_PROFILING;
}
if (Preferences::GetBool(gPrefsToWatch[PREF_methodjit_always])) {
newOptions |= JSOPTION_METHODJIT_ALWAYS;
}

View File

@ -120,6 +120,7 @@
#include "mozilla/FunctionTimer.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Element.h"
#include "nsContentUtils.h"
#define NS_ERROR_EDITOR_NO_SELECTION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,1)
#define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
@ -3149,7 +3150,8 @@ nsEditor::GetPriorNode(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing)
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot)
{
// just another version of GetPriorNode that takes a {parent, offset}
// instead of a node
@ -3164,13 +3166,15 @@ nsEditor::GetPriorNode(nsIDOMNode *aParentNode,
// if we aren't allowed to cross blocks, don't look before this block
return NS_OK;
}
return GetPriorNode(aParentNode, aEditableNode, aResultNode, bNoBlockCrossing);
return GetPriorNode(aParentNode, aEditableNode, aResultNode,
bNoBlockCrossing, aActiveEditorRoot);
}
// else look before the child at 'aOffset'
nsCOMPtr<nsIDOMNode> child = GetChildAt(aParentNode, aOffset);
if (child)
return GetPriorNode(child, aEditableNode, aResultNode, bNoBlockCrossing);
return GetPriorNode(child, aEditableNode, aResultNode, bNoBlockCrossing,
aActiveEditorRoot);
// unless there isn't one, in which case we are at the end of the node
// and want the deep-right child.
@ -3179,17 +3183,19 @@ nsEditor::GetPriorNode(nsIDOMNode *aParentNode,
return NS_OK;
// restart the search from the non-editable node we just found
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
return GetPriorNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
nsCOMPtr<nsIDOMNode> notEditableNode = *aResultNode;
return GetPriorNode(notEditableNode, aEditableNode, aResultNode,
bNoBlockCrossing, aActiveEditorRoot);
}
nsresult
nsEditor::GetNextNode(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing)
PRInt32 aOffset,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot)
{
// just another version of GetNextNode that takes a {parent, offset}
// instead of a node
@ -3231,7 +3237,8 @@ nsEditor::GetNextNode(nsIDOMNode *aParentNode,
// restart the search from the non-editable node we just found
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(*aResultNode);
return GetNextNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
return GetNextNode(notEditableNode, aEditableNode, aResultNode,
bNoBlockCrossing, aActiveEditorRoot);
}
// unless there isn't one, in which case we are at the end of the node
@ -3241,7 +3248,8 @@ nsEditor::GetNextNode(nsIDOMNode *aParentNode,
// don't cross out of parent block
return NS_OK;
}
return GetNextNode(aParentNode, aEditableNode, aResultNode, bNoBlockCrossing);
return GetNextNode(aParentNode, aEditableNode, aResultNode, bNoBlockCrossing,
aActiveEditorRoot);
}
@ -3249,227 +3257,139 @@ nsresult
nsEditor::GetPriorNode(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing)
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot)
{
nsresult result;
if (!aCurrentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
*aResultNode = nsnull; // init out-param
if (IsRootNode(aCurrentNode))
{
// Don't allow traversal above the root node! This helps
// prevent us from accidentally editing browser content
// when the editor is in a text widget.
nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
if (!IsDescendantOfBody(currentNode) ||
(aActiveEditorRoot &&
!nsContentUtils::ContentIsDescendantOf(currentNode,
aActiveEditorRoot))) {
*aResultNode = nsnull;
return NS_OK;
}
nsCOMPtr<nsIDOMNode> candidate;
result = GetPriorNodeImpl(aCurrentNode, aEditableNode, address_of(candidate), bNoBlockCrossing);
NS_ENSURE_SUCCESS(result, result);
if (!candidate)
{
// we could not find a prior node. return null.
return NS_OK;
}
else if (!aEditableNode) *aResultNode = candidate;
else if (IsEditable(candidate)) *aResultNode = candidate;
else
{ // restart the search from the non-editable node we just found
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(candidate);
return GetPriorNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
}
return result;
*aResultNode =
do_QueryInterface(FindNode(currentNode, false, aEditableNode,
bNoBlockCrossing, aActiveEditorRoot));
return NS_OK;
}
nsresult
nsEditor::GetPriorNodeImpl(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing)
nsIContent*
nsEditor::FindNextLeafNode(nsINode *aCurrentNode,
bool aGoForward,
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot)
{
// called only by GetPriorNode so we don't need to check params.
NS_PRECONDITION(IsDescendantOfBody(aCurrentNode) && !IsRootNode(aCurrentNode) &&
(!aActiveEditorRoot ||
nsContentUtils::ContentIsDescendantOf(aCurrentNode,
aActiveEditorRoot)),
"Bogus arguments");
// if aCurrentNode has a left sibling, return that sibling's rightmost child (or itself if it has no children)
nsCOMPtr<nsIDOMNode> prevSibling;
nsresult result = aCurrentNode->GetPreviousSibling(getter_AddRefs(prevSibling));
if ((NS_SUCCEEDED(result)) && prevSibling)
{
if (bNoBlockCrossing && IsBlockNode(prevSibling))
{
// don't look inside prevsib, since it is a block
*aResultNode = prevSibling;
return NS_OK;
}
*aResultNode = GetRightmostChild(prevSibling, bNoBlockCrossing);
if (!*aResultNode)
{
*aResultNode = prevSibling;
return NS_OK;
}
if (!IsDescendantOfBody(*aResultNode))
{
*aResultNode = nsnull;
return NS_OK;
}
}
else
{
// otherwise, walk up the parent tree until there is a child that comes before
// the ancestor of aCurrentNode. Then return that node's rightmost child
nsCOMPtr<nsIDOMNode> parent = do_QueryInterface(aCurrentNode);
nsCOMPtr<nsIDOMNode> node, notEditableNode;
do {
node = parent;
result = node->GetParentNode(getter_AddRefs(parent));
if ((NS_SUCCEEDED(result)) && parent)
{
if (!IsDescendantOfBody(parent))
{
*aResultNode = nsnull;
return NS_OK;
}
if ((bNoBlockCrossing && IsBlockNode(parent)) || IsRootNode(parent))
{
// we are at front of block or root, do not step out
*aResultNode = nsnull;
return NS_OK;
}
result = parent->GetPreviousSibling(getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && node)
{
if (bNoBlockCrossing && IsBlockNode(node))
{
// prev sibling is a block, do not step into it
*aResultNode = node;
return NS_OK;
}
*aResultNode = GetRightmostChild(node, bNoBlockCrossing);
if (!*aResultNode) *aResultNode = node;
return NS_OK;
}
nsINode* cur = aCurrentNode;
for (;;) {
// if aCurrentNode has a sibling in the right direction, return
// that sibling's closest child (or itself if it has no children)
nsIContent* sibling =
aGoForward ? cur->GetNextSibling() : cur->GetPreviousSibling();
if (sibling) {
if (bNoBlockCrossing && IsBlockNode(sibling)) {
// don't look inside prevsib, since it is a block
return sibling;
}
} while ((NS_SUCCEEDED(result)) && parent && !*aResultNode);
nsIContent *leaf =
aGoForward ? GetLeftmostChild(sibling, bNoBlockCrossing) :
GetRightmostChild(sibling, bNoBlockCrossing);
if (!leaf) {
return sibling;
}
return leaf;
}
nsINode *parent = cur->GetNodeParent();
if (!parent) {
return nsnull;
}
NS_ASSERTION(IsDescendantOfBody(parent),
"We started with a proper descendant of root, and should stop "
"if we ever hit the root, so we better have a descendant of "
"root now!");
if (IsRootNode(parent) ||
(bNoBlockCrossing && IsBlockNode(parent)) ||
parent == aActiveEditorRoot) {
return nsnull;
}
cur = parent;
}
return result;
NS_NOTREACHED("What part of for(;;) do you not understand?");
return nsnull;
}
nsresult
nsEditor::GetNextNode(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing)
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot)
{
if (!aCurrentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
*aResultNode = nsnull; // init out-param
if (IsRootNode(aCurrentNode))
nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
if (!IsDescendantOfBody(currentNode) ||
(aActiveEditorRoot &&
!nsContentUtils::ContentIsDescendantOf(currentNode,
aActiveEditorRoot))) {
*aResultNode = nsnull;
return NS_OK;
}
*aResultNode =
do_QueryInterface(FindNode(currentNode, true, aEditableNode,
bNoBlockCrossing, aActiveEditorRoot));
return NS_OK;
}
nsIContent*
nsEditor::FindNode(nsINode *aCurrentNode,
bool aGoForward,
bool aEditableNode,
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot)
{
if (IsRootNode(aCurrentNode) || aCurrentNode == aActiveEditorRoot)
{
// Don't allow traversal above the root node! This helps
// prevent us from accidentally editing browser content
// when the editor is in a text widget.
return NS_OK;
return nsnull;
}
nsCOMPtr<nsIDOMNode> candidate;
nsresult result = GetNextNodeImpl(aCurrentNode, aEditableNode,
address_of(candidate), bNoBlockCrossing);
NS_ENSURE_SUCCESS(result, result);
nsIContent* candidate =
FindNextLeafNode(aCurrentNode, aGoForward, bNoBlockCrossing,
aActiveEditorRoot);
if (!candidate)
{
// we could not find a next node. return null.
*aResultNode = nsnull;
return NS_OK;
if (!candidate) {
return nsnull;
}
else if (!aEditableNode) *aResultNode = candidate;
else if (IsEditable(candidate)) *aResultNode = candidate;
else
{ // restart the search from the non-editable node we just found
nsCOMPtr<nsIDOMNode> notEditableNode = do_QueryInterface(candidate);
return GetNextNode(notEditableNode, aEditableNode, aResultNode, bNoBlockCrossing);
if (!aEditableNode || IsEditable(candidate)) {
return candidate;
}
return result;
return FindNode(candidate, aGoForward, aEditableNode, bNoBlockCrossing,
aActiveEditorRoot);
}
nsresult
nsEditor::GetNextNodeImpl(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing)
{
// called only by GetNextNode so we don't need to check params.
// if aCurrentNode has a right sibling, return that sibling's leftmost child (or itself if it has no children)
nsCOMPtr<nsIDOMNode> nextSibling;
nsresult result = aCurrentNode->GetNextSibling(getter_AddRefs(nextSibling));
if ((NS_SUCCEEDED(result)) && nextSibling)
{
if (bNoBlockCrossing && IsBlockNode(nextSibling))
{
// next sibling is a block, do not step into it
*aResultNode = nextSibling;
return NS_OK;
}
*aResultNode = GetLeftmostChild(nextSibling, bNoBlockCrossing);
if (!*aResultNode)
{
*aResultNode = nextSibling;
return NS_OK;
}
if (!IsDescendantOfBody(*aResultNode))
{
*aResultNode = nsnull;
return NS_OK;
}
}
else
{
// otherwise, walk up the parent tree until there is a child that comes after
// the ancestor of aCurrentNode. Then return that node's leftmost child
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
nsCOMPtr<nsIDOMNode> node, notEditableNode;
do {
node = parent;
result = node->GetParentNode(getter_AddRefs(parent));
if ((NS_SUCCEEDED(result)) && parent)
{
if (!IsDescendantOfBody(parent))
{
*aResultNode = nsnull;
return NS_OK;
}
if ((bNoBlockCrossing && IsBlockNode(parent)) || IsRootNode(parent))
{
// we are at end of block or root, do not step out
*aResultNode = nsnull;
return NS_OK;
}
result = parent->GetNextSibling(getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && node)
{
if (bNoBlockCrossing && IsBlockNode(node))
{
// next sibling is a block, do not step into it
*aResultNode = node;
return NS_OK;
}
*aResultNode = GetLeftmostChild(node, bNoBlockCrossing);
if (!*aResultNode) *aResultNode = node;
return NS_OK;
}
}
} while ((NS_SUCCEEDED(result)) && parent);
}
return result;
}
already_AddRefed<nsIDOMNode>
nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode,
bool bNoBlockCrossing)
@ -3494,6 +3414,54 @@ nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode,
return resultNode.forget();
}
nsIContent*
nsEditor::GetRightmostChild(nsINode *aCurrentNode,
bool bNoBlockCrossing)
{
NS_ENSURE_TRUE(aCurrentNode, nsnull);
nsIContent *cur = aCurrentNode->GetLastChild();
if (!cur) {
return nsnull;
}
for (;;) {
if (bNoBlockCrossing && IsBlockNode(cur)) {
return cur;
}
nsIContent* next = cur->GetLastChild();
if (!next) {
return cur;
}
cur = next;
}
NS_NOTREACHED("What part of for(;;) do you not understand?");
return nsnull;
}
nsIContent*
nsEditor::GetLeftmostChild(nsINode *aCurrentNode,
bool bNoBlockCrossing)
{
NS_ENSURE_TRUE(aCurrentNode, nsnull);
nsIContent *cur = aCurrentNode->GetFirstChild();
if (!cur) {
return nsnull;
}
for (;;) {
if (bNoBlockCrossing && IsBlockNode(cur)) {
return cur;
}
nsIContent *next = cur->GetFirstChild();
if (!next) {
return cur;
}
cur = next;
}
NS_NOTREACHED("What part of for(;;) do you not understand?");
return nsnull;
}
already_AddRefed<nsIDOMNode>
nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode,
bool bNoBlockCrossing)
@ -3529,6 +3497,16 @@ nsEditor::IsBlockNode(nsIDOMNode *aNode)
}
bool
nsEditor::IsBlockNode(nsINode *aNode)
{
// stub to be overridden in nsHTMLEditor.
// screwing around with the class hierarchy here in order
// to not duplicate the code in GetNextNode/GetPrevNode
// across both nsEditor/nsHTMLEditor.
return false;
}
bool
nsEditor::CanContainTag(nsIDOMNode* aParent, const nsAString &aChildTag)
{
nsCOMPtr<nsIDOMElement> parentElement = do_QueryInterface(aParent);
@ -3563,38 +3541,41 @@ nsEditor::TagCanContainTag(const nsAString &aParentTag, const nsAString &aChildT
return true;
}
bool
nsEditor::IsRootNode(nsIDOMNode *inNode)
{
NS_ENSURE_TRUE(inNode, false);
return inNode == GetRoot();
}
bool
nsEditor::IsRootNode(nsIDOMNode *inNode)
nsEditor::IsRootNode(nsINode *inNode)
{
NS_ENSURE_TRUE(inNode, false);
nsIDOMElement *rootElement = GetRoot();
nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(rootElement);
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
return inNode == rootNode;
return node == rootElement;
}
bool
nsEditor::IsDescendantOfBody(nsIDOMNode *inNode)
{
NS_ENSURE_TRUE(inNode, false);
nsIDOMElement *rootElement = GetRoot();
NS_ENSURE_TRUE(rootElement, false);
nsCOMPtr<nsIDOMNode> root = do_QueryInterface(rootElement);
nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
return IsDescendantOfBody(node);
}
if (inNode == root.get()) return true;
nsCOMPtr<nsIDOMNode> parent, node = do_QueryInterface(inNode);
do
{
node->GetParentNode(getter_AddRefs(parent));
if (parent == root) return true;
node = parent;
} while (parent);
return false;
bool
nsEditor::IsDescendantOfBody(nsINode *inNode)
{
NS_ENSURE_TRUE(inNode, false);
nsCOMPtr<nsIContent> root = do_QueryInterface(GetRoot());
NS_ENSURE_TRUE(root, false);
return nsContentUtils::ContentIsDescendantOf(inNode, root);
}
bool
@ -3604,7 +3585,7 @@ nsEditor::IsContainer(nsIDOMNode *aNode)
}
bool
nsEditor::IsTextInDirtyFrameVisible(nsIDOMNode *aNode)
nsEditor::IsTextInDirtyFrameVisible(nsIContent *aNode)
{
// virtual method
//
@ -3614,11 +3595,52 @@ nsEditor::IsTextInDirtyFrameVisible(nsIDOMNode *aNode)
return true;
}
static bool
IsElementVisible(nsIContent* aContent) {
mozilla::dom::Element* element = aContent->AsElement();
static inline bool
IsElementVisible(dom::Element* aElement)
{
if (aElement->GetPrimaryFrame()) {
// It's visible, for our purposes
return true;
}
nsIContent *cur = aElement;
for (; ;) {
cur = cur->GetFlattenedTreeParent();
if (!cur) {
// None of our ancestors have lazy bits set, so we shouldn't have a frame
return false;
}
if (cur->GetPrimaryFrame()) {
// None of our ancestors up to the nearest ancestor with a frame have
// lazy bits; that means we won't get a frame
return false;
}
if (cur->HasFlag(NODE_NEEDS_FRAME)) {
// Double-check that the parent doesn't have a leaf frame
nsIContent *parent = cur->GetFlattenedTreeParent();
if (parent) {
NS_ASSERTION(parent->GetPrimaryFrame(),
"Why does our parent not have a frame?");
if (parent->GetPrimaryFrame()->IsLeaf()) {
// No frame for us
return false;
}
}
// |cur| will get a frame sometime. What does that mean for us?
// |We have to figure that out!
break;
}
}
// Now it might be that we have no frame because we're in a
// display:none subtree, or it might be that we're just dealing with
// lazy frame construction and it hasn't happened yet. Check which
// one it is.
nsRefPtr<nsStyleContext> styleContext =
nsComputedDOMStyle::GetStyleContextForElementNoFlush(element,
nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement,
nsnull, nsnull);
if (styleContext) {
return styleContext->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_NONE;
@ -3628,6 +3650,13 @@ IsElementVisible(nsIContent* aContent) {
bool
nsEditor::IsEditable(nsIDOMNode *aNode)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
return IsEditable(content);
}
bool
nsEditor::IsEditable(nsIContent *aNode)
{
NS_ENSURE_TRUE(aNode, false);
@ -3635,24 +3664,28 @@ nsEditor::IsEditable(nsIDOMNode *aNode)
// see if it has a frame. If so, we'll edit it.
// special case for textnodes: frame must have width.
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
if (content)
{
if (content->IsElement() &&
!IsElementVisible(content)) // If the element is invisible, it's not editable
return false;
if (!content->IsNodeOfType(nsINode::eTEXT))
return true; // not a text node; not invisible
return IsTextInDirtyFrameVisible(aNode);
if (aNode->IsElement() && !IsElementVisible(aNode->AsElement())) {
// If the element has no frame, it's not editable. Note that we
// need to check IsElement() here, because some of our tests
// rely on frameless textnodes being visible.
return false;
}
return false; // didn't pass any editability test
if (aNode->NodeType() != nsIDOMNode::TEXT_NODE)
return true; // not a text node; not invisible
return IsTextInDirtyFrameVisible(aNode);
}
bool
nsEditor::IsMozEditorBogusNode(nsIDOMNode *aNode)
{
nsCOMPtr<nsIContent> element = do_QueryInterface(aNode);
return IsMozEditorBogusNode(element);
}
bool
nsEditor::IsMozEditorBogusNode(nsIContent *element)
{
return element &&
element->AttrValueIs(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
kMOZEditorBogusNodeValue, eCaseMatters);
@ -3735,7 +3768,7 @@ NS_IMETHODIMP nsEditor::ResetModificationCount()
///////////////////////////////////////////////////////////////////////////
// GetTag: digs out the atom for the tag of this node
//
//
nsIAtom *
nsEditor::GetTag(nsIDOMNode *aNode)
{
@ -3826,6 +3859,11 @@ nsEditor::IsTextNode(nsIDOMNode *aNode)
return (nodeType == nsIDOMNode::TEXT_NODE);
}
bool
nsEditor::IsTextNode(nsINode *aNode)
{
return aNode->NodeType() == nsIDOMNode::TEXT_NODE;
}
///////////////////////////////////////////////////////////////////////////
// GetIndexOf: returns the position index of the node in the parent
@ -5334,6 +5372,12 @@ nsEditor::IsModifiableNode(nsIDOMNode *aNode)
return true;
}
bool
nsEditor::IsModifiableNode(nsINode *aNode)
{
return true;
}
nsKeyEvent*
nsEditor::GetNativeKeyEvent(nsIDOMKeyEvent* aDOMKeyEvent)
{

View File

@ -169,6 +169,7 @@ public:
public:
virtual bool IsModifiableNode(nsINode *aNode);
NS_IMETHOD InsertTextImpl(const nsAString& aStringToInsert,
nsCOMPtr<nsIDOMNode> *aInOutNode,
@ -367,18 +368,13 @@ protected:
// stub. see comment in source.
virtual bool IsBlockNode(nsIDOMNode *aNode);
virtual bool IsBlockNode(nsINode *aNode);
// helper for GetPriorNode
nsresult GetPriorNodeImpl(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing = false);
// helper for GetNextNode
nsresult GetNextNodeImpl(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing = false);
// helper for GetPriorNode and GetNextNode
nsIContent* FindNextLeafNode(nsINode *aCurrentNode,
bool aGoForward,
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot);
// Get nsIWidget interface
nsresult GetWidget(nsIWidget **aWidget);
@ -479,18 +475,22 @@ public:
* @param aResultNode [OUT] the node that occurs before aCurrentNode in the tree,
* skipping non-editable nodes if aEditableNode is true.
* If there is no prior node, aResultNode will be nsnull.
* @param bNoBlockCrossing If true, don't move across "block" nodes, whatever that means.
* @param aActiveEditorRoot If non-null, only return descendants of aActiveEditorRoot.
*/
nsresult GetPriorNode(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing = false);
bool bNoBlockCrossing = false,
nsIContent *aActiveEditorRoot = nsnull);
// and another version that takes a {parent,offset} pair rather than a node
nsresult GetPriorNode(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing = false);
bool bNoBlockCrossing = false,
nsIContent *aActiveEditorRoot = nsnull);
/** get the node immediately after to aCurrentNode
* @param aCurrentNode the node from which we start the search
@ -502,21 +502,31 @@ public:
nsresult GetNextNode(nsIDOMNode *aCurrentNode,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing = false);
bool bNoBlockCrossing = false,
nsIContent *aActiveEditorRoot = nsnull);
// and another version that takes a {parent,offset} pair rather than a node
nsresult GetNextNode(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing = false);
bool bNoBlockCrossing = false,
nsIContent *aActiveEditorRoot = nsnull);
// Helper for GetNextNode and GetPriorNode
nsIContent* FindNode(nsINode *aCurrentNode,
bool aGoForward,
bool aEditableNode,
bool bNoBlockCrossing,
nsIContent *aActiveEditorRoot);
/**
* Get the rightmost child of aCurrentNode;
* return nsnull if aCurrentNode has no children.
*/
already_AddRefed<nsIDOMNode> GetRightmostChild(nsIDOMNode *aCurrentNode,
bool bNoBlockCrossing = false);
nsIContent* GetRightmostChild(nsINode *aCurrentNode,
bool bNoBlockCrossing = false);
/**
* Get the leftmost child of aCurrentNode;
@ -524,6 +534,8 @@ public:
*/
already_AddRefed<nsIDOMNode> GetLeftmostChild(nsIDOMNode *aCurrentNode,
bool bNoBlockCrossing = false);
nsIContent* GetLeftmostChild(nsINode *aCurrentNode,
bool bNoBlockCrossing = false);
/** returns true if aNode is of the type implied by aTag */
static inline bool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
@ -546,20 +558,24 @@ public:
/** returns true if aNode is our root node */
bool IsRootNode(nsIDOMNode *inNode);
bool IsRootNode(nsINode *inNode);
/** returns true if aNode is a descendant of our root node */
bool IsDescendantOfBody(nsIDOMNode *inNode);
bool IsDescendantOfBody(nsINode *inNode);
/** returns true if aNode is a container */
virtual bool IsContainer(nsIDOMNode *aNode);
/** returns true if aNode is an editable node */
bool IsEditable(nsIDOMNode *aNode);
bool IsEditable(nsIContent *aNode);
virtual bool IsTextInDirtyFrameVisible(nsIDOMNode *aNode);
virtual bool IsTextInDirtyFrameVisible(nsIContent *aNode);
/** returns true if aNode is a MozEditorBogus node */
bool IsMozEditorBogusNode(nsIDOMNode *aNode);
bool IsMozEditorBogusNode(nsIContent *aNode);
/** counts number of editable child nodes */
nsresult CountEditableChildren(nsIDOMNode *aNode, PRUint32 &outCount);
@ -580,6 +596,7 @@ public:
virtual bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
static bool IsTextOrElementNode(nsIDOMNode *aNode);
static bool IsTextNode(nsIDOMNode *aNode);
static bool IsTextNode(nsINode *aNode);
static PRInt32 GetIndexOf(nsIDOMNode *aParent, nsIDOMNode *aChild);
static nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, PRInt32 aOffset);

View File

@ -913,6 +913,15 @@ nsHTMLEditor::IsBlockNode(nsIDOMNode *aNode)
return isBlock;
}
bool
nsHTMLEditor::IsBlockNode(nsINode *aNode)
{
bool isBlock;
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
NodeIsBlockStatic(node, &isBlock);
return isBlock;
}
// Non-static version for the nsIEditor interface and JavaScript
NS_IMETHODIMP
nsHTMLEditor::SetDocumentTitle(const nsAString &aTitle)
@ -3903,9 +3912,14 @@ nsHTMLEditor::FindUserSelectAllNode(nsIDOMNode* aNode)
NS_IMETHODIMP_(bool)
nsHTMLEditor::IsModifiableNode(nsIDOMNode *aNode)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
return IsModifiableNode(node);
}
return !content || content->IsEditable();
bool
nsHTMLEditor::IsModifiableNode(nsINode *aNode)
{
return !aNode || aNode->IsEditable();
}
static nsresult SetSelectionAroundHeadChildren(nsCOMPtr<nsISelection> aSelection, nsWeakPtr aDocWeak)
@ -4692,13 +4706,18 @@ nsresult
nsHTMLEditor::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing)
{
NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
nsresult res = GetPriorNode(inNode, true, address_of(*outNode), bNoBlockCrossing);
nsIContent* activeEditingHost = GetActiveEditingHost();
if (!activeEditingHost) {
*outNode = nsnull;
return NS_OK;
}
nsresult res = GetPriorNode(inNode, true, address_of(*outNode), bNoBlockCrossing, activeEditingHost);
NS_ENSURE_SUCCESS(res, res);
// if it's not in the body, then zero it out
if (*outNode && !IsNodeInActiveEditor(*outNode)) {
*outNode = nsnull;
}
NS_ASSERTION(!*outNode || IsNodeInActiveEditor(*outNode),
"GetPriorNode screwed up");
return res;
}
@ -4710,13 +4729,18 @@ nsresult
nsHTMLEditor::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode, bool bNoBlockCrossing)
{
NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
nsresult res = GetPriorNode(inParent, inOffset, true, address_of(*outNode), bNoBlockCrossing);
nsIContent* activeEditingHost = GetActiveEditingHost();
if (!activeEditingHost) {
*outNode = nsnull;
return NS_OK;
}
nsresult res = GetPriorNode(inParent, inOffset, true, address_of(*outNode), bNoBlockCrossing, activeEditingHost);
NS_ENSURE_SUCCESS(res, res);
// if it's not in the body, then zero it out
if (*outNode && !IsNodeInActiveEditor(*outNode)) {
*outNode = nsnull;
}
NS_ASSERTION(!*outNode || IsNodeInActiveEditor(*outNode),
"GetPriorNode screwed up");
return res;
}
@ -4924,10 +4948,11 @@ nsHTMLEditor::GetLastEditableLeaf(nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutL
}
bool
nsHTMLEditor::IsTextInDirtyFrameVisible(nsIDOMNode *aNode)
nsHTMLEditor::IsTextInDirtyFrameVisible(nsIContent *aNode)
{
bool isEmptyTextNode;
nsresult res = IsVisTextNode(aNode, &isEmptyTextNode, false);
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
nsresult res = IsVisTextNode(node, &isEmptyTextNode, false);
if (NS_FAILED(res))
{
// We are following the historical decision:
@ -4944,7 +4969,7 @@ nsHTMLEditor::IsTextInDirtyFrameVisible(nsIDOMNode *aNode)
// IsVisTextNode: figure out if textnode aTextNode has any visible content.
//
nsresult
nsHTMLEditor::IsVisTextNode( nsIDOMNode *aNode,
nsHTMLEditor::IsVisTextNode( nsIDOMNode* aNode,
bool *outIsEmptyNode,
bool aSafeToAskFrames)
{

View File

@ -384,6 +384,7 @@ public:
PRInt32 *aInOutOffset,
nsIDOMDocument *aDoc);
NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode *aNode);
virtual bool IsModifiableNode(nsINode *aNode);
NS_IMETHOD SelectAll();
@ -417,7 +418,7 @@ public:
// aSelection is optional -- if null, we get current seletion
nsresult CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode);
virtual bool IsTextInDirtyFrameVisible(nsIDOMNode *aNode);
virtual bool IsTextInDirtyFrameVisible(nsIContent *aNode);
nsresult IsVisTextNode( nsIDOMNode *aNode,
bool *outIsEmptyNode,
@ -547,6 +548,7 @@ protected:
NS_IMETHOD IsRootTag(nsString &aTag, bool &aIsTag);
virtual bool IsBlockNode(nsIDOMNode *aNode);
virtual bool IsBlockNode(nsINode *aNode);
static nsCOMPtr<nsIDOMNode> GetEnclosingTable(nsIDOMNode *aNode);

View File

@ -130,8 +130,7 @@ JetpackChild::Init(base::ProcessHandle aParentProcessHandle,
JS_SetVersion(mCx, JSVERSION_LATEST);
JS_SetOptions(mCx, JS_GetOptions(mCx) |
JSOPTION_DONT_REPORT_UNCAUGHT |
JSOPTION_ATLINE |
JSOPTION_JIT);
JSOPTION_ATLINE);
JS_SetErrorReporter(mCx, ReportError);
{

1
js/src/aclocal.m4 vendored
View File

@ -9,6 +9,7 @@ builtin(include, build/autoconf/altoptions.m4)dnl
builtin(include, build/autoconf/moznbytetype.m4)dnl
builtin(include, build/autoconf/mozprog.m4)dnl
builtin(include, build/autoconf/mozheader.m4)dnl
builtin(include, build/autoconf/mozcommonheader.m4)dnl
builtin(include, build/autoconf/acwinpaths.m4)dnl
builtin(include, build/autoconf/lto.m4)dnl
builtin(include, build/autoconf/gcc-pr49911.m4)dnl

View File

@ -0,0 +1,41 @@
dnl ***** BEGIN LICENSE BLOCK *****
dnl Version: MPL 1.1/GPL 2.0/LGPL 2.1
dnl
dnl The contents of this file are subject to the Mozilla Public License Version
dnl 1.1 (the "License"); you may not use this file except in compliance with
dnl the License. You may obtain a copy of the License at
dnl http://www.mozilla.org/MPL/
dnl
dnl Software distributed under the License is distributed on an "AS IS" basis,
dnl WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
dnl for the specific language governing rights and limitations under the
dnl License.
dnl
dnl The Original Code is mozilla.org code.
dnl
dnl The Initial Developer of the Original Code is the
dnl Mozilla Foundation <http://www.mozilla.org>
dnl
dnl Portions created by the Initial Developer are Copyright (C) 2009
dnl the Initial Developer. All Rights Reserved.
dnl
dnl
dnl Alternatively, the contents of this file may be used under the terms of
dnl either of the GNU General Public License Version 2 or later (the "GPL"),
dnl or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
dnl in which case the provisions of the GPL or the LGPL are applicable instead
dnl of those above. If you wish to allow use of your version of this file only
dnl under the terms of either the GPL or the LGPL, and not to allow others to
dnl use your version of this file under the terms of the MPL, indicate your
dnl decision by deleting the provisions above and replace them with the notice
dnl and other provisions required by the GPL or the LGPL. If you do not delete
dnl the provisions above, a recipient may use your version of this file under
dnl the terms of any one of the MPL, the GPL or the LGPL.
dnl
dnl ***** END LICENSE BLOCK *****
AC_DEFUN(MOZ_CHECK_COMMON_HEADERS,
MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h sys/bitypes.h \
memory.h unistd.h gnu/libc-version.h nl_types.h malloc.h \
X11/XKBlib.h io.h cpuid.h)
)

View File

@ -3248,12 +3248,7 @@ freebsd*)
CPPFLAGS="${CPPFLAGS} ${X_CFLAGS}"
;;
esac
MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h)
MOZ_CHECK_HEADERS(sys/bitypes.h memory.h unistd.h)
MOZ_CHECK_HEADERS(gnu/libc-version.h nl_types.h)
MOZ_CHECK_HEADERS(malloc.h)
MOZ_CHECK_HEADERS(X11/XKBlib.h)
MOZ_CHECK_HEADERS(io.h)
MOZ_CHECK_COMMON_HEADERS
dnl These are all the places some variant of statfs can be hiding.
MOZ_CHECK_HEADERS(sys/statvfs.h sys/statfs.h sys/vfs.h sys/mount.h)

View File

@ -429,14 +429,11 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin
}
/*
* Farble the body so that it looks like a block statement to EmitTree,
* which is called from EmitFunctionBody (see BytecodeEmitter.cpp).
* After we're done parsing, we must fold constants, analyze any nested
* functions, and generate code for this function, including a stop opcode
* at the end.
*/
tokenStream.mungeCurrentToken(TOK_LC);
ParseNode *pn = fn ? parser.functionBody() : NULL;
ParseNode *pn = fn ? parser.functionBody(Parser::StatementListBody) : NULL;
if (pn) {
if (!CheckStrictParameters(cx, &funbce)) {
pn = NULL;

View File

@ -1454,7 +1454,8 @@ EmitTraceOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
* instruction. nextpn is often a block, in which case the next
* instruction typically comes from the first statement inside.
*/
if (nextpn->isKind(PNK_LC) && nextpn->isArity(PN_LIST) && nextpn->pn_head)
JS_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
nextpn = nextpn->pn_head;
if (!UpdateLineNumberNotes(cx, bce, nextpn->pn_pos.begin.lineno))
return -1;
@ -3345,7 +3346,7 @@ EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
#if !JS_HAS_BLOCK_SCOPE
PushStatement(bce, &stmtInfo, STMT_SWITCH, top);
#else
if (pn2->isKind(PNK_LC)) {
if (pn2->isKind(PNK_STATEMENTLIST)) {
PushStatement(bce, &stmtInfo, STMT_SWITCH, top);
} else {
/* Re-push the switch's statement info record. */
@ -4272,8 +4273,8 @@ EmitVariables(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSBool inLetHe
/*
* Emit variable binding ops, but not destructuring ops. The
* parser (see Parser::variables) has ensured that our caller
* will be the PNK_FOR/PNK_IN case in EmitTree, and that case
* will emit the destructuring code only after emitting an
* will be the PNK_FOR/PNK_FORIN case in EmitTree, and that
* case will emit the destructuring code only after emitting an
* enumerating opcode and a branch that tests whether the
* enumeration ended.
*/
@ -5319,7 +5320,7 @@ EmitXMLTag(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
JS_ASSERT(pn->pn_count != 0);
ParseNode *pn2 = pn->pn_head;
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return false;
if (!EmitTree(cx, bce, pn2))
return false;
@ -5328,11 +5329,11 @@ EmitXMLTag(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
uint32 i;
for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) {
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return false;
if (!EmitTree(cx, bce, pn2))
return false;
if ((i & 1) && pn2->isKind(PNK_LC)) {
if ((i & 1) && pn2->isKind(PNK_XMLCURLYEXPR)) {
if (Emit1(cx, bce, JSOP_TOATTRVAL) < 0)
return false;
}
@ -5613,7 +5614,7 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
if (op == JSOP_POP) {
if (!EmitTree(cx, bce, pn3))
return false;
if (pn3->isKind(PNK_VAR) || pn3->isKind(PNK_LET)) {
if (pn3->isKind(PNK_VAR) || pn3->isKind(PNK_CONST) || pn3->isKind(PNK_LET)) {
/*
* Check whether a destructuring-initialized var decl
* was optimized to a group assignment. If so, we do
@ -5735,7 +5736,8 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
static inline bool
EmitFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
{
return pn->pn_left->isKind(PNK_IN)
JS_ASSERT(pn->pn_left->isKind(PNK_FORIN) || pn->pn_left->isKind(PNK_FORHEAD));
return pn->pn_left->isKind(PNK_FORIN)
? EmitForIn(cx, bce, pn, top)
: EmitNormalFor(cx, bce, pn, top);
}
@ -5787,7 +5789,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
/*
* This second pass is needed to emit JSOP_NOP with a source note
* for the already-emitted function definition prolog opcode. See
* comments in the PNK_LC case.
* comments in the PNK_STATEMENTLIST case.
*/
JS_ASSERT(pn->isOp(JSOP_NOP));
JS_ASSERT(bce->inFunction());
@ -5998,7 +6000,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
ok = PopStatementBCE(cx, bce);
break;
case PNK_DO:
case PNK_DOWHILE:
/* Emit an annotated nop so we know to decompile a 'do' keyword. */
noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
@ -6118,6 +6120,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break;
case PNK_VAR:
case PNK_CONST:
if (!EmitVariables(cx, bce, pn, JS_FALSE, &noteIndex))
return JS_FALSE;
break;
@ -6175,18 +6178,18 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break;
#endif
case PNK_LC:
{
#if JS_HAS_XML_SUPPORT
if (pn->isArity(PN_UNARY)) {
if (!EmitTree(cx, bce, pn->pn_kid))
return JS_FALSE;
if (Emit1(cx, bce, pn->getOp()) < 0)
return JS_FALSE;
break;
}
case PNK_XMLCURLYEXPR:
JS_ASSERT(pn->isArity(PN_UNARY));
if (!EmitTree(cx, bce, pn->pn_kid))
return JS_FALSE;
if (Emit1(cx, bce, pn->getOp()) < 0)
return JS_FALSE;
break;
#endif
case PNK_STATEMENTLIST:
{
JS_ASSERT(pn->isArity(PN_LIST));
noteIndex = -1;
@ -6219,7 +6222,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* functions, see bug 419662.
*/
JS_ASSERT(pnchild->isKind(PNK_SEMI));
JS_ASSERT(pnchild->pn_kid->isKind(PNK_VAR));
JS_ASSERT(pnchild->pn_kid->isKind(PNK_VAR) || pnchild->pn_kid->isKind(PNK_CONST));
if (!EmitTree(cx, bce, pnchild))
return JS_FALSE;
pnchild = pnchild->pn_next;
@ -6354,9 +6357,9 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return JS_FALSE;
pn2 = pn->expr();
noteType = (pn2->isKind(PNK_LC) ||
noteType = (pn2->isKind(PNK_STATEMENTLIST) ||
(pn2->isKind(PNK_LEXICALSCOPE) &&
pn2->expr()->isKind(PNK_LC)))
pn2->expr()->isKind(PNK_STATEMENTLIST)))
? SRC_LABELBRACE
: SRC_LABEL;
noteIndex = NewSrcNote2(cx, bce, noteType, ptrdiff_t(index));
@ -6536,10 +6539,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
break;
case PNK_PLUS:
case PNK_MINUS:
if (pn->isArity(PN_UNARY))
goto unary_plusminus;
case PNK_ADD:
case PNK_SUB:
case PNK_BITOR:
case PNK_BITXOR:
case PNK_BITAND:
@ -6629,7 +6630,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
case PNK_THROW:
#if JS_HAS_XML_SUPPORT
case PNK_AT:
case PNK_DEFAULT:
case PNK_DEFXMLNS:
JS_ASSERT(pn->isArity(PN_UNARY));
/* FALL THROUGH */
#endif
@ -6637,7 +6638,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
case PNK_VOID:
case PNK_NOT:
case PNK_BITNOT:
unary_plusminus:
case PNK_POS:
case PNK_NEG:
{
/* Unary op, including unary +/-. */
op = pn->getOp();
@ -7291,7 +7293,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return JS_FALSE;
if (!EmitTree(cx, bce, pn2))
return JS_FALSE;
@ -7330,7 +7332,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (pn->isArity(PN_LIST)) {
JS_ASSERT(pn->pn_count != 0);
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (pn2->isKind(PNK_LC) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
return JS_FALSE;
if (!EmitTree(cx, bce, pn2))
return JS_FALSE;

View File

@ -52,25 +52,25 @@
using namespace js;
static ParseNode *
ContainsStmt(ParseNode *pn, ParseNodeKind kind)
ContainsVarOrConst(ParseNode *pn)
{
if (!pn)
return NULL;
if (pn->isKind(kind))
if (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST))
return pn;
switch (pn->getArity()) {
case PN_LIST:
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
if (ParseNode *pnt = ContainsStmt(pn2, kind))
if (ParseNode *pnt = ContainsVarOrConst(pn2))
return pnt;
}
break;
case PN_TERNARY:
if (ParseNode *pnt = ContainsStmt(pn->pn_kid1, kind))
if (ParseNode *pnt = ContainsVarOrConst(pn->pn_kid1))
return pnt;
if (ParseNode *pnt = ContainsStmt(pn->pn_kid2, kind))
if (ParseNode *pnt = ContainsVarOrConst(pn->pn_kid2))
return pnt;
return ContainsStmt(pn->pn_kid3, kind);
return ContainsVarOrConst(pn->pn_kid3);
case PN_BINARY:
/*
* Limit recursion if pn is a binary expression, which can't contain a
@ -78,17 +78,17 @@ ContainsStmt(ParseNode *pn, ParseNodeKind kind)
*/
if (!pn->isOp(JSOP_NOP))
return NULL;
if (ParseNode *pnt = ContainsStmt(pn->pn_left, kind))
if (ParseNode *pnt = ContainsVarOrConst(pn->pn_left))
return pnt;
return ContainsStmt(pn->pn_right, kind);
return ContainsVarOrConst(pn->pn_right);
case PN_UNARY:
if (!pn->isOp(JSOP_NOP))
return NULL;
return ContainsStmt(pn->pn_kid, kind);
return ContainsVarOrConst(pn->pn_kid);
case PN_NAME:
return ContainsStmt(pn->maybeExpr(), kind);
return ContainsVarOrConst(pn->maybeExpr());
case PN_NAMESET:
return ContainsStmt(pn->pn_tree, kind);
return ContainsVarOrConst(pn->pn_tree);
default:;
}
return NULL;
@ -501,7 +501,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
/* First kid may be null (for default case in switch). */
if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(PNK_WHILE)))
return false;
if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_DO)))
if (!FoldConstants(cx, pn2, tc, pn->isKind(PNK_DOWHILE)))
return false;
break;
@ -552,7 +552,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
switch (pn->getKind()) {
case PNK_IF:
if (ContainsStmt(pn2, PNK_VAR) || ContainsStmt(pn3, PNK_VAR))
if (ContainsVarOrConst(pn2) || ContainsVarOrConst(pn3))
break;
/* FALL THROUGH */
@ -594,7 +594,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
* NB: pn must be a PNK_IF as PNK_HOOK can never have a null kid
* or an empty statement for a child.
*/
pn->setKind(PNK_LC);
pn->setKind(PNK_STATEMENTLIST);
pn->setArity(PN_LIST);
pn->makeEmpty();
}
@ -683,9 +683,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
case PNK_ADDASSIGN:
JS_ASSERT(pn->isOp(JSOP_ADD));
/* FALL THROUGH */
case PNK_PLUS:
if (pn->isArity(PN_UNARY))
goto unary_plusminus;
case PNK_ADD:
if (pn->isArity(PN_LIST)) {
/*
* Any string literal term with all others number or string means
@ -767,10 +765,7 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
/* Can't concatenate string literals, let's try numbers. */
goto do_binary_op;
case PNK_MINUS:
if (pn->isArity(PN_UNARY))
goto unary_plusminus;
/* FALL THROUGH */
case PNK_SUB:
case PNK_STAR:
case PNK_LSH:
case PNK_RSH:
@ -819,7 +814,8 @@ js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
case PNK_VOID:
case PNK_NOT:
case PNK_BITNOT:
unary_plusminus:
case PNK_POS:
case PNK_NEG:
if (pn1->isKind(PNK_NUMBER)) {
jsdouble d;

View File

@ -405,7 +405,7 @@ ParseNode::append(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right
left->pn_parens = false;
left->initList(pn1);
left->append(pn2);
if (kind == PNK_PLUS) {
if (kind == PNK_ADD) {
if (pn1->isKind(PNK_STRING))
left->pn_xflags |= PNX_STRCAT;
else if (!pn1->isKind(PNK_NUMBER))
@ -418,7 +418,7 @@ ParseNode::append(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right
}
left->append(right);
left->pn_pos.end = right->pn_pos.end;
if (kind == PNK_PLUS) {
if (kind == PNK_ADD) {
if (right->isKind(PNK_STRING))
left->pn_xflags |= PNX_STRCAT;
else if (!right->isKind(PNK_NUMBER))
@ -437,19 +437,19 @@ ParseNode::newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, Parse
/*
* Flatten a left-associative (left-heavy) tree of a given operator into
* a list, to reduce js_FoldConstants and js_EmitTree recursion.
* a list to reduce js::FoldConstants and js::frontend::EmitTree recursion.
*/
if (left->isKind(kind) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC))
return append(kind, op, left, right);
/*
* Fold constant addition immediately, to conserve node space and, what's
* more, so js_FoldConstants never sees mixed addition and concatenation
* more, so js::FoldConstants never sees mixed addition and concatenation
* operations with more than one leading non-string operand in a PN_LIST
* generated for expressions such as 1 + 2 + "pt" (which should evaluate
* to "3pt", not "12pt").
*/
if (kind == PNK_PLUS &&
if (kind == PNK_ADD &&
left->isKind(PNK_NUMBER) &&
right->isKind(PNK_NUMBER) &&
tc->parser->foldConstants)

View File

@ -68,8 +68,10 @@ enum ParseNodeKind {
PNK_BITOR,
PNK_BITXOR,
PNK_BITAND,
PNK_PLUS,
PNK_MINUS,
PNK_POS,
PNK_NEG,
PNK_ADD,
PNK_SUB,
PNK_STAR,
PNK_DIV,
PNK_MOD,
@ -78,7 +80,8 @@ enum ParseNodeKind {
PNK_DOT,
PNK_LB,
PNK_RB,
PNK_LC,
PNK_STATEMENTLIST,
PNK_XMLCURLYEXPR,
PNK_RC,
PNK_LP,
PNK_RP,
@ -97,12 +100,13 @@ enum ParseNodeKind {
PNK_CASE,
PNK_DEFAULT,
PNK_WHILE,
PNK_DO,
PNK_DOWHILE,
PNK_FOR,
PNK_BREAK,
PNK_CONTINUE,
PNK_IN,
PNK_VAR,
PNK_CONST,
PNK_WITH,
PNK_RETURN,
PNK_NEW,
@ -116,6 +120,7 @@ enum ParseNodeKind {
PNK_THROW,
PNK_INSTANCEOF,
PNK_DEBUGGER,
PNK_DEFXMLNS,
PNK_XMLSTAGO,
PNK_XMLETAGO,
PNK_XMLPTAGC,
@ -141,6 +146,7 @@ enum ParseNodeKind {
PNK_LEXICALSCOPE,
PNK_LET,
PNK_SEQ,
PNK_FORIN,
PNK_FORHEAD,
PNK_ARGSBODY,
PNK_UPVARS,
@ -201,30 +207,33 @@ enum ParseNodeKind {
* create the function object at parse (not emit)
* time to specialize arg and var bytecodes early.
* pn_body: PNK_UPVARS if the function's source body
* depends on outer names, else PNK_ARGSBODY
* if formal parameters, else PNK_LC node for
* function body statements, else PNK_RETURN
* for expression closure, else PNK_SEQ for
* expression closure with destructured
* formal parameters
* depends on outer names,
* PNK_ARGSBODY if formal parameters,
* PNK_STATEMENTLIST node for function body
* statements,
* PNK_RETURN for expression closure, or
* PNK_SEQ for expression closure with
* destructured formal parameters
* pn_cookie: static level and var index for function
* pn_dflags: PND_* definition/use flags (see below)
* pn_blockid: block id number
* PNK_ARGSBODY list list of formal parameters followed by PNK_LC node
* for function body statements as final element
* PNK_ARGSBODY list list of formal parameters followed by
* PNK_STATEMENTLIST node for function body
* statements as final element
* pn_count: 1 + number of formal parameters
* PNK_UPVARS nameset pn_names: lexical dependencies (js::Definitions)
* defined in enclosing scopes, or ultimately not
* defined (free variables, either global property
* references or reference errors).
* pn_tree: PNK_ARGSBODY or PNK_LC node
* pn_tree: PNK_ARGSBODY or PNK_STATEMENTLIST node
*
* <Statements>
* PNK_LC list pn_head: list of pn_count statements
* PNK_STATEMENTLIST list pn_head: list of pn_count statements
* PNK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null.
* In body of a comprehension or desugared generator
* expression, pn_kid2 is PNK_YIELD, PNK_ARRAYPUSH,
* or (if the push was optimized away) empty PNK_LC.
* or (if the push was optimized away) empty
* PNK_STATEMENTLIST.
* PNK_SWITCH binary pn_left: discriminant
* pn_right: list of PNK_CASE nodes, with at most one
* PNK_DEFAULT node, or if there are let bindings
@ -232,27 +241,27 @@ enum ParseNodeKind {
* PNK_LEXICALSCOPE node that contains the list of
* PNK_CASE nodes.
* PNK_CASE, binary pn_left: case expr
* pn_right: PNK_LC node for this case's statements
* pn_right: PNK_STATEMENTLIST node for this case's
* statements
* PNK_DEFAULT binary pn_left: null
* pn_right: PNK_LC node for this default's statements
* pn_right: PNK_STATEMENTLIST node for this default's
* statements
* pn_val: constant value if lookup or table switch
* PNK_WHILE binary pn_left: cond, pn_right: body
* PNK_DO binary pn_left: body, pn_right: cond
* PNK_FOR binary pn_left: either
* for/in loop: a ternary PNK_IN node with
* pn_kid1: PNK_VAR to left of 'in', or NULL
* its pn_xflags may have PNX_POPVAR
* and PNX_FORINVAR bits set
* pn_kid2: PNK_NAME or destructuring expr
* to left of 'in'; if pn_kid1, then this
* is a clone of pn_kid1->pn_head
* pn_kid3: object expr to right of 'in'
* for(;;) loop: a ternary PNK_FORHEAD node with
* pn_kid1: init expr before first ';'
* pn_kid2: cond expr before second ';'
* pn_kid3: update expr after second ';'
* any kid may be null
* PNK_DOWHILE binary pn_left: body, pn_right: cond
* PNK_FOR binary pn_left: either PNK_FORIN (for-in statement) or
* PNK_FORHEAD (for(;;) statement)
* pn_right: body
* PNK_FORIN ternary pn_kid1: PNK_VAR to left of 'in', or NULL
* its pn_xflags may have PNX_POPVAR
* and PNX_FORINVAR bits set
* pn_kid2: PNK_NAME or destructuring expr
* to left of 'in'; if pn_kid1, then this
* is a clone of pn_kid1->pn_head
* pn_kid3: object expr to right of 'in'
* PNK_FORHEAD ternary pn_kid1: init expr before first ';' or NULL
* pn_kid2: cond expr before second ';' or NULL
* pn_kid3: update expr after second ';' or NULL
* PNK_THROW unary pn_op: JSOP_THROW, pn_kid: exception
* PNK_TRY ternary pn_kid1: try block
* pn_kid2: null or PNK_CATCHLIST list of
@ -266,8 +275,8 @@ enum ParseNodeKind {
* PNK_BREAK name pn_atom: label or null
* PNK_CONTINUE name pn_atom: label or null
* PNK_WITH binary pn_left: head expr, pn_right: body
* PNK_VAR list pn_head: list of PNK_NAME or PNK_ASSIGN nodes
* each name node has either
* PNK_VAR, list pn_head: list of PNK_NAME or PNK_ASSIGN nodes
* PNK_CONST each name node has either
* pn_used: false
* pn_atom: variable name
* pn_expr: initializer or null
@ -320,19 +329,20 @@ enum ParseNodeKind {
* PNK_LSH, binary pn_left: left-assoc SH expr, pn_right: ADD expr
* PNK_RSH,
* PNK_URSH
* PNK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
* pn_xflags: if a left-associated binary PNK_PLUS
* PNK_ADD binary pn_left: left-assoc ADD expr, pn_right: MUL expr
* pn_xflags: if a left-associated binary PNK_ADD
* tree has been flattened into a list (see above
* under <Expressions>), pn_xflags will contain
* PNX_STRCAT if at least one list element is a
* string literal (PNK_STRING); if such a list has
* any non-string, non-number term, pn_xflags will
* contain PNX_CANTFOLD.
* pn_
* PNK_MINUS pn_op: JSOP_ADD, JSOP_SUB
* PNK_SUB binary pn_left: left-assoc SH expr, pn_right: ADD expr
* PNK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
* PNK_DIV, pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
* PNK_MOD
* PNK_POS, unary pn_kid: UNARY expr
* PNK_NEG
* PNK_TYPEOF, unary pn_kid: UNARY expr
* PNK_VOID,
* PNK_NOT,
@ -383,7 +393,7 @@ enum ParseNodeKind {
* PNK_XMLUNARY unary pn_kid: PNK_AT, PNK_ANYNAME, or PNK_DBLCOLON node
* pn_op: JSOP_XMLNAME, JSOP_BINDXMLNAME, or
* JSOP_SETXMLNAME
* PNK_DEFAULT name pn_atom: default XML namespace string literal
* PNK_DEFXMLNS name pn_kid: namespace expr
* PNK_FILTER binary pn_left: container expr, pn_right: filter expr
* PNK_DBLDOT binary pn_left: container expr, pn_right: selector expr
* PNK_ANYNAME nullary pn_op: JSOP_ANYNAME
@ -414,7 +424,7 @@ enum ParseNodeKind {
* PNK_XMLPI nullary pn_pitarget: XML processing instruction target
* pn_pidata: XML PI data, or null if no data
* PNK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string
* PNK_LC unary {expr} in XML tag or content; pn_kid is expr
* PNK_XMLCURLYEXPR unary {expr} in XML tag or content; pn_kid is expr
*
* So an XML tag with no {expr} and three attributes is a list with the form:
*
@ -429,7 +439,7 @@ enum ParseNodeKind {
* ((name1 {expr1}) (name2 {expr2} name3) {expr3})
*
* where () bracket a list with elements separated by spaces, and {expr} is a
* PNK_LC unary node with expr as its kid.
* PNK_XMLCURLYEXPR unary node with expr as its kid.
*
* Thus, the attribute name/value pairs occupy successive odd and even list
* locations, where pn_head is the PNK_XMLNAME node at list location 0. The
@ -710,10 +720,11 @@ struct ParseNode {
#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED)
/* PN_LIST pn_xflags bits. */
#define PNX_STRCAT 0x01 /* PNK_PLUS list has string term */
#define PNX_CANTFOLD 0x02 /* PNK_PLUS list has unfoldable term */
#define PNX_POPVAR 0x04 /* PNK_VAR last result needs popping */
#define PNX_FORINVAR 0x08 /* PNK_VAR is left kid of PNK_IN node,
#define PNX_STRCAT 0x01 /* PNK_ADD list has string term */
#define PNX_CANTFOLD 0x02 /* PNK_ADD list has unfoldable term */
#define PNX_POPVAR 0x04 /* PNK_VAR or PNK_CONST last result
needs popping */
#define PNX_FORINVAR 0x08 /* PNK_VAR is left kid of PNK_FORIN node
which is left kid of PNK_FOR */
#define PNX_ENDCOMMA 0x10 /* array literal has comma at end */
#define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */
@ -985,8 +996,8 @@ CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
* js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants
* of js::ParseNode, allocated only for function, var, const, and let
* declarations that define truly lexical bindings. This means that a child of
* a PNK_VAR list may be a Definition instead of a ParseNode. The pn_defn
* bit is set for all Definitions, clear otherwise.
* a PNK_VAR list may be a Definition as well as a ParseNode. The pn_defn bit
* is set for all Definitions, clear otherwise.
*
* In an upvars list, defn->resolve() is the outermost definition the
* name may reference. If a with block or a function that calls eval encloses
@ -1029,7 +1040,7 @@ CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
* map x to dn via tc->decls;
* pn = dn;
* }
* insert pn into its parent PNK_VAR list;
* insert pn into its parent PNK_VAR/PNK_CONST list;
* } else {
* pn = allocate a ParseNode for this reference to x;
* dn = lookup x in tc's lexical scope chain;

View File

@ -261,7 +261,7 @@ GenerateBlockIdForStmtNode(ParseNode *pn, TreeContext *tc)
{
JS_ASSERT(tc->topStmt);
JS_ASSERT(STMT_MAYBE_SCOPE(tc->topStmt));
JS_ASSERT(pn->isKind(PNK_LC) || pn->isKind(PNK_LEXICALSCOPE));
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST) || pn->isKind(PNK_LEXICALSCOPE));
if (!GenerateBlockId(tc, tc->topStmt->blockid))
return false;
pn->pn_blockid = tc->topStmt->blockid;
@ -321,7 +321,7 @@ HasFinalReturn(ParseNode *pn)
uintN rv, rv2, hasDefault;
switch (pn->getKind()) {
case PNK_LC:
case PNK_STATEMENTLIST:
if (!pn->pn_head)
return ENDS_IN_OTHER;
return HasFinalReturn(pn->last());
@ -339,7 +339,7 @@ HasFinalReturn(ParseNode *pn)
return ENDS_IN_RETURN;
return ENDS_IN_OTHER;
case PNK_DO:
case PNK_DOWHILE:
pn2 = pn->pn_right;
if (pn2->isKind(PNK_FALSE))
return HasFinalReturn(pn->pn_left);
@ -368,7 +368,7 @@ HasFinalReturn(ParseNode *pn)
if (pn2->isKind(PNK_DEFAULT))
hasDefault = ENDS_IN_RETURN;
pn3 = pn2->pn_right;
JS_ASSERT(pn3->isKind(PNK_LC));
JS_ASSERT(pn3->isKind(PNK_STATEMENTLIST));
if (pn3->pn_head) {
rv2 = HasFinalReturn(pn3->last());
if (rv2 == ENDS_IN_OTHER && pn2->pn_next)
@ -571,7 +571,7 @@ js::CheckStrictParameters(JSContext *cx, TreeContext *tc)
}
ParseNode *
Parser::functionBody()
Parser::functionBody(FunctionBodyType type)
{
JS_ASSERT(tc->inFunction());
@ -583,10 +583,11 @@ Parser::functionBody()
tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID);
ParseNode *pn;
#if JS_HAS_EXPR_CLOSURES
if (tokenStream.currentToken().type == TOK_LC) {
if (type == StatementListBody) {
pn = statements();
} else {
JS_ASSERT(type == ExpressionBody);
JS_ASSERT(JS_HAS_EXPR_CLOSURES);
pn = UnaryNode::create(PNK_RETURN, tc);
if (pn) {
pn->pn_kid = assignExpr();
@ -605,9 +606,6 @@ Parser::functionBody()
}
}
}
#else
pn = statements();
#endif
if (pn) {
JS_ASSERT(!(tc->topStmt->flags & SIF_SCOPE));
@ -675,6 +673,8 @@ Define(ParseNode *pn, JSAtom *atom, TreeContext *tc, bool let = false)
if ((!pnu || pnu->pn_blockid < tc->bodyid) && foundLexdep)
tc->lexdeps->remove(atom);
}
pn->pn_dflags |= dn->pn_dflags & PND_CLOSED;
}
Definition *toAdd = (Definition *) pn;
@ -1509,17 +1509,18 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind
return NULL;
}
FunctionBodyType bodyType = StatementListBody;
#if JS_HAS_EXPR_CLOSURES
TokenKind tt = tokenStream.getToken(TSF_OPERAND);
if (tt != TOK_LC) {
if (tokenStream.getToken(TSF_OPERAND) != TOK_LC) {
tokenStream.ungetToken();
fun->flags |= JSFUN_EXPR_CLOSURE;
bodyType = ExpressionBody;
}
#else
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);
#endif
ParseNode *body = functionBody();
ParseNode *body = functionBody(bodyType);
if (!body)
return NULL;
@ -1530,7 +1531,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind
return NULL;
#if JS_HAS_EXPR_CLOSURES
if (tt == TOK_LC)
if (bodyType == StatementListBody)
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
else if (kind == Statement && !MatchOrInsertSemicolon(context, &tokenStream))
return NULL;
@ -1766,23 +1767,20 @@ Parser::recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMembe
ParseNode *
Parser::statements()
{
ParseNode *pn2, *saveBlock;
TokenKind tt;
JS_CHECK_RECURSION(context, return NULL);
ParseNode *pn = ListNode::create(PNK_LC, tc);
ParseNode *pn = ListNode::create(PNK_STATEMENTLIST, tc);
if (!pn)
return NULL;
pn->makeEmpty();
pn->pn_blockid = tc->blockid();
saveBlock = tc->blockNode;
ParseNode *saveBlock = tc->blockNode;
tc->blockNode = pn;
bool inDirectivePrologue = tc->atBodyLevel();
tokenStream.setOctalCharacterEscape(false);
for (;;) {
tt = tokenStream.peekToken(TSF_OPERAND);
TokenKind tt = tokenStream.peekToken(TSF_OPERAND);
if (tt <= TOK_EOF || tt == TOK_RC) {
if (tt == TOK_ERROR) {
if (tokenStream.isEOF())
@ -1791,17 +1789,17 @@ Parser::statements()
}
break;
}
pn2 = statement();
if (!pn2) {
ParseNode *next = statement();
if (!next) {
if (tokenStream.isEOF())
tokenStream.setUnexpectedEOF();
return NULL;
}
if (inDirectivePrologue && !recognizeDirectivePrologue(pn2, &inDirectivePrologue))
if (inDirectivePrologue && !recognizeDirectivePrologue(next, &inDirectivePrologue))
return NULL;
if (pn2->isKind(PNK_FUNCTION)) {
if (next->isKind(PNK_FUNCTION)) {
/*
* PNX_FUNCDEFS notifies the emitter that the block contains body-
* level function definitions that should be processed before the
@ -1819,7 +1817,7 @@ Parser::statements()
tc->noteHasExtensibleScope();
}
}
pn->append(pn2);
pn->append(next);
}
/*
@ -2815,7 +2813,7 @@ Parser::letBlock(JSBool statement)
ParseNode *pn = pnblock;
pn->pn_expr = pnlet;
pnlet->pn_left = variables(true);
pnlet->pn_left = variables(PNK_LP, true);
if (!pnlet->pn_left)
return NULL;
pnlet->pn_left->pn_xflags = PNX_POPVAR;
@ -2951,7 +2949,7 @@ Parser::switchStatement()
PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
/* pn2 is a list of case nodes. The default case has pn_left == NULL */
ParseNode *pn2 = ListNode::create(PNK_LC, tc);
ParseNode *pn2 = ListNode::create(PNK_STATEMENTLIST, tc);
if (!pn2)
return NULL;
pn2->makeEmpty();
@ -3003,7 +3001,7 @@ Parser::switchStatement()
MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
ParseNode *pn4 = ListNode::create(PNK_LC, tc);
ParseNode *pn4 = ListNode::create(PNK_STATEMENTLIST, tc);
if (!pn4)
return NULL;
pn4->makeEmpty();
@ -3108,12 +3106,13 @@ Parser::forStatement()
* clause of an ordinary for loop.
*/
tc->flags |= TCF_IN_FOR_INIT;
if (tt == TOK_VAR) {
if (tt == TOK_VAR || tt == TOK_CONST) {
forDecl = true;
(void) tokenStream.getToken();
pn1 = variables(false);
tokenStream.consumeKnownToken(tt);
pn1 = variables(tt == TOK_VAR ? PNK_VAR : PNK_CONST, false);
}
#if JS_HAS_BLOCK_SCOPE
} else if (tt == TOK_LET) {
else if (tt == TOK_LET) {
let = true;
(void) tokenStream.getToken();
if (tokenStream.peekToken() == TOK_LP) {
@ -3124,10 +3123,11 @@ Parser::forStatement()
if (!pnlet)
return NULL;
blockInfo.flags |= SIF_FOR_BLOCK;
pn1 = variables(false);
pn1 = variables(PNK_LET, false);
}
}
#endif
} else {
else {
pn1 = expr();
}
tc->flags &= ~TCF_IN_FOR_INIT;
@ -3313,7 +3313,7 @@ Parser::forStatement()
tc->topStmt = save;
#endif
pn4 = TernaryNode::create(PNK_IN, tc);
pn4 = TernaryNode::create(PNK_FORIN, tc);
if (!pn4)
return NULL;
} else {
@ -3648,9 +3648,7 @@ Parser::letStatement()
* ES4 specifies that let at top level and at body-block scope
* does not shadow var, so convert back to var.
*/
tokenStream.mungeCurrentToken(TOK_VAR, JSOP_DEFVAR);
pn = variables(false);
pn = variables(PNK_VAR, false);
if (!pn)
return NULL;
pn->pn_xflags |= PNX_POPVAR;
@ -3712,7 +3710,7 @@ Parser::letStatement()
tc->blockNode = pn1;
}
pn = variables(false);
pn = variables(PNK_LET, false);
if (!pn)
return NULL;
pn->pn_xflags = PNX_POPVAR;
@ -3757,7 +3755,7 @@ Parser::expressionStatement()
/* Normalize empty statement to empty block for the decompiler. */
if (pn->isKind(PNK_SEMI) && !pn->pn_kid) {
pn->setKind(PNK_LC);
pn->setKind(PNK_STATEMENTLIST);
pn->setArity(PN_LIST);
pn->makeEmpty();
}
@ -3889,7 +3887,7 @@ Parser::statement()
case TOK_DO:
{
pn = BinaryNode::create(PNK_DO, tc);
pn = BinaryNode::create(PNK_DOWHILE, tc);
if (!pn)
return NULL;
StmtInfo stmtInfo;
@ -4035,7 +4033,16 @@ Parser::statement()
return withStatement();
case TOK_VAR:
pn = variables(false);
pn = variables(PNK_VAR, false);
if (!pn)
return NULL;
/* Tell js_EmitTree to generate a final POP. */
pn->pn_xflags |= PNX_POPVAR;
break;
case TOK_CONST:
pn = variables(PNK_CONST, false);
if (!pn)
return NULL;
@ -4101,7 +4108,7 @@ Parser::statement()
if (tc->inStrictMode())
return expressionStatement();
pn = UnaryNode::create(PNK_DEFAULT, tc);
pn = UnaryNode::create(PNK_DEFXMLNS, tc);
if (!pn)
return NULL;
if (!tokenStream.matchToken(TOK_NAME) ||
@ -4140,18 +4147,18 @@ Parser::statement()
}
ParseNode *
Parser::variables(bool inLetHead)
Parser::variables(ParseNodeKind kind, bool inLetHead)
{
/*
* The three options here are:
* - TOK_VAR: We're parsing var declarations.
* - TOK_LET: We are parsing a let declaration.
* - TOK_LP: We are parsing the head of a let block.
* The four options here are:
* - PNK_VAR: We're parsing var declarations.
* - PNK_CONST: We're parsing const declarations.
* - PNK_LET: We are parsing a let declaration.
* - PNK_LP: We are parsing the head of a let block.
*/
TokenKind tt = tokenStream.currentToken().type;
JS_ASSERT(tt == TOK_VAR || tt == TOK_LET || tt == TOK_LP);
JS_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET || kind == PNK_LP);
bool let = (tt == TOK_LET || tt == TOK_LP);
bool let = (kind == PNK_LET || kind == PNK_LP);
#if JS_HAS_BLOCK_SCOPE
bool popScope = (inLetHead || (let && (tc->flags & TCF_IN_FOR_INIT)));
@ -4169,8 +4176,8 @@ Parser::variables(bool inLetHead)
}
BindData data;
data.op = let ? JSOP_NOP : tokenStream.currentToken().t_op;
ParseNode *pn = ListNode::create(tt == TOK_LET ? PNK_LET : tt == TOK_VAR ? PNK_VAR : PNK_LP, tc);
data.op = let ? JSOP_NOP : kind == PNK_VAR ? JSOP_DEFVAR : JSOP_DEFCONST;
ParseNode *pn = ListNode::create(kind, tc);
if (!pn)
return NULL;
pn->setOp(data.op);
@ -4191,7 +4198,7 @@ Parser::variables(bool inLetHead)
ParseNode *pn2;
do {
tt = tokenStream.getToken();
TokenKind tt = tokenStream.getToken();
#if JS_HAS_DESTRUCTURING
if (tt == TOK_LB || tt == TOK_LC) {
tc->flags |= TCF_DECL_DESTRUCTURING;
@ -4381,7 +4388,7 @@ BEGIN_EXPR_PARSER(addExpr1)
while (pn && tokenStream.isCurrentTokenType(TOK_PLUS, TOK_MINUS)) {
TokenKind tt = tokenStream.currentToken().type;
JSOp op = (tt == TOK_PLUS) ? JSOP_ADD : JSOP_SUB;
ParseNodeKind kind = (tt == TOK_PLUS) ? PNK_PLUS : PNK_MINUS;
ParseNodeKind kind = (tt == TOK_PLUS) ? PNK_ADD : PNK_SUB;
pn = ParseNode::newBinaryOrAppend(kind, op, pn, mulExpr1n(), tc);
}
return pn;
@ -4782,9 +4789,9 @@ Parser::unaryExpr()
case TOK_BITNOT:
return unaryOpExpr(PNK_BITNOT, JSOP_BITNOT);
case TOK_PLUS:
return unaryOpExpr(PNK_PLUS, JSOP_POS);
return unaryOpExpr(PNK_POS, JSOP_POS);
case TOK_MINUS:
return unaryOpExpr(PNK_MINUS, JSOP_NEG);
return unaryOpExpr(PNK_NEG, JSOP_NEG);
case TOK_INC:
case TOK_DEC:
@ -5406,7 +5413,7 @@ Parser::comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp,
if (!pn3)
return NULL;
pn2->pn_left = new_<TernaryNode>(PNK_IN, JSOP_NOP, vars, pn3, pn4);
pn2->pn_left = new_<TernaryNode>(PNK_FORIN, JSOP_NOP, vars, pn3, pn4);
if (!pn2->pn_left)
return NULL;
*pnp = pn2;
@ -6038,7 +6045,7 @@ Parser::xmlExpr(JSBool inTag)
JS_ASSERT(!tc->inStrictMode());
JS_ASSERT(tokenStream.currentToken().type == TOK_LC);
ParseNode *pn = UnaryNode::create(PNK_LC, tc);
ParseNode *pn = UnaryNode::create(PNK_XMLCURLYEXPR, tc);
if (!pn)
return NULL;
@ -6083,7 +6090,7 @@ Parser::atomNode(ParseNodeKind kind, JSOp op)
* Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces
* a list of names and/or expressions, a single expression, or a single name.
* If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME. Otherwise if
* PN_UNARY, getKind() will be PNK_LC.
* PN_UNARY, getKind() will be PNK_XMLCURLYEXPR.
*/
ParseNode *
Parser::xmlNameExpr()
@ -6135,7 +6142,7 @@ Parser::xmlNameExpr()
*/
#define XML_FOLDABLE(pn) ((pn)->isArity(PN_LIST) \
? ((pn)->pn_xflags & PNX_CANTFOLD) == 0 \
: !(pn)->isKind(PNK_LC))
: !(pn)->isKind(PNK_XMLCURLYEXPR))
/*
* Parse the productions:
@ -6152,7 +6159,7 @@ Parser::xmlNameExpr()
* If PN_LIST or PN_NULLARY, getKind() will be PNK_XMLNAME for the case where
* XMLTagContent: XMLNameExpr. If getKind() is not PNK_XMLNAME but getArity()
* is PN_LIST, getKind() will be tagkind. If PN_UNARY, getKind() will be
* PNK_LC and we parsed exactly one expression.
* PNK_XMLCURLYEXPR and we parsed exactly one expression.
*/
ParseNode *
Parser::xmlTagContent(ParseNodeKind tagkind, JSAtom **namep)
@ -6333,7 +6340,7 @@ Parser::xmlElementOrList(JSBool allowList)
freeTree(pn);
pn = pn2;
} else {
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_LC));
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR));
pn->initList(pn2);
if (!XML_FOLDABLE(pn2))
pn->pn_xflags |= PNX_CANTFOLD;
@ -6395,7 +6402,7 @@ Parser::xmlElementOrList(JSBool allowList)
}
/* Make a TOK_XMLETAGO list with pn2 as its single child. */
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_LC));
JS_ASSERT(pn2->isKind(PNK_XMLNAME) || pn2->isKind(PNK_XMLCURLYEXPR));
list = ListNode::create(PNK_XMLETAGO, tc);
if (!list)
return NULL;

View File

@ -157,7 +157,13 @@ struct Parser : private AutoGCRooter
/* Public entry points for parsing. */
ParseNode *statement();
bool recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMember);
ParseNode *functionBody();
/*
* Parse a function body. Pass StatementListBody if the body is a list of
* statements; pass ExpressionBody if the body is a single expression.
*/
enum FunctionBodyType { StatementListBody, ExpressionBody };
ParseNode *functionBody(FunctionBodyType type);
private:
/*
@ -188,7 +194,7 @@ struct Parser : private AutoGCRooter
ParseNode *letStatement();
#endif
ParseNode *expressionStatement();
ParseNode *variables(bool inLetHead);
ParseNode *variables(ParseNodeKind kind, bool inLetHead);
ParseNode *expr();
ParseNode *assignExpr();
ParseNode *condExpr1();

View File

@ -533,7 +533,7 @@ ConsiderUnbranding(FunctionBox *funbox)
pn2 = pn2->pn_tree;
if (pn2->isKind(PNK_ARGSBODY))
pn2 = pn2->last();
if (!pn2->isKind(PNK_LC))
if (!pn2->isKind(PNK_STATEMENTLIST))
returnsExpr = true;
}
#endif

View File

@ -2251,6 +2251,7 @@ TokenKindToString(TokenKind tt)
case TOK_CONTINUE: return "TOK_CONTINUE";
case TOK_IN: return "TOK_IN";
case TOK_VAR: return "TOK_VAR";
case TOK_CONST: return "TOK_CONST";
case TOK_WITH: return "TOK_WITH";
case TOK_RETURN: return "TOK_RETURN";
case TOK_NEW: return "TOK_NEW";

View File

@ -105,6 +105,7 @@ enum TokenKind {
TOK_CONTINUE, /* continue keyword */
TOK_IN, /* in keyword */
TOK_VAR, /* var keyword */
TOK_CONST, /* const keyword */
TOK_WITH, /* with keyword */
TOK_RETURN, /* return keyword */
TOK_NEW, /* new keyword */
@ -543,14 +544,7 @@ class TokenStream
bool isEOF() const { return !!(flags & TSF_EOF); }
bool hasOctalCharacterEscape() const { return flags & TSF_OCTAL_CHAR; }
/* Mutators. */
bool reportCompileErrorNumberVA(ParseNode *pn, uintN flags, uintN errorNumber, va_list ap);
void mungeCurrentToken(TokenKind newKind) { tokens[cursor].type = newKind; }
void mungeCurrentToken(JSOp newOp) { tokens[cursor].t_op = newOp; }
void mungeCurrentToken(TokenKind newKind, JSOp newOp) {
mungeCurrentToken(newKind);
mungeCurrentToken(newOp);
}
private:
static JSAtom *atomize(JSContext *cx, CharBuffer &cb);
@ -666,6 +660,10 @@ class TokenStream
return matchToken(tt);
}
void consumeKnownToken(TokenKind tt) {
JS_ALWAYS_TRUE(matchToken(tt));
}
/*
* Give up responsibility for managing the sourceMap filename's memory.
*/

View File

@ -0,0 +1,6 @@
// |jit-test| error: InternalError
var op = Object.prototype;
op.b = op;
op.__iterator__ = Iterator;
for (var c in {}) {}

View File

@ -0,0 +1,11 @@
function f() {
function g() {
for (var i = 0; i < 3; i++)
x = i;
};
var [x] = 0;
g();
assertEq(x, 2);
print(x);
}
f();

View File

@ -261,7 +261,6 @@ BEGIN_TEST(testDebugger_singleStepThrow)
uint32 opts = JS_GetOptions(cx);
opts |= JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS;
opts &= ~JSOPTION_JIT;
JS_SetOptions(cx, opts);
CHECK(JS_DefineFunction(cx, global, "setStepMode", setStepMode, 0, 0));

View File

@ -118,24 +118,21 @@ BEGIN_TEST(testFuncCallback_bug507012)
#endif
// Uncomment this to validate whether you're hitting all runmodes (interp,
// tjit, mjit, ...?) Unfortunately, that still doesn't cover all
// mjit, ...?) Unfortunately, that still doesn't cover all
// transitions between the various runmodes, but it's a start.
//JS_DumpAllProfiles(cx);
return true;
}
// Not strictly necessary, but part of the test attempts to check
// whether these callbacks still trigger when traced, so force
// JSOPTION_JIT just to be sure. Once the method jit and tracing jit
// are integrated, this'll probably have to change (and we'll probably
// want to test in all modes.)
// Make sure that the method jit is enabled.
// We'll probably want to test in all modes.
virtual
JSContext *createContext()
{
JSContext *cx = JSAPITest::createContext();
if (cx)
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_METHODJIT | JSOPTION_PCCOUNT);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_PCCOUNT);
return cx;
}

View File

@ -24,12 +24,6 @@ BEGIN_TEST(testGCOutOfMemory)
jsvalRoot root(cx);
/*
* We loop until we get out-of-memory. We have to disable the jit since it
* ignores the runtime allocation limits during execution.
*/
JS_ToggleOptions(cx, JSOPTION_JIT);
static const char source[] =
"var max = 0; (function() {"
" var array = [];"
@ -45,7 +39,6 @@ BEGIN_TEST(testGCOutOfMemory)
CHECK(!JS_IsExceptionPending(cx));
CHECK_EQUAL(errorCount, 1);
JS_GC(cx);
JS_ToggleOptions(cx, JSOPTION_JIT);
EVAL("(function() {"
" var array = [];"
" for (var i = max >> 2; i != 0;) {"

View File

@ -39,9 +39,6 @@ BEGIN_TEST(testTrap_gc)
CHECK(JSVAL_IS_OBJECT(v2));
CHECK_EQUAL(emptyTrapCallCount, 0);
// Disable JIT for debugging
JS_SetOptions(cx, JS_GetOptions(cx) & ~JSOPTION_JIT);
// Enable debug mode
CHECK(JS_SetDebugMode(cx, JS_TRUE));

View File

@ -374,7 +374,7 @@ class JSAPITest
JS_SetNativeStackQuota(cx, MAX_STACK_SIZE);
JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT);
JS_SetOptions(cx, JSOPTION_VAROBJFIX);
JS_SetVersion(cx, JSVERSION_LATEST);
JS_SetErrorReporter(cx, &reportError);
return cx;

View File

@ -2157,7 +2157,7 @@ JS_StringToVersion(const char *string);
of the input string */
/* JS_BIT(10) is currently unused. */
#define JSOPTION_JIT JS_BIT(11) /* Deprecated; does nothing */
/* JS_BIT(11) is currently unused. */
#define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12) /* A promise to the compiler
that a null rval out-param
@ -2170,7 +2170,9 @@ JS_StringToVersion(const char *string);
embedding. */
#define JSOPTION_METHODJIT JS_BIT(14) /* Whole-method JIT. */
#define JSOPTION_PROFILING JS_BIT(15) /* Profiler to make tracer/methodjit choices. */
/* JS_BIT(15) is currently unused. */
#define JSOPTION_METHODJIT_ALWAYS \
JS_BIT(16) /* Always whole-method JIT,
don't tune at run-time. */

View File

@ -132,6 +132,12 @@ JS_ObjectCountDynamicSlots(JSObject *obj)
return obj->numDynamicSlots(obj->numSlots());
return 0;
}
JS_PUBLIC_API(void)
JS_ShrinkingGC(JSContext *cx)
{
js_GC(cx, NULL, GC_SHRINK, gcstats::PUBLIC_API);
}
JS_FRIEND_API(JSPrincipals *)
JS_GetCompartmentPrincipals(JSCompartment *compartment)

View File

@ -70,6 +70,9 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObj
extern JS_FRIEND_API(uint32)
JS_ObjectCountDynamicSlots(JSObject *obj);
extern JS_FRIEND_API(void)
JS_ShrinkingGC(JSContext *cx);
extern JS_FRIEND_API(size_t)
JS_GetE4XObjectsCreated(JSContext *cx);

View File

@ -354,6 +354,8 @@ size_t sCustomIteratorCount = 0;
static inline bool
GetCustomIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
{
JS_CHECK_RECURSION(cx, return false);
/* Check whether we have a valid __iterator__ method. */
JSAtom *atom = cx->runtime->atomState.iteratorAtom;
if (!js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, vp))

View File

@ -83,7 +83,7 @@ JS_KEYWORD(super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
* implementation to ease code migration.
*/
#if JS_HAS_CONST
JS_KEYWORD(const, TOK_VAR, JSOP_DEFCONST, JSVERSION_DEFAULT)
JS_KEYWORD(const, TOK_CONST, JSOP_DEFCONST, JSVERSION_DEFAULT)
#else
JS_KEYWORD(const, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif

View File

@ -1780,10 +1780,10 @@ ASTSerializer::binop(ParseNodeKind kind, JSOp op)
return BINOP_STRICTEQ;
case PNK_STRICTNE:
return BINOP_STRICTNE;
case PNK_PLUS:
return BINOP_PLUS;
case PNK_MINUS:
return BINOP_MINUS;
case PNK_ADD:
return BINOP_ADD;
case PNK_SUB:
return BINOP_SUB;
case PNK_STAR:
return BINOP_STAR;
case PNK_DIV:
@ -1810,7 +1810,8 @@ ASTSerializer::binop(ParseNodeKind kind, JSOp op)
bool
ASTSerializer::statements(ParseNode *pn, NodeVector &elts)
{
JS_ASSERT(pn->isKind(PNK_LC) && pn->isArity(PN_LIST));
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
JS_ASSERT(pn->isArity(PN_LIST));
if (!elts.reserve(pn->pn_count))
return false;
@ -1860,7 +1861,7 @@ ASTSerializer::xmls(ParseNode *pn, NodeVector &elts)
bool
ASTSerializer::blockStatement(ParseNode *pn, Value *dst)
{
JS_ASSERT(pn->isKind(PNK_LC));
JS_ASSERT(pn->isKind(PNK_STATEMENTLIST));
NodeVector stmts(cx);
return statements(pn, stmts) &&
@ -1887,13 +1888,17 @@ ASTSerializer::sourceElement(ParseNode *pn, Value *dst)
bool
ASTSerializer::declaration(ParseNode *pn, Value *dst)
{
JS_ASSERT(pn->isKind(PNK_FUNCTION) || pn->isKind(PNK_VAR) || pn->isKind(PNK_LET));
JS_ASSERT(pn->isKind(PNK_FUNCTION) ||
pn->isKind(PNK_VAR) ||
pn->isKind(PNK_LET) ||
pn->isKind(PNK_CONST));
switch (pn->getKind()) {
case PNK_FUNCTION:
return function(pn, AST_FUNC_DECL, dst);
case PNK_VAR:
case PNK_CONST:
return variableDeclaration(pn, false, dst);
default:
@ -1905,7 +1910,7 @@ ASTSerializer::declaration(ParseNode *pn, Value *dst)
bool
ASTSerializer::variableDeclaration(ParseNode *pn, bool let, Value *dst)
{
JS_ASSERT(let ? pn->isKind(PNK_LET) : pn->isKind(PNK_VAR));
JS_ASSERT(let ? pn->isKind(PNK_LET) : (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST)));
/* Later updated to VARDECL_CONST if we find a PND_CONST declarator. */
VarDeclKind kind = let ? VARDECL_LET : VARDECL_VAR;
@ -2071,7 +2076,7 @@ ASTSerializer::forInit(ParseNode *pn, Value *dst)
return true;
}
return pn->isKind(PNK_VAR)
return (pn->isKind(PNK_VAR) || pn->isKind(PNK_CONST))
? variableDeclaration(pn, false, dst)
: pn->isKind(PNK_LET)
? variableDeclaration(pn, true, dst)
@ -2085,6 +2090,7 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
switch (pn->getKind()) {
case PNK_FUNCTION:
case PNK_VAR:
case PNK_CONST:
case PNK_LET:
return declaration(pn, dst);
@ -2111,11 +2117,11 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
builder.letStatement(dtors, stmt, &pn->pn_pos, dst);
}
if (!pn->isKind(PNK_LC))
if (!pn->isKind(PNK_STATEMENTLIST))
return statement(pn, dst);
/* FALL THROUGH */
case PNK_LC:
case PNK_STATEMENTLIST:
return blockStatement(pn, dst);
case PNK_IF:
@ -2146,7 +2152,7 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
: builder.whileStatement(expr, stmt, &pn->pn_pos, dst));
}
case PNK_DO:
case PNK_DOWHILE:
{
Value stmt, test;
@ -2165,7 +2171,7 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
bool isForEach = pn->pn_iflags & JSITER_FOREACH;
if (head->isKind(PNK_IN)) {
if (head->isKind(PNK_FORIN)) {
Value var, expr;
return (!head->pn_kid1
@ -2200,7 +2206,7 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
return false;
ParseNode *head = loop->pn_left;
JS_ASSERT(head->isKind(PNK_IN));
JS_ASSERT(head->isKind(PNK_FORIN));
bool isForEach = loop->pn_iflags & JSITER_FOREACH;
@ -2246,7 +2252,7 @@ ASTSerializer::statement(ParseNode *pn, Value *dst)
return builder.debuggerStatement(&pn->pn_pos, dst);
#if JS_HAS_XML_SUPPORT
case PNK_DEFAULT:
case PNK_DEFXMLNS:
{
LOCAL_ASSERT(pn->isArity(PN_UNARY));
@ -2306,7 +2312,7 @@ ASTSerializer::comprehensionBlock(ParseNode *pn, Value *dst)
ParseNode *in = pn->pn_left;
LOCAL_ASSERT(in && in->isKind(PNK_IN));
LOCAL_ASSERT(in && in->isKind(PNK_FORIN));
bool isForEach = pn->pn_iflags & JSITER_FOREACH;
@ -2337,7 +2343,7 @@ ASTSerializer::comprehension(ParseNode *pn, Value *dst)
if (!optExpression(next->pn_kid1, &filter))
return false;
next = next->pn_kid2;
} else if (next->isKind(PNK_LC) && next->pn_count == 0) {
} else if (next->isKind(PNK_STATEMENTLIST) && next->pn_count == 0) {
/* FoldConstants optimized away the push. */
NodeVector empty(cx);
return builder.arrayExpression(empty, &pn->pn_pos, dst);
@ -2454,11 +2460,8 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
builder.assignmentExpression(op, lhs, rhs, &pn->pn_pos, dst);
}
case PNK_PLUS:
case PNK_MINUS:
if (pn->isArity(PN_UNARY))
goto unary_plusminus;
/* FALL THROUGH */
case PNK_ADD:
case PNK_SUB:
case PNK_STRICTEQ:
case PNK_EQ:
case PNK_STRICTNE:
@ -2495,7 +2498,8 @@ ASTSerializer::expression(ParseNode *pn, Value *dst)
case PNK_VOID:
case PNK_NOT:
case PNK_BITNOT:
unary_plusminus: {
case PNK_POS:
case PNK_NEG: {
UnaryOperator op = unop(pn->getKind(), pn->getOp());
LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT);
@ -2716,7 +2720,7 @@ ASTSerializer::xml(ParseNode *pn, Value *dst)
JS_CHECK_RECURSION(cx, return false);
switch (pn->getKind()) {
#ifdef JS_HAS_XML_SUPPORT
case PNK_LC:
case PNK_XMLCURLYEXPR:
{
Value expr;
return expression(pn->pn_kid, &expr) &&
@ -3031,7 +3035,8 @@ ASTSerializer::functionArgsAndBody(ParseNode *pn, NodeVector &args, Value *body)
LOCAL_ASSERT(head && head->isKind(PNK_SEMI));
pndestruct = head->pn_kid;
LOCAL_ASSERT(pndestruct && pndestruct->isKind(PNK_VAR));
LOCAL_ASSERT(pndestruct);
LOCAL_ASSERT(pndestruct->isKind(PNK_VAR));
} else {
pndestruct = NULL;
}
@ -3051,7 +3056,7 @@ ASTSerializer::functionArgsAndBody(ParseNode *pn, NodeVector &args, Value *body)
expression(pnstart->pn_kid, body);
}
case PNK_LC: /* statement closure */
case PNK_STATEMENTLIST: /* statement closure */
{
ParseNode *pnstart = (pnbody->pn_xflags & PNX_DESTRUCT)
? pnbody->pn_head->pn_next

View File

@ -81,7 +81,7 @@ enum BinaryOperator {
/* shift */
BINOP_LSH, BINOP_RSH, BINOP_URSH,
/* arithmetic */
BINOP_PLUS, BINOP_MINUS, BINOP_STAR, BINOP_DIV, BINOP_MOD,
BINOP_ADD, BINOP_SUB, BINOP_STAR, BINOP_DIV, BINOP_MOD,
/* binary */
BINOP_BITOR, BINOP_BITXOR, BINOP_BITAND,
/* misc */

View File

@ -156,7 +156,6 @@ static jsdouble gTimeoutInterval = -1.0;
static volatile bool gCanceled = false;
static bool enableMethodJit = false;
static bool enableProfiling = false;
static bool enableTypeInference = false;
static bool enableDisassemblyDumps = false;
@ -613,8 +612,6 @@ static const struct JSOption {
uint32 flag;
} js_options[] = {
{"atline", JSOPTION_ATLINE},
{"jitprofiling", JSOPTION_PROFILING},
{"tracejit", JSOPTION_JIT},
{"methodjit", JSOPTION_METHODJIT},
{"methodjit_always",JSOPTION_METHODJIT_ALWAYS},
{"relimit", JSOPTION_RELIMIT},
@ -1071,7 +1068,7 @@ Now(JSContext *cx, uintN argc, jsval *vp)
}
static JSBool
Print(JSContext *cx, uintN argc, jsval *vp)
PrintInternal(JSContext *cx, uintN argc, jsval *vp, FILE *file)
{
jsval *argv;
uintN i;
@ -1086,17 +1083,29 @@ Print(JSContext *cx, uintN argc, jsval *vp)
bytes = JS_EncodeString(cx, str);
if (!bytes)
return JS_FALSE;
fprintf(gOutFile, "%s%s", i ? " " : "", bytes);
fprintf(file, "%s%s", i ? " " : "", bytes);
JS_free(cx, bytes);
}
fputc('\n', gOutFile);
fflush(gOutFile);
fputc('\n', file);
fflush(file);
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}
static JSBool
Print(JSContext *cx, uintN argc, jsval *vp)
{
return PrintInternal(cx, argc, vp, gOutFile);
}
static JSBool
PrintErr(JSContext *cx, uintN argc, jsval *vp)
{
return PrintInternal(cx, argc, vp, gErrFile);
}
static JSBool
Help(JSContext *cx, uintN argc, jsval *vp);
@ -3956,6 +3965,7 @@ static JSFunctionSpec shell_functions[] = {
JS_FN("run", Run, 1,0),
JS_FN("readline", ReadLine, 0,0),
JS_FN("print", Print, 0,0),
JS_FN("printErr", PrintErr, 0,0),
JS_FN("putstr", PutStr, 0,0),
JS_FN("dateNow", Now, 0,0),
JS_FN("help", Help, 0,0),
@ -4008,10 +4018,6 @@ static JSFunctionSpec shell_functions[] = {
JS_FN("evalInFrame", EvalInFrame, 2,0),
JS_FN("shapeOf", ShapeOf, 1,0),
JS_FN("resolver", Resolver, 1,0),
#ifdef MOZ_TRACEVIS
JS_FN("startTraceVis", StartTraceVisNative, 1,0),
JS_FN("stopTraceVis", StopTraceVisNative, 0,0),
#endif
#ifdef DEBUG
JS_FN("arrayInfo", js_ArrayInfo, 1,0),
#endif
@ -4054,7 +4060,8 @@ static const char *const shell_help_messages[] = {
" Run the file named by the first argument, returning the number of\n"
" of milliseconds spent compiling and executing it",
"readline() Read a single line from stdin",
"print([exp ...]) Evaluate and print expressions",
"print([exp ...]) Evaluate and print expressions to stdout",
"printErr([exp ...]) Evaluate and print expressions to stderr",
"putstr([exp]) Evaluate and print expression without newline",
"dateNow() Return the current time with sub-ms precision",
"help([name ...]) Display usage and help messages",
@ -4134,10 +4141,6 @@ static const char *const shell_help_messages[] = {
"shapeOf(obj) Get the shape of obj (an implementation detail)",
"resolver(src[, proto]) Create object with resolve hook that copies properties\n"
" from src. If proto is omitted, use Object.prototype.",
#ifdef MOZ_TRACEVIS
"startTraceVis(filename) Start TraceVis recording (stops any current recording)",
"stopTraceVis() Stop TraceVis recording",
#endif
#ifdef DEBUG
"arrayInfo(a1, a2, ...) Report statistics about arrays",
#endif
@ -5062,11 +5065,6 @@ ProcessArgs(JSContext *cx, JSObject *obj, OptionParser *op)
ParseZealArg(cx, zeal);
#endif
if (op->getBoolOption('p')) {
enableProfiling = true;
JS_ToggleOptions(cx, JSOPTION_PROFILING);
}
if (op->getBoolOption('d')) {
JS_SetRuntimeDebugMode(JS_GetRuntime(cx), true);
JS_SetDebugMode(cx, true);
@ -5322,14 +5320,10 @@ main(int argc, char **argv, char **envp)
|| !op.addMultiStringOption('e', "execute", "CODE", "Inline code to run")
|| !op.addBoolOption('i', "shell", "Enter prompt after running code")
|| !op.addBoolOption('m', "methodjit", "Enable the JaegerMonkey method JIT")
|| !op.addBoolOption('j', "tracejit", "Deprecated; does nothing")
|| !op.addBoolOption('p', "profiling", "Enable runtime profiling select JIT mode")
|| !op.addBoolOption('n', "typeinfer", "Enable type inference")
|| !op.addBoolOption('d', "debugjit", "Enable runtime debug mode for method JIT code")
|| !op.addBoolOption('a', "always-mjit",
"Do not try to run in the interpreter before "
"method jitting. Note that this has no particular effect on the "
"tracer; it still kicks in if enabled.")
"Do not try to run in the interpreter before method jitting.")
|| !op.addBoolOption('D', "dump-bytecode", "Dump bytecode with exec count for all scripts")
|| !op.addBoolOption('b', "print-timing", "Print sub-ms runtime for each file that's run")
#ifdef DEBUG

View File

@ -224,7 +224,6 @@ function optionsInit() {
xml: true,
relimit: true,
methodjit: true,
jitprofiling: true,
methodjit_always: true
};

View File

@ -167,7 +167,7 @@ skip-if(xulRuntime.OS=="WINNT"&&isDebugBuild) slow script regress-341360.js
script regress-343713.js
script regress-343966.js
script regress-344711-n.js
skip script regress-344804.js # bug 524732
script regress-344804.js
script regress-344959.js
script regress-346237.js
script regress-346801.js

View File

@ -1,6 +1,6 @@
url-prefix ../../jsreftest.html?test=js1_5/Scope/
script regress-154693.js
skip script regress-181834.js # bug 524732
script regress-181834.js
script regress-184107.js
script regress-185485.js
script regress-191276.js

View File

@ -649,7 +649,6 @@ function optionsClear() {
var optionName = optionNames[i];
if (optionName &&
optionName != "methodjit" &&
optionName != "jitprofiling" &&
optionName != "methodjit_always")
{
options(optionName);

View File

@ -30,8 +30,6 @@ user_pref("extensions.checkUpdateSecurity", false);
user_pref("browser.EULA.override", true);
user_pref("javascript.options.methodjit.chrome", true);
user_pref("javascript.options.methodjit.content", true);
user_pref("javascript.options.jitprofiling.chrome", true);
user_pref("javascript.options.jitprofiling.content", true);
user_pref("javascript.options.methodjit_always", false);
user_pref("javascript.options.strict", false);
user_pref("javascript.options.werror", false);

View File

@ -392,7 +392,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%}
[uuid(29b63029-0868-4344-b0ca-d93256ee7c78)]
[uuid(07661008-5505-4784-a612-89f7dc2144da)]
interface nsIXPConnect : nsISupports
{
%{ C++
@ -735,7 +735,7 @@ interface nsIXPConnect : nsISupports
/**
* Trigger a JS garbage collection.
*/
void GarbageCollect();
void GarbageCollect(in boolean shrinkingGC);
/**
* Define quick stubs on the given object, @a proto.

View File

@ -153,7 +153,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(11785c1f-346f-475c-950e-fe1bacce70f1)]
[scriptable, uuid(d6916b9e-0947-400f-8552-81fd96312c9d)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -324,7 +324,6 @@ interface nsIXPCComponents_Utils : nsISupports
attribute boolean xml;
attribute boolean relimit;
attribute boolean methodjit;
attribute boolean jitprofiling;
attribute boolean methodjit_always;
[implicit_jscontext]
void setGCZeal(in long zeal);

View File

@ -298,10 +298,6 @@ static JSFunctionSpec gGlobalFun[] = {
{"atob", Atob, 1,0},
{"btoa", Btoa, 1,0},
{"File", File, 1,JSFUN_CONSTRUCTOR},
#ifdef MOZ_TRACEVIS
{"initEthogram", js_InitEthogram, 0,0},
{"shutdownEthogram", js_ShutdownEthogram, 0,0},
#endif
{nsnull,nsnull,0,0}
};

View File

@ -726,7 +726,6 @@ static const struct JSOption {
uint32 flag;
} js_options[] = {
{"atline", JSOPTION_ATLINE},
{"jit", JSOPTION_JIT},
{"relimit", JSOPTION_RELIMIT},
{"strict", JSOPTION_STRICT},
{"werror", JSOPTION_WERROR},
@ -1283,15 +1282,9 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
compileOnly = true;
isInteractive = false;
break;
case 'j':
JS_ToggleOptions(cx, JSOPTION_JIT);
break;
case 'm':
JS_ToggleOptions(cx, JSOPTION_METHODJIT);
break;
case 'p':
JS_ToggleOptions(cx, JSOPTION_PROFILING);
break;
case 'n':
JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
break;

View File

@ -56,8 +56,8 @@
#include "nsJSUtils.h"
#include "mozJSComponentLoader.h"
#include "nsContentUtils.h"
#include "jsgc.h"
#include "jsgc.h"
using namespace js;
/***************************************************************************/
// stuff used by all
@ -3102,13 +3102,13 @@ xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSOb
JSCompartment *compartment;
JSObject *sandbox;
nsRefPtr<Identity> identity;
if (!identityPtr) {
identity = new Identity();
identityPtr = identity;
}
rv = xpc_CreateGlobalObject(cx, &SandboxClass, principal, identityPtr,
nsRefPtr<Identity> identity;
if (!identityPtr) {
identity = new Identity();
identityPtr = identity;
}
rv = xpc_CreateGlobalObject(cx, &SandboxClass, principal, identityPtr,
wantXrays, &sandbox, &compartment);
NS_ENSURE_SUCCESS(rv, rv);
@ -3324,25 +3324,25 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
sandboxName.Adopt(tmp, strlen(tmp));
}
// see Bug 677294:
if (!JS_HasProperty(cx, optionsObject, "sameGroupAs", &found))
return NS_ERROR_INVALID_ARG;
if (found) {
if (!JS_GetProperty(cx, optionsObject, "sameGroupAs", &option) ||
JSVAL_IS_PRIMITIVE(option)) {
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
}
void* privateValue =
JS_GetCompartmentPrivate(cx,GetObjectCompartment(JSVAL_TO_OBJECT(option)));
xpc::CompartmentPrivate *compartmentPrivate =
static_cast<xpc::CompartmentPrivate*>(privateValue);
if (!compartmentPrivate || !compartmentPrivate->key)
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
identity = compartmentPrivate->key->GetPtr();
// see Bug 677294:
if (!JS_HasProperty(cx, optionsObject, "sameGroupAs", &found))
return NS_ERROR_INVALID_ARG;
if (found) {
if (!JS_GetProperty(cx, optionsObject, "sameGroupAs", &option) ||
JSVAL_IS_PRIMITIVE(option)) {
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
}
void* privateValue =
JS_GetCompartmentPrivate(cx,GetObjectCompartment(JSVAL_TO_OBJECT(option)));
xpc::CompartmentPrivate *compartmentPrivate =
static_cast<xpc::CompartmentPrivate*>(privateValue);
if (!compartmentPrivate || !compartmentPrivate->key)
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
identity = compartmentPrivate->key->GetPtr();
}
}
@ -4070,7 +4070,6 @@ GENERATE_JSOPTION_GETTER_SETTER(Atline, JSOPTION_ATLINE)
GENERATE_JSOPTION_GETTER_SETTER(Xml, JSOPTION_XML)
GENERATE_JSOPTION_GETTER_SETTER(Relimit, JSOPTION_RELIMIT)
GENERATE_JSOPTION_GETTER_SETTER(Methodjit, JSOPTION_METHODJIT)
GENERATE_JSOPTION_GETTER_SETTER(Jitprofiling, JSOPTION_PROFILING)
GENERATE_JSOPTION_GETTER_SETTER(Methodjit_always, JSOPTION_METHODJIT_ALWAYS)
#undef GENERATE_JSOPTION_GETTER_SETTER

View File

@ -343,7 +343,7 @@ nsXPConnect::NeedCollect()
}
void
nsXPConnect::Collect()
nsXPConnect::Collect(bool shrinkingGC)
{
// We're dividing JS objects into 2 categories:
//
@ -406,15 +406,18 @@ nsXPConnect::Collect()
JS_ASSERT(!threadData.conservativeGC.requestThreshold);
if (threadData.requestDepth == 1)
threadData.conservativeGC.requestThreshold = 1;
JS_GC(cx);
if (shrinkingGC)
JS_ShrinkingGC(cx);
else
JS_GC(cx);
if (threadData.requestDepth == 1)
threadData.conservativeGC.requestThreshold = 0;
}
NS_IMETHODIMP
nsXPConnect::GarbageCollect()
nsXPConnect::GarbageCollect(bool shrinkingGC)
{
Collect();
Collect(shrinkingGC);
return NS_OK;
}

View File

@ -566,7 +566,7 @@ public:
virtual nsresult FinishCycleCollection();
virtual nsCycleCollectionParticipant *ToParticipant(void *p);
virtual bool NeedCollect();
virtual void Collect();
virtual void Collect(bool shrinkingGC=false);
#ifdef DEBUG_CC
virtual void PrintAllReferencesTo(void *p);
#endif

View File

@ -100,7 +100,7 @@ nsRefreshDriver::GetRefreshTimerType() const
if (mThrottled) {
return nsITimer::TYPE_ONE_SHOT;
}
if (HaveAnimationFrameListeners() || sPrecisePref) {
if (HaveFrameRequestCallbacks() || sPrecisePref) {
return nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP;
}
return nsITimer::TYPE_REPEATING_SLACK;
@ -269,8 +269,7 @@ nsRefreshDriver::ObserverCount() const
// style changes, etc.
sum += mStyleFlushObservers.Length();
sum += mLayoutFlushObservers.Length();
sum += mBeforePaintTargets.Length();
sum += mAnimationFrameListenerDocs.Length();
sum += mFrameRequestCallbackDocs.Length();
return sum;
}
@ -365,34 +364,19 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
}
if (i == 0) {
// Don't just loop while we have things in mBeforePaintTargets,
// the whole point is that event handlers should readd the
// target as needed.
nsTArray< nsCOMPtr<nsIDocument> > targets;
targets.SwapElements(mBeforePaintTargets);
for (PRUint32 i = 0; i < targets.Length(); ++i) {
targets[i]->BeforePaintEventFiring();
// Grab all of our frame request callbacks up front.
nsIDocument::FrameRequestCallbackList frameRequestCallbacks;
for (PRUint32 i = 0; i < mFrameRequestCallbackDocs.Length(); ++i) {
mFrameRequestCallbackDocs[i]->
TakeFrameRequestCallbacks(frameRequestCallbacks);
}
// Also grab all of our animation frame listeners up front.
nsIDocument::AnimationListenerList animationListeners;
for (PRUint32 i = 0; i < mAnimationFrameListenerDocs.Length(); ++i) {
mAnimationFrameListenerDocs[i]->
TakeAnimationFrameListeners(animationListeners);
}
// OK, now reset mAnimationFrameListenerDocs so they can be
// OK, now reset mFrameRequestCallbackDocs so they can be
// readded as needed.
mAnimationFrameListenerDocs.Clear();
mFrameRequestCallbackDocs.Clear();
PRInt64 eventTime = mMostRecentRefreshEpochTime / PR_USEC_PER_MSEC;
for (PRUint32 i = 0; i < targets.Length(); ++i) {
nsEvent ev(true, NS_BEFOREPAINT);
ev.time = eventTime;
nsEventDispatcher::Dispatch(targets[i], nsnull, &ev);
}
for (PRUint32 i = 0; i < animationListeners.Length(); ++i) {
animationListeners[i]->OnBeforePaint(eventTime);
for (PRUint32 i = 0; i < frameRequestCallbacks.Length(); ++i) {
frameRequestCallbacks[i]->Sample(eventTime);
}
// This is the Flush_Style case.
@ -541,39 +525,22 @@ nsRefreshDriver::IsRefreshObserver(nsARefreshObserver *aObserver,
}
#endif
bool
nsRefreshDriver::ScheduleBeforePaintEvent(nsIDocument* aDocument)
{
NS_ASSERTION(mBeforePaintTargets.IndexOf(aDocument) ==
mBeforePaintTargets.NoIndex,
"Shouldn't have a paint event posted for this document");
bool appended = mBeforePaintTargets.AppendElement(aDocument) != nsnull;
EnsureTimerStarted(false);
return appended;
}
void
nsRefreshDriver::ScheduleAnimationFrameListeners(nsIDocument* aDocument)
nsRefreshDriver::ScheduleFrameRequestCallbacks(nsIDocument* aDocument)
{
NS_ASSERTION(mAnimationFrameListenerDocs.IndexOf(aDocument) ==
mAnimationFrameListenerDocs.NoIndex,
NS_ASSERTION(mFrameRequestCallbackDocs.IndexOf(aDocument) ==
mFrameRequestCallbackDocs.NoIndex,
"Don't schedule the same document multiple times");
mAnimationFrameListenerDocs.AppendElement(aDocument);
mFrameRequestCallbackDocs.AppendElement(aDocument);
// No need to worry about restarting our timer in precise mode if it's
// already running; that will happen automatically when it fires.
EnsureTimerStarted(false);
}
void
nsRefreshDriver::RevokeBeforePaintEvent(nsIDocument* aDocument)
nsRefreshDriver::RevokeFrameRequestCallbacks(nsIDocument* aDocument)
{
mBeforePaintTargets.RemoveElement(aDocument);
}
void
nsRefreshDriver::RevokeAnimationFrameListeners(nsIDocument* aDocument)
{
mAnimationFrameListenerDocs.RemoveElement(aDocument);
mFrameRequestCallbackDocs.RemoveElement(aDocument);
// No need to worry about restarting our timer in slack mode if it's already
// running; that will happen automatically when it fires.
}

View File

@ -177,24 +177,14 @@ public:
}
/**
* Add a document for which we should fire a MozBeforePaint event.
* Add a document for which we have nsIFrameRequestCallbacks
*/
bool ScheduleBeforePaintEvent(nsIDocument* aDocument);
void ScheduleFrameRequestCallbacks(nsIDocument* aDocument);
/**
* Add a document for which we have nsIAnimationFrameListeners
* Remove a document for which we have nsIFrameRequestCallbacks
*/
void ScheduleAnimationFrameListeners(nsIDocument* aDocument);
/**
* Remove a document for which we should fire a MozBeforePaint event.
*/
void RevokeBeforePaintEvent(nsIDocument* aDocument);
/**
* Remove a document for which we have nsIAnimationFrameListeners
*/
void RevokeAnimationFrameListeners(nsIDocument* aDocument);
void RevokeFrameRequestCallbacks(nsIDocument* aDocument);
/**
* Tell the refresh driver that it is done driving refreshes and
@ -256,8 +246,8 @@ private:
PRInt32 GetRefreshTimerInterval() const;
PRInt32 GetRefreshTimerType() const;
bool HaveAnimationFrameListeners() const {
return mAnimationFrameListenerDocs.Length() != 0;
bool HaveFrameRequestCallbacks() const {
return mFrameRequestCallbackDocs.Length() != 0;
}
nsCOMPtr<nsITimer> mTimer;
@ -283,9 +273,7 @@ private:
nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
// nsTArray on purpose, because we want to be able to swap.
nsTArray< nsCOMPtr<nsIDocument> > mBeforePaintTargets;
// nsTArray on purpose, because we want to be able to swap.
nsTArray<nsIDocument*> mAnimationFrameListenerDocs;
nsTArray<nsIDocument*> mFrameRequestCallbackDocs;
// This is the last interval we used for our timer. May be 0 if we
// haven't computed a timer interval yet.

View File

@ -7,15 +7,6 @@
var report = false;
function f() {
if (report) {
opener.postMessage("eventHappened", "*");
}
window.mozRequestAnimationFrame();
}
document.addEventListener("MozBeforePaint", f, false);
f();
function g() {
if (report) {
opener.postMessage("callbackHappened", "*");

View File

@ -25,9 +25,8 @@ var start = window.mozAnimationStartTime;
var firstListenerTime;
var secondListenerTime;
function secondListener(ev) {
secondListenerTime = ev.timeStamp;
window.removeEventListener("MozBeforePaint", secondListener, false);
function secondListener(t) {
secondListenerTime = t;
// They really shouldn't be more than 100ms apart, but we can get weird
// effects on slow machines. 5 minutes is our test timeout, though.
@ -40,17 +39,14 @@ function secondListener(ev) {
SimpleTest.finish();
}
function firstListener(ev) {
firstListenerTime = ev.timeStamp;
window.removeEventListener("MozBeforePaint", firstListener, false);
window.addEventListener("MozBeforePaint", secondListener, false);
mozRequestAnimationFrame();
function firstListener(t) {
firstListenerTime = t;
mozRequestAnimationFrame(secondListener);
}
addLoadEvent(function() {
setTimeout(function() {
window.addEventListener("MozBeforePaint", firstListener, false);
mozRequestAnimationFrame();
mozRequestAnimationFrame(firstListener);
}, 100);
});

View File

@ -24,16 +24,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607529
var doneOneLoad = false;
var eventsHappening = false;
var callbacksHappening = false;
function tryFinishTest() {
if (eventsHappening && callbacksHappening) {
w.close();
SimpleTest.finish();
}
}
/** Test for Bug 607529 **/
window.onmessage = function(e) {
isnot(e.data, "notcached", "Should never end up not being cached");
@ -48,13 +38,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=607529
else if (e.data == "revived") {
w.postMessage("report", "*");
}
else if (e.data == "eventHappened") {
eventsHappening = true;
tryFinishTest();
}
else if (e.data == "callbackHappened") {
callbacksHappening = true;
tryFinishTest();
w.close();
SimpleTest.finish();
} else {
var msg = JSON.parse(e.data);
if (msg.error) {

View File

@ -137,32 +137,25 @@ nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
ENSURE_TRUE(mContent);
// Remove the drag events
nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
if (dragTarget) {
dragTarget->RemoveEventListener(NS_LITERAL_STRING("drop"),
mMouseListener, false);
dragTarget->RemoveEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, false);
if (mContent) {
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("drop"),
mMouseListener, false);
mContent->RemoveSystemEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, false);
}
// remove mMouseListener as a mouse event listener (bug 40533, bug 355931)
NS_NAMED_LITERAL_STRING(click, "click");
nsContentUtils::DestroyAnonymousContent(&mCapture);
nsEventListenerManager* elm = mBrowse->GetListenerManager(false);
if (elm) {
elm->RemoveEventListenerByType(mMouseListener, click,
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
if (mBrowse) {
mBrowse->RemoveSystemEventListener(NS_LITERAL_STRING("click"),
mMouseListener, false);
}
nsContentUtils::DestroyAnonymousContent(&mBrowse);
elm = mTextContent->GetListenerManager(false);
if (elm) {
elm->RemoveEventListenerByType(mMouseListener, click,
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
if (mTextContent) {
mTextContent->RemoveSystemEventListener(NS_LITERAL_STRING("click"),
mMouseListener, false);
}
nsContentUtils::DestroyAnonymousContent(&mTextContent);
@ -265,21 +258,15 @@ nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
return NS_ERROR_OUT_OF_MEMORY;
// Register the whole frame as an event listener of drag events
nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
NS_ENSURE_STATE(dragTarget);
dragTarget->AddEventListener(NS_LITERAL_STRING("drop"),
mMouseListener, false);
dragTarget->AddEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, false);
mContent->AddSystemEventListener(NS_LITERAL_STRING("drop"),
mMouseListener, false);
mContent->AddSystemEventListener(NS_LITERAL_STRING("dragover"),
mMouseListener, false);
NS_NAMED_LITERAL_STRING(click, "click");
nsEventListenerManager* manager = mTextContent->GetListenerManager(true);
NS_ENSURE_STATE(manager);
// Register as an event listener of the textbox
// to open file dialog on mouse click
manager->AddEventListenerByType(mMouseListener, click,
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
mTextContent->AddSystemEventListener(NS_LITERAL_STRING("click"),
mMouseListener, false);
// Create the browse button
nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::input, nsnull,
@ -326,9 +313,8 @@ nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
mCapture->SetAttr(kNameSpaceID_None, nsGkAtoms::value,
NS_LITERAL_STRING("capture"), false);
nsCOMPtr<nsIDOMEventTarget> captureEventTarget =
do_QueryInterface(mCapture);
captureEventTarget->AddEventListener(click, mCaptureMouseListener, false);
mCapture->AddSystemEventListener(NS_LITERAL_STRING("click"),
mCaptureMouseListener, false);
}
}
nsCOMPtr<nsIDOMHTMLInputElement> fileContent = do_QueryInterface(mContent);
@ -349,15 +335,10 @@ nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
if (mCapture && !aElements.AppendElement(mCapture))
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mBrowse);
NS_ENSURE_STATE(target);
manager = target->GetListenerManager(true);
NS_ENSURE_STATE(manager);
// Register as an event listener of the button
// to open file dialog on mouse click
manager->AddEventListenerByType(mMouseListener, click,
NS_EVENT_FLAG_BUBBLE |
NS_EVENT_FLAG_SYSTEM_EVENT);
mBrowse->AddSystemEventListener(NS_LITERAL_STRING("click"),
mMouseListener, false);
SyncAttr(kNameSpaceID_None, nsGkAtoms::size, SYNC_TEXT);
SyncDisabledState();

View File

@ -88,6 +88,10 @@ function startAnimatedScrollBy(dx, dy) {
var sentScrollBy = false;
function nudgeScroll(now) {
if (!scrolling) {
// we've been canceled
return;
}
var ddx = dx * (now - prevNow) / kDurationMs;
var ddy = dy * (now - prevNow) / kDurationMs;
@ -110,18 +114,14 @@ function startAnimatedScrollBy(dx, dy) {
rootView().scrollBy(fixupDx, fixupDy);
scrolling = false;
removeEventListener("MozBeforePaint", nudgeScroll, false);
}
else {
mozRequestAnimationFrame();
mozRequestAnimationFrame(nudgeScroll);
}
prevNow = now;
}
nudgeScroll(start);
addEventListener("MozBeforePaint",
function (e) { nudgeScroll(e.timeStamp); },
false);
mozRequestAnimationFrame();
mozRequestAnimationFrame(nudgeScroll);
}

View File

@ -134,7 +134,7 @@ nsPrintData::~nsPrintData()
void nsPrintData::OnStartPrinting()
{
if (!mOnStartSent) {
DoOnProgressChange(0, 0, true, nsIWebProgressListener::STATE_START|nsIWebProgressListener::STATE_IS_DOCUMENT);
DoOnProgressChange(0, 0, true, nsIWebProgressListener::STATE_START|nsIWebProgressListener::STATE_IS_DOCUMENT|nsIWebProgressListener::STATE_IS_NETWORK);
mOnStartSent = true;
}
}
@ -142,19 +142,18 @@ void nsPrintData::OnStartPrinting()
void nsPrintData::OnEndPrinting()
{
DoOnProgressChange(100, 100, true, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT);
DoOnProgressChange(100, 100, true, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_NETWORK);
}
void
nsPrintData::DoOnProgressChange(PRInt32 aProgess,
nsPrintData::DoOnProgressChange(PRInt32 aProgress,
PRInt32 aMaxProgress,
bool aDoStartStop,
PRInt32 aFlag)
{
if (aProgess == 0) return;
for (PRInt32 i=0;i<mPrintProgressListeners.Count();i++) {
nsIWebProgressListener* wpl = mPrintProgressListeners.ObjectAt(i);
wpl->OnProgressChange(nsnull, nsnull, aProgess, aMaxProgress, aProgess, aMaxProgress);
wpl->OnProgressChange(nsnull, nsnull, aProgress, aMaxProgress, aProgress, aMaxProgress);
if (aDoStartStop) {
wpl->OnStateChange(nsnull, nsnull, aFlag, 0);
}

View File

@ -85,7 +85,7 @@ public:
// Listener Helper Methods
void OnEndPrinting();
void OnStartPrinting();
void DoOnProgressChange(PRInt32 aProgess,
void DoOnProgressChange(PRInt32 aProgress,
PRInt32 aMaxProgress,
bool aDoStartStop,
PRInt32 aFlag);

View File

@ -1,38 +1,43 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="grad">
<stop offset="5%" stop-color="#F66"/>
<stop offset="95%" stop-color="#FF6"/>
</linearGradient>
<circle fill="url(#grad)" stroke="black" stroke-width="1" cx="0" cy="0"
r="20" id="circle"/>
<g id="smiley">
<circle fill="yellow" stroke="black" stroke-width="1" cx="0" cy="0"
r="20"/>
<circle fill="white" stroke="black" stroke-width="1" cx="-7" cy="-7"
r="7"/>
<circle fill="white" stroke="black" stroke-width="1" cx="7" cy="-7"
r="7"/>
<circle cx="-5" cy="-7" r="2"/>
<circle cx="5" cy="-7" r="2"/>
<path d="m-11 7a13,13 0 0,0 22,0" fill="none" stroke="black"/>
</g>
</defs>
<g transform="translate(50 50)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(150 50)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(250 50)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(50 150)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(150 150)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(250 150)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(50 250)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(150 250)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
<g transform="translate(250 250)">
<use xlink:href="#circle" transform="scale(2)"/>
<use xlink:href="#smiley" transform="scale(2)"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -4,12 +4,17 @@
onload="setTimeAndSnapshot(1, true)">
<script xlink:href="../smil-util.js" type="text/javascript"/>
<defs>
<linearGradient id="grad">
<stop offset="5%" stop-color="#F66"/>
<stop offset="95%" stop-color="#FF6"/>
</linearGradient>
<circle fill="url(#grad)" stroke="black" stroke-width="1" cx="0" cy="0"
r="20" id="circle"/>
<g id="smiley">
<circle fill="yellow" stroke="black" stroke-width="1" cx="0" cy="0"
r="20"/>
<circle fill="white" stroke="black" stroke-width="1" cx="-7" cy="-7"
r="7"/>
<circle fill="white" stroke="black" stroke-width="1" cx="7" cy="-7"
r="7"/>
<circle cx="-5" cy="-7" r="2"/>
<circle cx="5" cy="-7" r="2"/>
<path d="m-11 7a13,13 0 0,0 22,0" fill="none" stroke="black"/>
</g>
</defs>
<!-- to animation
@ -17,14 +22,14 @@
required by the SVGT1.2 test suite and Opera's behaviour.
-->
<g transform="translate(50 50)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform"
type="scale" to="4" dur="2s" fill="freeze"/>
</use>
</g>
<!-- from-to animation -->
<g transform="translate(150 50)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform"
type="scale" from="-5" to="9" dur="2s" fill="freeze"/>
</use>
@ -35,7 +40,7 @@
should be -2, so we add a rotation animation to correct the gradient
-->
<g transform="translate(250 50)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform"
type="scale" to="-4" dur="2s" fill="freeze"/>
<animateTransform attributeName="transform"
@ -63,35 +68,35 @@
scale factor should be 2.
-->
<g transform="translate(50 150)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform"
type="scale" by="4" dur="2s" fill="freeze"/>
</use>
</g>
<!-- by animation #2 -->
<g transform="translate(150 150)">
<use xlink:href="#circle" transform="scale(4)">
<use xlink:href="#smiley" transform="scale(4)">
<animateTransform attributeName="transform"
type="scale" by="1" dur="2s" fill="freeze" additive="sum"/>
</use>
</g>
<!-- from-by animation -->
<g transform="translate(250 150)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform"
type="scale" from="2" by="0" dur="2s" fill="freeze"/>
</use>
</g>
<!-- values animation -->
<g transform="translate(50 250)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform"
type="scale" values="0; 10; 2; 5; -1" dur="2s" fill="freeze"/>
</use>
</g>
<!-- repetition -->
<g transform="translate(150 250)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform" type="scale" from="0"
to="0.6" dur="0.3s" repeatCount="4" accumulate="sum"
fill="freeze"/>
@ -99,7 +104,7 @@
</g>
<!-- repeated to-animation (should NOT accumulate) -->
<g transform="translate(250 250)">
<use xlink:href="#circle">
<use xlink:href="#smiley">
<animateTransform attributeName="transform" type="scale"
to="6" dur="0.75" repeatCount="2" accumulate="sum"
fill="freeze"/>

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -155,9 +155,17 @@ function iframe_loaded(event)
if (!("backend_only" in info)) {
var end_compute = get_computed_value(test_cs[idx], current_item.prop);
is(end_compute, start_compute[idx],
"computed values should match when cloning " +
current_item.prop + ": " + current_item.value);
// Output computed values only when the test failed.
// Computed values may be very long.
if (end_compute == start_compute[idx]) {
ok(true,
"computed values should match when cloning " +
current_item.prop + ": " + current_item.value);
} else {
is(end_compute, start_compute[idx],
"computed values should match when cloning " +
current_item.prop + ": " + current_item.value);
}
}
}

View File

@ -305,11 +305,13 @@ nsXULTooltipListener::AddTooltipSupport(nsIContent* aNode)
if (!aNode)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
evtTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false);
evtTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this, false);
evtTarget->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true);
aNode->AddSystemEventListener(NS_LITERAL_STRING("mouseout"), this,
false, false);
aNode->AddSystemEventListener(NS_LITERAL_STRING("mousemove"), this,
false, false);
aNode->AddSystemEventListener(NS_LITERAL_STRING("dragstart"), this,
true, false);
return NS_OK;
}
@ -319,10 +321,9 @@ nsXULTooltipListener::RemoveTooltipSupport(nsIContent* aNode)
if (!aNode)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(aNode));
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, false);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, true);
aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mouseout"), this, false);
aNode->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"), this, false);
aNode->RemoveSystemEventListener(NS_LITERAL_STRING("dragstart"), this, true);
return NS_OK;
}
@ -417,21 +418,24 @@ nsXULTooltipListener::ShowTooltip()
// listen for popuphidden on the tooltip node, so that we can
// be sure DestroyPopup is called even if someone else closes the tooltip
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(currentTooltip));
evtTarget->AddEventListener(NS_LITERAL_STRING("popuphiding"),
this, false);
currentTooltip->AddSystemEventListener(NS_LITERAL_STRING("popuphiding"),
this, false, false);
// listen for mousedown, mouseup, keydown, and DOMMouseScroll events at document level
nsIDocument* doc = sourceNode->GetDocument();
if (doc) {
evtTarget = do_QueryInterface(doc);
evtTarget->AddEventListener(NS_LITERAL_STRING("DOMMouseScroll"),
// Probably, we should listen to untrusted events for hiding tooltips
// on content since tooltips might disturb something of web
// applications. If we don't specify the aWantsUntrusted of
// AddSystemEventListener(), the event target sets it to TRUE if the
// target is in content.
doc->AddSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"),
this, true);
evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
doc->AddSystemEventListener(NS_LITERAL_STRING("mousedown"),
this, true);
evtTarget->AddEventListener(NS_LITERAL_STRING("mouseup"),
this, true);
evtTarget->AddEventListener(NS_LITERAL_STRING("keydown"),
doc->AddSystemEventListener(NS_LITERAL_STRING("mouseup"),
this, true);
doc->AddSystemEventListener(NS_LITERAL_STRING("keydown"),
this, true);
}
mSourceNode = nsnull;
@ -660,11 +664,12 @@ nsXULTooltipListener::DestroyTooltip()
nsCOMPtr<nsIDocument> doc = currentTooltip->GetDocument();
if (doc) {
// remove the mousedown and keydown listener from document
nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(doc));
evtTarget->RemoveEventListener(NS_LITERAL_STRING("DOMMouseScroll"), this, true);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, true);
evtTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
doc->RemoveSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"), this,
true);
doc->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), this,
true);
doc->RemoveSystemEventListener(NS_LITERAL_STRING("mouseup"), this, true);
doc->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), this, true);
}
// remove the popuphidden listener from tooltip

View File

@ -1,64 +0,0 @@
/* ***** 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.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Hyatt <hyatt@mozilla.org> (Original Author)
* Jan Varga <varga@ku.sk>
* Scott Johnson <sjohnson@mozilla.com>, Mozilla Corporation
*
* 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 nsITreeImageListener_h__
#define nsITreeImageListener_h__
// The interface for our image listener.
// {90586540-2D50-403e-8DCE-981CAA778444}
#define NS_ITREEIMAGELISTENER_IID \
{ 0x90586540, 0x2d50, 0x403e, { 0x8d, 0xce, 0x98, 0x1c, 0xaa, 0x77, 0x84, 0x44 } }
class nsITreeImageListener : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITREEIMAGELISTENER_IID)
NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol) = 0;
/**
* Clear the internal frame pointer to prevent dereferencing an object
* that no longer exists.
*/
NS_IMETHOD ClearFrame() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsITreeImageListener, NS_ITREEIMAGELISTENER_IID)
#endif

View File

@ -2157,9 +2157,11 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIndex, nsTreeColumn* aCol, bool aUseContex
// We either aren't done loading, or we're animating. Add our row as a listener for invalidations.
nsCOMPtr<imgIDecoderObserver> obs;
imgReq->GetDecoderObserver(getter_AddRefs(obs));
nsCOMPtr<nsITreeImageListener> listener(do_QueryInterface(obs));
if (listener)
listener->AddCell(aRowIndex, aCol);
if (obs) {
static_cast<nsTreeImageListener*> (obs.get())->AddCell(aRowIndex, aCol);
}
return NS_OK;
}
}

View File

@ -63,7 +63,6 @@
#include "nsScrollbarFrame.h"
#include "nsThreadUtils.h"
#include "mozilla/LookAndFeel.h"
#include "nsITreeImageListener.h"
class nsOverflowChecker;
class nsTreeImageListener;

View File

@ -42,7 +42,7 @@
#include "imgIRequest.h"
#include "imgIContainer.h"
NS_IMPL_ISUPPORTS3(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver, nsITreeImageListener)
NS_IMPL_ISUPPORTS2(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver)
nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame)
: mTreeFrame(aTreeFrame),
@ -92,7 +92,7 @@ NS_IMETHODIMP nsTreeImageListener::FrameChanged(imgIContainer *aContainer,
}
NS_IMETHODIMP
void
nsTreeImageListener::AddCell(PRInt32 aIndex, nsITreeColumn* aCol)
{
if (!mInvalidationArea) {
@ -114,8 +114,6 @@ nsTreeImageListener::AddCell(PRInt32 aIndex, nsITreeColumn* aCol)
mInvalidationArea->AddRow(aIndex);
}
}
return NS_OK;
}

View File

@ -45,10 +45,9 @@
#include "nsITreeColumns.h"
#include "nsStubImageDecoderObserver.h"
#include "nsTreeBodyFrame.h"
#include "nsITreeImageListener.h"
// This class handles image load observation.
class nsTreeImageListener : public nsStubImageDecoderObserver, public nsITreeImageListener
class nsTreeImageListener : public nsStubImageDecoderObserver
{
public:
nsTreeImageListener(nsTreeBodyFrame *aTreeFrame);
@ -64,7 +63,6 @@ public:
NS_IMETHOD FrameChanged(imgIContainer *aContainer,
const nsIntRect *aDirtyRect);
NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol);
NS_IMETHOD ClearFrame();
friend class nsTreeBodyFrame;
@ -72,6 +70,7 @@ public:
protected:
void UnsuppressInvalidation() { mInvalidationSuppressed = false; }
void Invalidate();
void AddCell(PRInt32 aIndex, nsITreeColumn* aCol);
private:
nsTreeBodyFrame* mTreeFrame;

View File

@ -132,7 +132,7 @@ const AnimatedZoom = {
return this.beginTime != null;
},
onBeforePaint: function(aTimeStamp) {
sample: function(aTimeStamp) {
try {
let tdiff = aTimeStamp - this.beginTime;
let counter = tdiff / this.animationDuration;

View File

@ -176,6 +176,18 @@ let Util = {
else if (tabletPref == 1)
return this._isTablet = true;
#ifdef ANDROID
// Disable tablet mode on non-honeycomb devices because of theme bugs (bug 705026)
let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
let shellVersion = sysInfo.get("shellVersion") || "";
let matches = shellVersion.match(/\((\d+)\)$/);
if (matches) {
let sdkVersion = parseInt(matches[1]);
if (sdkVersion < 11 || sdkVersion > 13)
return this._isTablet = false;
}
#endif
let dpi = this.displayDPI;
if (dpi <= 96)
return this._isTablet = (window.innerWidth > 1024);

View File

@ -175,7 +175,7 @@ MouseModule.prototype = {
}
},
onBeforePaint: function onBeforePaint(aTimeStamp) {
sample: function sample(aTimeStamp) {
this._waitingForPaint = false;
},
@ -889,7 +889,7 @@ KineticController.prototype = {
}
let callback = {
onBeforePaint: function kineticHandleEvent(timeStamp) {
sample: function kineticHandleEvent(timeStamp) {
// Someone called end() on us between timer intervals
// or we are paused.
if (!self.isActive() || self._paused)

View File

@ -146,7 +146,7 @@ chrome.jar:
skin/images/aurora-lightbox-close.png (images/aurora-lightbox-close.png)
chrome.jar:
% skin browser classic/1.0 %skin/gingerbread/ os=Android osversion=2.3 osversion=2.3.3 osversion=2.3.4 osversion=2.3.5 osversion=2.3.6 osversion=2.3.7
% skin browser classic/1.0 %skin/gingerbread/ os=Android osversion=2.3 osversion=2.3.3 osversion=2.3.4 osversion=2.3.5 osversion=2.3.6 osversion=2.3.7 osversion=2.3.8 osversion>=4.0
% skin browser gingerbread/1.0 %skin/gingerbread/
skin/gingerbread/aboutPage.css (aboutPage.css)
skin/gingerbread/about.css (about.css)
@ -285,7 +285,7 @@ chrome.jar:
skin/gingerbread/images/aurora-lightbox-close.png (images/aurora-lightbox-close.png)
chrome.jar:
% skin browser classic/1.0 %skin/honeycomb/ os=Android osversion>=3.0
% skin browser classic/1.0 %skin/honeycomb/ os=Android osversion=3.0 osversion=3.1 osversion=3.2 osversion=3.2.1 osversion=3.2.2 osversion=3.2.3 osversion=3.2.4 osversion=3.2.5 osversion=3.2.6 osversion=3.2.7 osversion=3.2.8 osversion=3.2.9
% skin browser honeycomb/1.0 %skin/honeycomb/
skin/honeycomb/aboutPage.css (aboutPage.css)
skin/honeycomb/about.css (about.css)

View File

@ -628,8 +628,6 @@ pref("javascript.options.strict.debug", true);
pref("javascript.options.relimit", true);
pref("javascript.options.methodjit.content", true);
pref("javascript.options.methodjit.chrome", true);
pref("javascript.options.jitprofiling.content", true);
pref("javascript.options.jitprofiling.chrome", true);
pref("javascript.options.pccounts.content", false);
pref("javascript.options.pccounts.chrome", false);
pref("javascript.options.methodjit_always", false);

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