This commit is contained in:
Richard Newman 2011-11-29 11:56:13 -08:00
Родитель 298535ff72 b826a2d2a6
Коммит 9158f387e6
224 изменённых файлов: 1864 добавлений и 2250 удалений

1
aclocal.m4 поставляемый
Просмотреть файл

@ -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

Просмотреть файл

@ -3481,7 +3481,6 @@ const BrowserSearch = {
openLinkIn(submission.uri.spec,
useNewTab ? "tab" : "current",
{ postData: submission.postData,
inBackground: false,
relatedToCurrent: true });
},
@ -3951,6 +3950,9 @@ var FullScreen = {
return;
}
if (gFindBarInitialized)
gFindBar.close();
this.showWarning(true);
// Exit DOM full-screen mode upon open, close, or change tab.

Просмотреть файл

@ -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

Просмотреть файл

@ -222,7 +222,7 @@ menuitem.bookmark-item {
}
.bookmark-item[query][tagContainer] {
list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
list-style-image: url("chrome://browser/skin/places/tag.png");
}
.bookmark-item[query][dayContainer] {

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 799 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 799 B

Просмотреть файл

@ -39,10 +39,10 @@ browser.jar:
skin/classic/browser/urlbar-arrow.png
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/videoFeedIcon.png)
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/videoFeedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/audioFeedIcon.png)
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/audioFeedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png)

Просмотреть файл

@ -77,7 +77,7 @@ treechildren::-moz-tree-image(query, OrganizerQuery_Downloads) {
treechildren::-moz-tree-image(title, query, tagContainer),
treechildren::-moz-tree-image(query, OrganizerQuery_Tags) {
list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
list-style-image: url("chrome://browser/skin/places/tag.png");
}
/* calendar icon for folders grouping items by date */

Просмотреть файл

@ -242,7 +242,7 @@ toolbarbutton.bookmark-item > menupopup {
}
.bookmark-item[query][tagContainer] {
list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
list-style-image: url("chrome://browser/skin/places/tag.png");
}
.bookmark-item[query][dayContainer] {
@ -1913,6 +1913,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
}
.tabbrowser-tab[selected="true"] {
color: #000;
z-index: 1;
position: relative;
}

Двоичные данные
browser/themes/pinstripe/feeds/audioFeedIcon.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 852 B

Двоичные данные
browser/themes/pinstripe/feeds/videoFeedIcon.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 852 B

Просмотреть файл

@ -51,10 +51,10 @@ browser.jar:
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/videoFeedIcon.png)
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/videoFeedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/audioFeedIcon.png)
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/audioFeedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/setDesktopBackground.css
skin/classic/browser/inspector.css
skin/classic/browser/monitor.png

Просмотреть файл

@ -144,7 +144,7 @@ treechildren::-moz-tree-image(query, OrganizerQuery_Downloads) {
treechildren::-moz-tree-image(title, query, tagContainer),
treechildren::-moz-tree-image(query, OrganizerQuery_Tags) {
list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
list-style-image: url("chrome://browser/skin/places/tag.png");
}
/* calendar icon for folders grouping items by date */

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 441 B

Просмотреть файл

@ -621,7 +621,7 @@ menuitem.bookmark-item {
}
.bookmark-item[query][tagContainer] {
list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
list-style-image: url("chrome://browser/skin/places/tag.png");
-moz-image-region: auto;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичные данные
browser/themes/winstripe/feeds/audioFeedIcon.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 787 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 791 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичные данные
browser/themes/winstripe/feeds/videoFeedIcon.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 787 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 791 B

Просмотреть файл

@ -6,7 +6,7 @@ browser.jar:
skin/classic/browser/sanitizeDialog.css (sanitizeDialog.css)
* skin/classic/browser/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css)
* skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css)
skin/classic/browser/aboutSessionRestore-window-icon.png (aboutSessionRestore-window-icon.png)
skin/classic/browser/aboutSessionRestore-window-icon.png (preferences/application.png)
skin/classic/browser/aboutCertError.css (aboutCertError.css)
#ifdef MOZ_SERVICES_SYNC
skin/classic/browser/aboutSyncTabs.css
@ -51,10 +51,10 @@ browser.jar:
skin/classic/browser/urlbar-history-dropmarker.png
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/audioFeedIcon.png)
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/audioFeedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/videoFeedIcon.png)
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/videoFeedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/inspector.css
@ -204,10 +204,10 @@ browser.jar:
skin/classic/aero/browser/urlbar-history-dropmarker.png
skin/classic/aero/browser/feeds/feedIcon.png (feeds/feedIcon-aero.png)
skin/classic/aero/browser/feeds/feedIcon16.png (feeds/feedIcon16-aero.png)
skin/classic/aero/browser/feeds/audioFeedIcon.png (feeds/audioFeedIcon-aero.png)
skin/classic/aero/browser/feeds/audioFeedIcon16.png (feeds/audioFeedIcon16-aero.png)
skin/classic/aero/browser/feeds/videoFeedIcon.png (feeds/videoFeedIcon-aero.png)
skin/classic/aero/browser/feeds/videoFeedIcon16.png (feeds/videoFeedIcon16-aero.png)
skin/classic/aero/browser/feeds/audioFeedIcon.png (feeds/feedIcon-aero.png)
skin/classic/aero/browser/feeds/audioFeedIcon16.png (feeds/feedIcon16-aero.png)
skin/classic/aero/browser/feeds/videoFeedIcon.png (feeds/feedIcon-aero.png)
skin/classic/aero/browser/feeds/videoFeedIcon16.png (feeds/feedIcon16-aero.png)
skin/classic/aero/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/aero/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/aero/browser/inspector.css
@ -228,7 +228,7 @@ browser.jar:
skin/classic/aero/browser/places/history.png (places/history-aero.png)
skin/classic/aero/browser/places/allBookmarks.png (places/allBookmarks-aero.png)
skin/classic/aero/browser/places/unsortedBookmarks.png (places/unsortedBookmarks-aero.png)
skin/classic/aero/browser/places/searching_16.png (places/searching_16-aero.png)
skin/classic/aero/browser/places/searching_16.png (places/searching_16.png)
skin/classic/aero/browser/places/downloads.png (places/downloads.png)
skin/classic/aero/browser/preferences/alwaysAsk.png (preferences/alwaysAsk-aero.png)
skin/classic/aero/browser/preferences/application.png (preferences/application-aero.png)
@ -237,7 +237,6 @@ browser.jar:
#ifdef MOZ_SERVICES_SYNC
skin/classic/aero/browser/preferences/Options-sync.png (preferences/Options-sync.png)
#endif
skin/classic/aero/browser/preferences/plugin.png (preferences/plugin-aero.png)
skin/classic/aero/browser/preferences/saveFile.png (preferences/saveFile-aero.png)
* skin/classic/aero/browser/preferences/preferences.css (preferences/preferences.css)
skin/classic/aero/browser/preferences/applications.css (preferences/applications.css)

Просмотреть файл

@ -81,7 +81,7 @@ treechildren::-moz-tree-image(title, query) {
treechildren::-moz-tree-image(title, query, tagContainer),
treechildren::-moz-tree-image(query, OrganizerQuery_Tags) {
list-style-image: url("chrome://mozapps/skin/places/tagContainerIcon.png");
list-style-image: url("chrome://browser/skin/places/tag.png");
-moz-image-region: auto;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 4.1 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 539 B

Просмотреть файл

@ -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@

Просмотреть файл

@ -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.

Просмотреть файл

@ -51,6 +51,9 @@
#include "nsISHContainer.h"
#include "nsIWindowWatcher.h"
#include "mozilla/Services.h"
#include "nsIXULWindow.h"
#include "nsIAppShellService.h"
#include "nsAppShellCID.h"
static bool sInited = 0;
PRUint32 nsCCUncollectableMarker::sGeneration = 0;
@ -231,6 +234,19 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
MarkWindowList(windowList);
}
nsCOMPtr<nsIAppShellService> appShell =
do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
if (appShell) {
nsCOMPtr<nsIXULWindow> hw;
appShell->GetHiddenWindow(getter_AddRefs(hw));
if (hw) {
nsCOMPtr<nsIDocShell> shell;
hw->GetDocShell(getter_AddRefs(shell));
nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
MarkDocShell(shellTreeNode);
}
}
return NS_OK;
}

Просмотреть файл

@ -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) &&
bool alreadyRegistered = !mFrameRequestCallbacks.IsEmpty();
if (mFrameRequestCallbacks.AppendElement(aCallback) &&
!alreadyRegistered && mPresShell && IsEventHandlingEnabled()) {
mPresShell->GetPresContext()->RefreshDriver()->
ScheduleAnimationFrameListeners(this);
ScheduleFrameRequestCallbacks(this);
}
return;
}
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);

Просмотреть файл

@ -405,7 +405,7 @@ nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext,
if (!ls) {
// If we didn't find a script listener or no listeners existed
// create and add a new one.
nsCOMPtr<nsIDOMEventListener> scriptListener;
nsCOMPtr<nsIJSEventListener> scriptListener;
rv = NS_NewJSEventListener(aContext, aScopeObject, mTarget, aName,
aHandler, getter_AddRefs(scriptListener));
if (NS_SUCCEEDED(rv)) {

Просмотреть файл

@ -63,7 +63,8 @@ class nsCxPusher;
class nsIEventListenerInfo;
class nsIDocument;
typedef struct {
struct nsListenerStruct
{
nsRefPtr<nsIDOMEventListener> mListener;
PRUint32 mEventType;
nsCOMPtr<nsIAtom> mTypeAtom;
@ -74,7 +75,14 @@ typedef struct {
return (mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) ?
static_cast<nsIJSEventListener *>(mListener.get()) : nsnull;
}
} nsListenerStruct;
~nsListenerStruct()
{
if ((mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) && mListener) {
static_cast<nsIJSEventListener*>(mListener.get())->Disconnect();
}
}
};
/*
* Event listener manager

Просмотреть файл

@ -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,6 +365,8 @@ 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();
}

Просмотреть файл

@ -35,8 +35,8 @@ 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)
if (v.ended && v.seenSuspend && !v.finished) {
v.finished = true;
v.parentNode.removeChild(v);
manager.finished(v.token);
}
@ -48,8 +48,8 @@ function startTest(test, token) {
v.seenSuspend = true;
ok(true, test.name + " got suspend");
if (v.ended && v.seenSuspend) {
if (v.parentNode)
if (v.ended && !v.finished) {
v.finished = true;
v.parentNode.removeChild(v);
manager.finished(v.token);
}

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -327,7 +327,7 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventTarget* aTarget,
NS_ENSURE_SUCCESS(rv, rv);
// Execute it.
nsCOMPtr<nsIDOMEventListener> eventListener;
nsCOMPtr<nsIJSEventListener> eventListener;
rv = NS_NewJSEventListener(boundContext, scope,
scriptTarget, onEventAtom,
boundHandler.getObject(),
@ -336,6 +336,7 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventTarget* aTarget,
// Handle the event.
eventListener->HandleEvent(aEvent);
eventListener->Disconnect();
return NS_OK;
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -46,13 +46,16 @@ class nsIScriptObjectOwner;
class nsIAtom;
#define NS_IJSEVENTLISTENER_IID \
{ 0xafc5d047, 0xdb6b, 0x4076, \
{ 0xb3, 0xfa, 0x57, 0x96, 0x1e, 0x21, 0x48, 0x42 } }
{ 0x92f9212b, 0xa6aa, 0x4867, \
{ 0x93, 0x8a, 0x56, 0xbe, 0x17, 0x67, 0x4f, 0xd4 } }
// Implemented by script event listeners. Used to retrieve the
// script object corresponding to the event target and the handler itself.
// (Note this interface is now used to store script objects for all
// script languages, so is no longer JS specific)
//
// Note, mTarget is a raw pointer and the owner of the nsIJSEventListener object
// is expected to call Disconnect()!
class nsIJSEventListener : public nsIDOMEventListener
{
public:
@ -60,9 +63,10 @@ public:
nsIJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
nsISupports *aTarget, JSObject *aHandler)
: mContext(aContext), mScopeObject(aScopeObject),
mTarget(do_QueryInterface(aTarget)), mHandler(aHandler)
: mContext(aContext), mScopeObject(aScopeObject), mHandler(aHandler)
{
nsCOMPtr<nsISupports> base = do_QueryInterface(aTarget);
mTarget = base.get();
}
nsIScriptContext *GetEventContext() const
@ -75,6 +79,11 @@ public:
return mTarget;
}
void Disconnect()
{
mTarget = nsnull;
}
JSObject* GetEventScope() const
{
return mScopeObject;
@ -94,10 +103,11 @@ public:
protected:
virtual ~nsIJSEventListener()
{
NS_ASSERTION(!mTarget, "Should have called Disconnect()!");
}
nsCOMPtr<nsIScriptContext> mContext;
JSObject* mScopeObject;
nsCOMPtr<nsISupports> mTarget;
nsISupports* mTarget;
JSObject *mHandler;
};
@ -107,6 +117,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
nsresult NS_NewJSEventListener(nsIScriptContext *aContext,
JSObject* aScopeObject, nsISupports* aTarget,
nsIAtom* aType, JSObject* aHandler,
nsIDOMEventListener **aReturn);
nsIJSEventListener **aReturn);
#endif // nsIJSEventListener_h__

Просмотреть файл

@ -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();

Просмотреть файл

@ -1548,6 +1548,7 @@ OpenDatabaseHelper::ReleaseMainThreadObjects()
mOpenDBRequest = nsnull;
mDatabase = nsnull;
mDatabaseId = nsnull;
HelperBase::ReleaseMainThreadObjects();
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -103,7 +103,6 @@ nsJSEventListener::~nsJSEventListener()
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTarget)
if (tmp->mContext) {
if (tmp->mContext->GetScriptTypeID() == nsIProgrammingLanguage::JAVASCRIPT) {
NS_DROP_JS_OBJECTS(tmp, nsJSEventListener);
@ -117,7 +116,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -274,7 +272,7 @@ nsJSEventListener::SetHandler(JSObject *aHandler)
nsresult
NS_NewJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
nsISupports*aTarget, nsIAtom* aEventType,
JSObject* aHandler, nsIDOMEventListener ** aReturn)
JSObject* aHandler, nsIJSEventListener** aReturn)
{
NS_ENSURE_ARG(aEventType);
nsJSEventListener* it =

Просмотреть файл

@ -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,8 +3183,9 @@ 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);
}
@ -3189,7 +3194,8 @@ nsEditor::GetNextNode(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool aEditableNode,
nsCOMPtr<nsIDOMNode> *aResultNode,
bool bNoBlockCrossing)
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,226 +3257,138 @@ 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.
*aResultNode =
do_QueryInterface(FindNode(currentNode, false, aEditableNode,
bNoBlockCrossing, aActiveEditorRoot));
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;
}
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))
{
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
*aResultNode = prevSibling;
return NS_OK;
return sibling;
}
*aResultNode = GetRightmostChild(prevSibling, bNoBlockCrossing);
if (!*aResultNode)
{
*aResultNode = prevSibling;
return NS_OK;
nsIContent *leaf =
aGoForward ? GetLeftmostChild(sibling, bNoBlockCrossing) :
GetRightmostChild(sibling, bNoBlockCrossing);
if (!leaf) {
return sibling;
}
if (!IsDescendantOfBody(*aResultNode))
{
*aResultNode = nsnull;
return NS_OK;
return leaf;
}
nsINode *parent = cur->GetNodeParent();
if (!parent) {
return nsnull;
}
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;
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;
}
if ((bNoBlockCrossing && IsBlockNode(parent)) || IsRootNode(parent))
{
// we are at front of block or root, do not step out
*aResultNode = nsnull;
return NS_OK;
cur = parent;
}
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;
}
}
} while ((NS_SUCCEEDED(result)) && parent && !*aResultNode);
}
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
nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
if (!IsDescendantOfBody(currentNode) ||
(aActiveEditorRoot &&
!nsContentUtils::ContentIsDescendantOf(currentNode,
aActiveEditorRoot))) {
*aResultNode = nsnull;
return NS_OK;
}
if (IsRootNode(aCurrentNode))
*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;
}
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);
}
return result;
if (!candidate) {
return nsnull;
}
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;
if (!aEditableNode || IsEditable(candidate)) {
return candidate;
}
return FindNode(candidate, aGoForward, aEditableNode, bNoBlockCrossing,
aActiveEditorRoot);
}
already_AddRefed<nsIDOMNode>
nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode,
@ -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)
@ -3528,6 +3496,16 @@ nsEditor::IsBlockNode(nsIDOMNode *aNode)
return false;
}
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)
{
@ -3568,33 +3546,36 @@ nsEditor::IsRootNode(nsIDOMNode *inNode)
{
NS_ENSURE_TRUE(inNode, false);
return inNode == GetRoot();
}
bool
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
bool
nsEditor::IsDescendantOfBody(nsINode *inNode)
{
node->GetParentNode(getter_AddRefs(parent));
if (parent == root) return true;
node = parent;
} while (parent);
NS_ENSURE_TRUE(inNode, false);
nsCOMPtr<nsIContent> root = do_QueryInterface(GetRoot());
NS_ENSURE_TRUE(root, false);
return 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
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;
if (!content->IsNodeOfType(nsINode::eTEXT))
}
if (aNode->NodeType() != nsIDOMNode::TEXT_NODE)
return true; // not a text node; not invisible
return IsTextInDirtyFrameVisible(aNode);
}
return false; // didn't pass any editability test
}
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);
@ -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:

Просмотреть файл

@ -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);
{

1
js/src/aclocal.m4 поставляемый
Просмотреть файл

@ -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, &noteIndex))
return JS_FALSE;
break;
@ -6175,18 +6178,18 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
break;
#endif
case PNK_LC:
{
#if JS_HAS_XML_SUPPORT
if (pn->isArity(PN_UNARY)) {
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
* 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'
* 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
* pn_right: body
* 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. */

Просмотреть файл

@ -133,6 +133,12 @@ JS_ObjectCountDynamicSlots(JSObject *obj)
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 */

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше