зеркало из https://github.com/mozilla/pjs.git
Merge mozilla-central and mozilla-inbound
This commit is contained in:
Коммит
cd04c26764
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
|
@ -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]);
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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">
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
|
@ -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@
|
||||
|
|
18
configure.in
18
configure.in
|
@ -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 ========================================================
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -55,7 +55,7 @@ SDK_XPIDLSRCS = \
|
|||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIAnimationFrameListener.idl \
|
||||
nsIFrameRequestCallback.idl \
|
||||
nsIBrowserDOMWindow.idl \
|
||||
nsIContentPermissionPrompt.idl \
|
||||
nsIContentPrefService.idl \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -110,6 +110,7 @@ typedef nsCString Buffer;
|
|||
|
||||
struct NPRemoteWindow
|
||||
{
|
||||
NPRemoteWindow();
|
||||
uint64_t window;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
)
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, ¬eIndex))
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// |jit-test| error: InternalError
|
||||
var op = Object.prototype;
|
||||
op.b = op;
|
||||
op.__iterator__ = Iterator;
|
||||
for (var c in {}) {}
|
||||
|
|
@ -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();
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;) {"
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -224,7 +224,6 @@ function optionsInit() {
|
|||
xml: true,
|
||||
relimit: true,
|
||||
methodjit: true,
|
||||
jitprofiling: true,
|
||||
methodjit_always: true
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -649,7 +649,6 @@ function optionsClear() {
|
|||
var optionName = optionNames[i];
|
||||
if (optionName &&
|
||||
optionName != "methodjit" &&
|
||||
optionName != "jitprofiling" &&
|
||||
optionName != "methodjit_always")
|
||||
{
|
||||
options(optionName);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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", "*");
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
До Ширина: | Высота: | Размер: 1.2 KiB После Ширина: | Высота: | Размер: 1.4 KiB |
|
@ -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"/>
|
||||
|
|
До Ширина: | Высота: | Размер: 3.9 KiB После Ширина: | Высота: | Размер: 4.1 KiB |
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
#include "nsScrollbarFrame.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "nsITreeImageListener.h"
|
||||
|
||||
class nsOverflowChecker;
|
||||
class nsTreeImageListener;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче