зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to autoland, a=merge
MozReview-Commit-ID: 6wWFiDQ0QJ8
This commit is contained in:
Коммит
269e3163e5
|
@ -125,7 +125,7 @@ const addView = curry((options, {document, window}) => {
|
||||||
toolbar.setAttribute("id", "inner-" + options.id);
|
toolbar.setAttribute("id", "inner-" + options.id);
|
||||||
toolbar.setAttribute("defaultset", options.items.join(","));
|
toolbar.setAttribute("defaultset", options.items.join(","));
|
||||||
toolbar.setAttribute("customizable", "true");
|
toolbar.setAttribute("customizable", "true");
|
||||||
toolbar.setAttribute("style", "-moz-appearance: none; overflow: hidden");
|
toolbar.setAttribute("style", "-moz-appearance: none; overflow: hidden; border: 0;");
|
||||||
toolbar.setAttribute("mode", "icons");
|
toolbar.setAttribute("mode", "icons");
|
||||||
toolbar.setAttribute("iconsize", "small");
|
toolbar.setAttribute("iconsize", "small");
|
||||||
toolbar.setAttribute("context", "toolbar-context-menu");
|
toolbar.setAttribute("context", "toolbar-context-menu");
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/* global XPCOMUtils, Services, PlacesUtils, gPrincipal, EventEmitter */
|
/* global XPCOMUtils, Services, PlacesUtils, EventEmitter */
|
||||||
/* global gLinks */
|
/* global gLinks */
|
||||||
/* exported PlacesProvider */
|
/* exported PlacesProvider */
|
||||||
|
|
||||||
|
@ -22,52 +22,14 @@ XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
|
||||||
return EventEmitter;
|
return EventEmitter;
|
||||||
});
|
});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "gPrincipal", function() {
|
|
||||||
let uri = Services.io.newURI("about:newtab");
|
|
||||||
return Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
|
|
||||||
});
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||||
"resource://gre/modules/Task.jsm");
|
"resource://gre/modules/Task.jsm");
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
|
||||||
|
"resource://gre/modules/NewTabUtils.jsm");
|
||||||
|
|
||||||
// The maximum number of results PlacesProvider retrieves from history.
|
// The maximum number of results PlacesProvider retrieves from history.
|
||||||
const HISTORY_RESULTS_LIMIT = 100;
|
const HISTORY_RESULTS_LIMIT = 100;
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton that checks if a given link should be displayed on about:newtab
|
|
||||||
* or if we should rather not do it for security reasons. URIs that inherit
|
|
||||||
* their caller's principal will be filtered.
|
|
||||||
*/
|
|
||||||
let LinkChecker = {
|
|
||||||
_cache: new Map(),
|
|
||||||
|
|
||||||
get flags() {
|
|
||||||
return Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL |
|
|
||||||
Ci.nsIScriptSecurityManager.DONT_REPORT_ERRORS;
|
|
||||||
},
|
|
||||||
|
|
||||||
checkLoadURI: function LinkChecker_checkLoadURI(aURI) {
|
|
||||||
if (!this._cache.has(aURI)) {
|
|
||||||
this._cache.set(aURI, this._doCheckLoadURI(aURI));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._cache.get(aURI);
|
|
||||||
},
|
|
||||||
|
|
||||||
_doCheckLoadURI: function LinkChecker_doCheckLoadURI(aURI) {
|
|
||||||
let result = false;
|
|
||||||
try {
|
|
||||||
Services.scriptSecurityManager.
|
|
||||||
checkLoadURIStrWithPrincipal(gPrincipal, aURI, this.flags);
|
|
||||||
result = true;
|
|
||||||
} catch (e) {
|
|
||||||
// We got a weird URI or one that would inherit the caller's principal.
|
|
||||||
Cu.reportError(e);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Queries history to retrieve the most visited sites. Emits events when the
|
/* Queries history to retrieve the most visited sites. Emits events when the
|
||||||
* history changes.
|
* history changes.
|
||||||
* Implements the EventEmitter interface.
|
* Implements the EventEmitter interface.
|
||||||
|
@ -105,7 +67,8 @@ Links.prototype = {
|
||||||
aNewFrecency, aGUID, aHidden, aLastVisitDate) { // jshint ignore:line
|
aNewFrecency, aGUID, aHidden, aLastVisitDate) { // jshint ignore:line
|
||||||
// The implementation of the query in getLinks excludes hidden and
|
// The implementation of the query in getLinks excludes hidden and
|
||||||
// unvisited pages, so it's important to exclude them here, too.
|
// unvisited pages, so it's important to exclude them here, too.
|
||||||
if (!aHidden && aLastVisitDate) {
|
if (!aHidden && aLastVisitDate &&
|
||||||
|
NewTabUtils.linkChecker.checkLoadURI(aURI.spec)) {
|
||||||
gLinks.emit("linkChanged", {
|
gLinks.emit("linkChanged", {
|
||||||
url: aURI.spec,
|
url: aURI.spec,
|
||||||
frecency: aNewFrecency,
|
frecency: aNewFrecency,
|
||||||
|
@ -122,10 +85,12 @@ Links.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
onTitleChanged: function historyObserver_onTitleChanged(aURI, aNewTitle) {
|
onTitleChanged: function historyObserver_onTitleChanged(aURI, aNewTitle) {
|
||||||
|
if (NewTabUtils.linkChecker.checkLoadURI(aURI.spec)) {
|
||||||
gLinks.emit("linkChanged", {
|
gLinks.emit("linkChanged", {
|
||||||
url: aURI.spec,
|
url: aURI.spec,
|
||||||
title: aNewTitle
|
title: aNewTitle
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver,
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver,
|
||||||
|
@ -184,7 +149,7 @@ Links.prototype = {
|
||||||
params: {limit: this.maxNumLinks}
|
params: {limit: this.maxNumLinks}
|
||||||
});
|
});
|
||||||
|
|
||||||
return links.filter(link => LinkChecker.checkLoadURI(link.url));
|
return links.filter(link => NewTabUtils.linkChecker.checkLoadURI(link.url));
|
||||||
}),
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -247,6 +212,10 @@ Links.prototype = {
|
||||||
const gLinks = new Links(); // jshint ignore:line
|
const gLinks = new Links(); // jshint ignore:line
|
||||||
|
|
||||||
let PlacesProvider = {
|
let PlacesProvider = {
|
||||||
LinkChecker,
|
|
||||||
links: gLinks,
|
links: gLinks,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Kept only for backwards-compatibility
|
||||||
|
XPCOMUtils.defineLazyGetter(PlacesProvider, "LinkChecker",
|
||||||
|
() => NewTabUtils.linkChecker);
|
||||||
|
|
||||||
|
|
|
@ -59,13 +59,13 @@ function makeVisit(index, daysAgo, isTyped, domain = TEST_URL) {
|
||||||
add_task(function test_LinkChecker_securityCheck() {
|
add_task(function test_LinkChecker_securityCheck() {
|
||||||
|
|
||||||
let urls = [
|
let urls = [
|
||||||
{url: "file://home/file/image.png", expected: false},
|
|
||||||
{url: "resource:///modules/PlacesProvider.jsm", expected: false},
|
|
||||||
{url: "javascript:alert('hello')", expected: false}, // jshint ignore:line
|
{url: "javascript:alert('hello')", expected: false}, // jshint ignore:line
|
||||||
{url: "data:image/png;base64,XXX", expected: false},
|
{url: "data:image/png;base64,XXX", expected: false},
|
||||||
{url: "about:newtab", expected: true},
|
{url: "about:newtab", expected: true},
|
||||||
{url: "https://example.com", expected: true},
|
{url: "https://example.com", expected: true},
|
||||||
{url: "ftp://example.com", expected: true},
|
{url: "ftp://example.com", expected: true},
|
||||||
|
{url: "file://home/file/image.png", expected: true},
|
||||||
|
{url: "resource:///modules/PlacesProvider.jsm", expected: true},
|
||||||
];
|
];
|
||||||
for (let {url, expected} of urls) {
|
for (let {url, expected} of urls) {
|
||||||
let observed = PlacesProvider.LinkChecker.checkLoadURI(url);
|
let observed = PlacesProvider.LinkChecker.checkLoadURI(url);
|
||||||
|
|
|
@ -37,5 +37,13 @@
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "clang.tar.bz2",
|
"filename": "clang.tar.bz2",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"visibility": "public",
|
||||||
|
"filename": "makecab.tar.bz2",
|
||||||
|
"unpack": true,
|
||||||
|
"digest": "da1f7685e5bc49a5ffbe5b4a3678ac7a58a0e125031726d30e2bacbbffa53d6efb9fd9f00d6dff5b54cff9412a103efa564c2af6f8fccc63082f6939181769f8",
|
||||||
|
"size": 296777
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -29,5 +29,13 @@
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "vs2015u3.zip",
|
"filename": "vs2015u3.zip",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"visibility": "public",
|
||||||
|
"filename": "makecab.tar.bz2",
|
||||||
|
"unpack": true,
|
||||||
|
"digest": "da1f7685e5bc49a5ffbe5b4a3678ac7a58a0e125031726d30e2bacbbffa53d6efb9fd9f00d6dff5b54cff9412a103efa564c2af6f8fccc63082f6939181769f8",
|
||||||
|
"size": 296777
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -38,5 +38,13 @@
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "clang.tar.bz2",
|
"filename": "clang.tar.bz2",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"visibility": "public",
|
||||||
|
"filename": "makecab.tar.bz2",
|
||||||
|
"unpack": true,
|
||||||
|
"digest": "da1f7685e5bc49a5ffbe5b4a3678ac7a58a0e125031726d30e2bacbbffa53d6efb9fd9f00d6dff5b54cff9412a103efa564c2af6f8fccc63082f6939181769f8",
|
||||||
|
"size": 296777
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -30,5 +30,13 @@
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "vs2015u3.zip",
|
"filename": "vs2015u3.zip",
|
||||||
"unpack": true
|
"unpack": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"visibility": "public",
|
||||||
|
"filename": "makecab.tar.bz2",
|
||||||
|
"unpack": true,
|
||||||
|
"digest": "da1f7685e5bc49a5ffbe5b4a3678ac7a58a0e125031726d30e2bacbbffa53d6efb9fd9f00d6dff5b54cff9412a103efa564c2af6f8fccc63082f6939181769f8",
|
||||||
|
"size": 296777
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -206,9 +206,12 @@ body:not(.compact) .newtab-site[type=sponsored] .newtab-thumbnail {
|
||||||
}
|
}
|
||||||
|
|
||||||
body.compact .newtab-title {
|
body.compact .newtab-title {
|
||||||
background-color: hsla(0,0%,100%,.8);
|
background-color: hsla(0,0%,100%,.85);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 21px;
|
line-height: 21px;
|
||||||
|
border: 1px solid hsla(0,0%,80%,.8);
|
||||||
|
border-top-color: hsla(0,0%,0%,.1);
|
||||||
|
background-clip: padding-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newtab-title,
|
.newtab-title,
|
||||||
|
@ -221,12 +224,6 @@ body.compact .newtab-suggested {
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.compact .newtab-title {
|
|
||||||
border: 1px solid hsla(0,0%,80%,.8);
|
|
||||||
border-top-color: hsla(0,0%,0%,.1);
|
|
||||||
background-clip: padding-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.newtab-suggested[active] {
|
.newtab-suggested[active] {
|
||||||
background-color: rgba(51, 51, 51, 0.95);
|
background-color: rgba(51, 51, 51, 0.95);
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -242,7 +239,7 @@ body:not(.compact) .newtab-site:hover .newtab-title {
|
||||||
|
|
||||||
body.compact .newtab-site:hover .newtab-title {
|
body.compact .newtab-site:hover .newtab-title {
|
||||||
color: white;
|
color: white;
|
||||||
background-color: hsla(0,0%,20%,.8);
|
background-color: hsla(0,0%,20%,.85);
|
||||||
border-color: hsla(0,0%,0%,.8);
|
border-color: hsla(0,0%,0%,.8);
|
||||||
border-top-color: white;
|
border-top-color: white;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ if test -n "$USE_ICU"; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
version=`sed -n 's/^[[:space:]]*#[[:space:]]*define[[:space:]][[:space:]]*U_ICU_VERSION_MAJOR_NUM[[:space:]][[:space:]]*\([0-9][0-9]*\)[[:space:]]*$/\1/p' "$icudir/common/unicode/uvernum.h"`
|
version=`sed -n 's/^[[[:space:]]]*#[[:space:]]*define[[:space:]][[:space:]]*U_ICU_VERSION_MAJOR_NUM[[:space:]][[:space:]]*\([0-9][0-9]*\)[[:space:]]*$/\1/p' "$icudir/common/unicode/uvernum.h"`
|
||||||
if test x"$version" = x; then
|
if test x"$version" = x; then
|
||||||
AC_MSG_ERROR([cannot determine icu version number from uvernum.h header file $lineno])
|
AC_MSG_ERROR([cannot determine icu version number from uvernum.h header file $lineno])
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -416,3 +416,6 @@ def alter_path(sdk_bin_path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
set_config('PATH', alter_path)
|
set_config('PATH', alter_path)
|
||||||
|
|
||||||
|
check_prog('MAKECAB', ('makecab.exe',))
|
||||||
|
|
||||||
|
|
|
@ -14,3 +14,4 @@ fi
|
||||||
MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-1}
|
MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-1}
|
||||||
|
|
||||||
export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=c:/builds/crash-stats-api.token
|
export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=c:/builds/crash-stats-api.token
|
||||||
|
export MAKECAB=$topsrcdir/makecab.exe
|
||||||
|
|
|
@ -61,3 +61,7 @@ if CONFIG['ENABLE_TESTS']:
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
||||||
|
with Files("**"):
|
||||||
|
BUG_COMPONENT = ("Core", "Security: CAPS")
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ define(function (require, exports, module) {
|
||||||
propTypes: {
|
propTypes: {
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
|
object: React.PropTypes.array.isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (object, context) {
|
getTitle: function (object, context) {
|
||||||
|
@ -170,6 +172,12 @@ define(function (require, exports, module) {
|
||||||
let ItemRep = React.createFactory(React.createClass({
|
let ItemRep = React.createFactory(React.createClass({
|
||||||
displayName: "ItemRep",
|
displayName: "ItemRep",
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
object: React.PropTypes.any.isRequired,
|
||||||
|
delim: React.PropTypes.string.isRequired,
|
||||||
|
mode: React.PropTypes.symbol,
|
||||||
|
},
|
||||||
|
|
||||||
render: wrapRender(function () {
|
render: wrapRender(function () {
|
||||||
const { Rep } = createFactories(require("./rep"));
|
const { Rep } = createFactories(require("./rep"));
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,8 @@ define(function (require, exports, module) {
|
||||||
displayName: "Attr",
|
displayName: "Attr",
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (grip) {
|
getTitle: function (grip) {
|
||||||
|
|
|
@ -21,6 +21,10 @@ define(function (require, exports, module) {
|
||||||
const Caption = React.createClass({
|
const Caption = React.createClass({
|
||||||
displayName: "Caption",
|
displayName: "Caption",
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
object: React.PropTypes.object,
|
||||||
|
},
|
||||||
|
|
||||||
render: wrapRender(function () {
|
render: wrapRender(function () {
|
||||||
return (
|
return (
|
||||||
DOM.span({"className": "caption"}, this.props.object)
|
DOM.span({"className": "caption"}, this.props.object)
|
||||||
|
|
|
@ -26,7 +26,8 @@ define(function (require, exports, module) {
|
||||||
displayName: "Date",
|
displayName: "Date",
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (grip) {
|
getTitle: function (grip) {
|
||||||
|
|
|
@ -27,7 +27,8 @@ define(function (require, exports, module) {
|
||||||
displayName: "Document",
|
displayName: "Document",
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getLocation: function (grip) {
|
getLocation: function (grip) {
|
||||||
|
|
|
@ -31,6 +31,9 @@ define(function (require, exports, module) {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
onDOMNodeMouseOver: React.PropTypes.func,
|
||||||
|
onDOMNodeMouseOut: React.PropTypes.func,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getElements: function (grip, mode) {
|
getElements: function (grip, mode) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ define(function (require, exports, module) {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
render: wrapRender(function () {
|
render: wrapRender(function () {
|
||||||
|
|
|
@ -27,7 +27,8 @@ define(function (require, exports, module) {
|
||||||
displayName: "Func",
|
displayName: "Func",
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (grip) {
|
getTitle: function (grip) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ define(function (require, exports, module) {
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
provider: React.PropTypes.object,
|
provider: React.PropTypes.object,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getLength: function (grip) {
|
getLength: function (grip) {
|
||||||
|
|
|
@ -30,6 +30,8 @@ define(function (require, exports, module) {
|
||||||
object: React.PropTypes.object,
|
object: React.PropTypes.object,
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
|
isInterestingEntry: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (object) {
|
getTitle: function (object) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ define(function (require, exports, module) {
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
isInterestingProp: React.PropTypes.func,
|
isInterestingProp: React.PropTypes.func,
|
||||||
title: React.PropTypes.string,
|
title: React.PropTypes.string,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (object) {
|
getTitle: function (object) {
|
||||||
|
|
|
@ -22,6 +22,10 @@ define(function (require, exports, module) {
|
||||||
const InfinityRep = React.createClass({
|
const InfinityRep = React.createClass({
|
||||||
displayName: "Infinity",
|
displayName: "Infinity",
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
object: React.PropTypes.object.isRequired,
|
||||||
|
},
|
||||||
|
|
||||||
render: wrapRender(function () {
|
render: wrapRender(function () {
|
||||||
return (
|
return (
|
||||||
span({className: "objectBox objectBox-number"},
|
span({className: "objectBox objectBox-number"},
|
||||||
|
|
|
@ -25,6 +25,9 @@ define(function (require, exports, module) {
|
||||||
propTypes: {
|
propTypes: {
|
||||||
useQuotes: React.PropTypes.bool,
|
useQuotes: React.PropTypes.bool,
|
||||||
style: React.PropTypes.object,
|
style: React.PropTypes.object,
|
||||||
|
cropLimit: React.PropTypes.number.isRequired,
|
||||||
|
member: React.PropTypes.string,
|
||||||
|
object: React.PropTypes.object.isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function () {
|
getDefaultProps: function () {
|
||||||
|
|
|
@ -22,6 +22,13 @@ define(function (require, exports, module) {
|
||||||
const Number = React.createClass({
|
const Number = React.createClass({
|
||||||
displayName: "Number",
|
displayName: "Number",
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
object: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.object,
|
||||||
|
React.PropTypes.number,
|
||||||
|
]).isRequired
|
||||||
|
},
|
||||||
|
|
||||||
stringify: function (object) {
|
stringify: function (object) {
|
||||||
let isNegativeZero = Object.is(object, -0) ||
|
let isNegativeZero = Object.is(object, -0) ||
|
||||||
(object.type && object.type == "-0");
|
(object.type && object.type == "-0");
|
||||||
|
|
|
@ -27,6 +27,7 @@ define(function (require, exports, module) {
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (grip) {
|
getTitle: function (grip) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ define(function (require, exports, module) {
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (grip) {
|
getTitle: function (grip) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ define(function (require, exports, module) {
|
||||||
object: React.PropTypes.object,
|
object: React.PropTypes.object,
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (object) {
|
getTitle: function (object) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ define(function (require, exports, module) {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (object) {
|
getTitle: function (object) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ define(function (require, exports, module) {
|
||||||
delim: React.PropTypes.string,
|
delim: React.PropTypes.string,
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
render: wrapRender(function () {
|
render: wrapRender(function () {
|
||||||
|
|
|
@ -27,6 +27,7 @@ define(function (require, exports, module) {
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getSource: function (grip) {
|
getSource: function (grip) {
|
||||||
|
|
|
@ -28,6 +28,9 @@ define(function (require, exports, module) {
|
||||||
propTypes: {
|
propTypes: {
|
||||||
useQuotes: React.PropTypes.bool,
|
useQuotes: React.PropTypes.bool,
|
||||||
style: React.PropTypes.object,
|
style: React.PropTypes.object,
|
||||||
|
object: React.PropTypes.string.isRequired,
|
||||||
|
member: React.PropTypes.any,
|
||||||
|
cropLimit: React.PropTypes.number,
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps: function () {
|
getDefaultProps: function () {
|
||||||
|
|
|
@ -28,6 +28,7 @@ define(function (require, exports, module) {
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (grip) {
|
getTitle: function (grip) {
|
||||||
|
|
|
@ -31,6 +31,9 @@ define(function (require, exports, module) {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
// @TODO Change this to Object.values once it's supported in Node's version of V8
|
||||||
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
|
onDOMNodeMouseOver: React.PropTypes.func,
|
||||||
|
onDOMNodeMouseOut: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTextContent: function (grip) {
|
getTextContent: function (grip) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ define(function (require, exports, module) {
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
object: React.PropTypes.object.isRequired,
|
object: React.PropTypes.object.isRequired,
|
||||||
|
objectLink: React.PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
getTitle: function (grip) {
|
getTitle: function (grip) {
|
||||||
|
|
|
@ -21,6 +21,10 @@ const SplitBox = React.createClass({
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
// Initial size of controlled panel.
|
// Initial size of controlled panel.
|
||||||
initialSize: PropTypes.number,
|
initialSize: PropTypes.number,
|
||||||
|
// Initial width of controlled panel.
|
||||||
|
initialWidth: PropTypes.number,
|
||||||
|
// Initial height of controlled panel.
|
||||||
|
initialHeight: PropTypes.number,
|
||||||
// Left/top panel
|
// Left/top panel
|
||||||
startPanel: PropTypes.any,
|
startPanel: PropTypes.any,
|
||||||
// Min panel size.
|
// Min panel size.
|
||||||
|
@ -34,7 +38,9 @@ const SplitBox = React.createClass({
|
||||||
// Size of the splitter handle bar.
|
// Size of the splitter handle bar.
|
||||||
splitterSize: PropTypes.number,
|
splitterSize: PropTypes.number,
|
||||||
// True if the splitter bar is vertical (default is vertical).
|
// True if the splitter bar is vertical (default is vertical).
|
||||||
vert: PropTypes.bool
|
vert: PropTypes.bool,
|
||||||
|
// Style object.
|
||||||
|
style: PropTypes.object,
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
|
|
|
@ -14,7 +14,7 @@ const l10n = new LocalizationHelper("devtools/client/locales/webconsole.properti
|
||||||
const AsyncFrame = createFactory(createClass({
|
const AsyncFrame = createFactory(createClass({
|
||||||
displayName: "AsyncFrame",
|
displayName: "AsyncFrame",
|
||||||
|
|
||||||
PropTypes: {
|
propTypes: {
|
||||||
asyncCause: PropTypes.string.isRequired
|
asyncCause: PropTypes.string.isRequired
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ const AsyncFrame = createFactory(createClass({
|
||||||
const StackTrace = createClass({
|
const StackTrace = createClass({
|
||||||
displayName: "StackTrace",
|
displayName: "StackTrace",
|
||||||
|
|
||||||
PropTypes: {
|
propTypes: {
|
||||||
stacktrace: PropTypes.array.isRequired,
|
stacktrace: PropTypes.array.isRequired,
|
||||||
onViewSourceInDebugger: PropTypes.func.isRequired,
|
onViewSourceInDebugger: PropTypes.func.isRequired,
|
||||||
onViewSourceInScratchpad: PropTypes.func.isRequired,
|
onViewSourceInScratchpad: PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
/* eslint-env browser */
|
/* eslint-env browser */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { DOM: dom, createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
|
const React = require("devtools/client/shared/vendor/react");
|
||||||
|
const { DOM: dom, createClass, createFactory, PropTypes } = React;
|
||||||
|
|
||||||
const AUTO_EXPAND_DEPTH = 0;
|
const AUTO_EXPAND_DEPTH = 0;
|
||||||
const NUMBER_OF_OFFSCREEN_ITEMS = 1;
|
const NUMBER_OF_OFFSCREEN_ITEMS = 1;
|
||||||
|
@ -630,6 +631,14 @@ module.exports = createClass({
|
||||||
const ArrowExpander = createFactory(createClass({
|
const ArrowExpander = createFactory(createClass({
|
||||||
displayName: "ArrowExpander",
|
displayName: "ArrowExpander",
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
item: PropTypes.any.isRequired,
|
||||||
|
visible: PropTypes.bool.isRequired,
|
||||||
|
expanded: PropTypes.bool.isRequired,
|
||||||
|
onCollapse: PropTypes.func.isRequired,
|
||||||
|
onExpand: PropTypes.func.isRequired,
|
||||||
|
},
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return this.props.item !== nextProps.item
|
return this.props.item !== nextProps.item
|
||||||
|| this.props.visible !== nextProps.visible
|
|| this.props.visible !== nextProps.visible
|
||||||
|
@ -659,6 +668,23 @@ const ArrowExpander = createFactory(createClass({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const TreeNode = createFactory(createClass({
|
const TreeNode = createFactory(createClass({
|
||||||
|
propTypes: {
|
||||||
|
focused: PropTypes.bool.isRequired,
|
||||||
|
onFocusedNodeUnmount: PropTypes.func,
|
||||||
|
item: PropTypes.any.isRequired,
|
||||||
|
expanded: PropTypes.bool.isRequired,
|
||||||
|
hasChildren: PropTypes.bool.isRequired,
|
||||||
|
onExpand: PropTypes.func.isRequired,
|
||||||
|
index: PropTypes.number.isRequired,
|
||||||
|
first: PropTypes.bool,
|
||||||
|
last: PropTypes.bool,
|
||||||
|
onFocus: PropTypes.func,
|
||||||
|
onBlur: PropTypes.func,
|
||||||
|
onCollapse: PropTypes.func.isRequired,
|
||||||
|
depth: PropTypes.number.isRequired,
|
||||||
|
renderItem: PropTypes.func.isRequired,
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.props.focused) {
|
if (this.props.focused) {
|
||||||
this.refs.button.focus();
|
this.refs.button.focus();
|
||||||
|
|
|
@ -21,9 +21,11 @@ add_task(function* () {
|
||||||
dir.append(TEST_FILE);
|
dir.append(TEST_FILE);
|
||||||
let uri = Services.io.newFileURI(dir);
|
let uri = Services.io.newFileURI(dir);
|
||||||
|
|
||||||
// We need a file remote type to make sure we don't switch processes when we
|
// Open tab with correct remote type so we don't switch processes when we load
|
||||||
// load the file:// URI.
|
// the file:// URI, otherwise we won't get the same web console.
|
||||||
let { browser } = yield loadTab("about:blank", E10SUtils.FILE_REMOTE_TYPE);
|
let remoteType = E10SUtils.getRemoteTypeForURI(uri.spec,
|
||||||
|
gMultiProcessBrowser);
|
||||||
|
let { browser } = yield loadTab("about:blank", remoteType);
|
||||||
|
|
||||||
hud = yield openConsole();
|
hud = yield openConsole();
|
||||||
hud.jsterm.clearOutput();
|
hud.jsterm.clearOutput();
|
||||||
|
|
|
@ -78,8 +78,8 @@ public:
|
||||||
if (mNormalIter && mTrackingIter &&
|
if (mNormalIter && mTrackingIter &&
|
||||||
mNormalIter != mNormalStopAt &&
|
mNormalIter != mNormalStopAt &&
|
||||||
mTrackingIter != mTrackingStopAt &&
|
mTrackingIter != mTrackingStopAt &&
|
||||||
(mTrackingIter->mWhen < mNormalIter->mWhen ||
|
(mTrackingIter->When() < mNormalIter->When() ||
|
||||||
(mTrackingIter->mWhen == mNormalIter->mWhen &&
|
(mTrackingIter->When() == mNormalIter->When() &&
|
||||||
mTrackingIter->mTimeoutId < mNormalIter->mTimeoutId))) {
|
mTrackingIter->mTimeoutId < mNormalIter->mTimeoutId))) {
|
||||||
timeout = mTrackingIter;
|
timeout = mTrackingIter;
|
||||||
mKind = Kind::Tracking;
|
mKind = Kind::Tracking;
|
||||||
|
|
|
@ -108,5 +108,54 @@ Timeout::HasRefCnt(uint32_t aCount) const
|
||||||
}
|
}
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeout::SetWhenOrTimeRemaining(const TimeStamp& aBaseTime,
|
||||||
|
const TimeDuration& aDelay)
|
||||||
|
{
|
||||||
|
// This must not be called on dummy timeouts. Instead use SetDummyWhen().
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mWindow);
|
||||||
|
|
||||||
|
// If we are frozen simply set mTimeRemaining to be the "time remaining" in
|
||||||
|
// the timeout (i.e., the interval itself). This will be used to create a
|
||||||
|
// new mWhen time when the window is thawed. The end effect is that time does
|
||||||
|
// not appear to pass for frozen windows.
|
||||||
|
if (mWindow->IsFrozen()) {
|
||||||
|
mWhen = TimeStamp();
|
||||||
|
mTimeRemaining = aDelay;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we are not frozen we must set a precise mWhen target wakeup
|
||||||
|
// time. Even if we are suspended we want to use this target time so
|
||||||
|
// that it appears time passes while suspended.
|
||||||
|
mWhen = aBaseTime + aDelay;
|
||||||
|
mTimeRemaining = TimeDuration(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Timeout::SetDummyWhen(const TimeStamp& aWhen)
|
||||||
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!mWindow);
|
||||||
|
mWhen = aWhen;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TimeStamp&
|
||||||
|
Timeout::When() const
|
||||||
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!mWhen.IsNull());
|
||||||
|
// Note, mWindow->IsFrozen() can be true here. The Freeze() method calls
|
||||||
|
// When() to calculate the delay to populate mTimeRemaining.
|
||||||
|
return mWhen;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TimeDuration&
|
||||||
|
Timeout::TimeRemaining() const
|
||||||
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mWhen.IsNull());
|
||||||
|
// Note, mWindow->IsFrozen() can be false here. The Thaw() method calls
|
||||||
|
// TimeRemaining() to calculate the new When() value.
|
||||||
|
return mTimeRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "nsPIDOMWindow.h"
|
|
||||||
|
|
||||||
class nsGlobalWindow;
|
class nsGlobalWindow;
|
||||||
class nsIEventTarget;
|
class nsIEventTarget;
|
||||||
|
@ -48,6 +47,17 @@ public:
|
||||||
bool HasRefCnt(uint32_t aCount) const;
|
bool HasRefCnt(uint32_t aCount) const;
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
|
void SetWhenOrTimeRemaining(const TimeStamp& aBaseTime,
|
||||||
|
const TimeDuration& aDelay);
|
||||||
|
|
||||||
|
void SetDummyWhen(const TimeStamp& aWhen);
|
||||||
|
|
||||||
|
// Can only be called when not frozen.
|
||||||
|
const TimeStamp& When() const;
|
||||||
|
|
||||||
|
// Can only be called when frozen.
|
||||||
|
const TimeDuration& TimeRemaining() const;
|
||||||
|
|
||||||
// Window for which this timeout fires
|
// Window for which this timeout fires
|
||||||
RefPtr<nsGlobalWindow> mWindow;
|
RefPtr<nsGlobalWindow> mWindow;
|
||||||
|
|
||||||
|
@ -71,14 +81,6 @@ public:
|
||||||
// Interval in milliseconds
|
// Interval in milliseconds
|
||||||
uint32_t mInterval;
|
uint32_t mInterval;
|
||||||
|
|
||||||
// mWhen and mTimeRemaining can't be in a union, sadly, because they
|
|
||||||
// have constructors.
|
|
||||||
// Nominal time to run this timeout. Use only when timeouts are not
|
|
||||||
// suspended.
|
|
||||||
TimeStamp mWhen;
|
|
||||||
// Remaining time to wait. Used only when timeouts are suspended.
|
|
||||||
TimeDuration mTimeRemaining;
|
|
||||||
|
|
||||||
// Principal with which to execute
|
// Principal with which to execute
|
||||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||||
|
|
||||||
|
@ -95,6 +97,14 @@ public:
|
||||||
nsCOMPtr<nsITimeoutHandler> mScriptHandler;
|
nsCOMPtr<nsITimeoutHandler> mScriptHandler;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// mWhen and mTimeRemaining can't be in a union, sadly, because they
|
||||||
|
// have constructors.
|
||||||
|
// Nominal time to run this timeout. Use only when timeouts are not
|
||||||
|
// frozen.
|
||||||
|
TimeStamp mWhen;
|
||||||
|
// Remaining time to wait. Used only when timeouts are frozen.
|
||||||
|
TimeDuration mTimeRemaining;
|
||||||
|
|
||||||
~Timeout();
|
~Timeout();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -177,24 +177,14 @@ TimeoutManager::SetTimeout(nsITimeoutHandler* aHandler,
|
||||||
realInterval = std::max(realInterval, uint32_t(DOMMinTimeoutValue()));
|
realInterval = std::max(realInterval, uint32_t(DOMMinTimeoutValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeDuration delta = TimeDuration::FromMilliseconds(realInterval);
|
timeout->mWindow = &mWindow;
|
||||||
|
|
||||||
if (mWindow.IsFrozen()) {
|
TimeDuration delta = TimeDuration::FromMilliseconds(realInterval);
|
||||||
// If we are frozen simply set timeout->mTimeRemaining to be the
|
timeout->SetWhenOrTimeRemaining(TimeStamp::Now(), delta);
|
||||||
// "time remaining" in the timeout (i.e., the interval itself). This
|
|
||||||
// will be used to create a new mWhen time when the window is thawed.
|
|
||||||
// The end effect is that time does not appear to pass for frozen windows.
|
|
||||||
timeout->mTimeRemaining = delta;
|
|
||||||
} else {
|
|
||||||
// Since we are not frozen we must set a precise mWhen target wakeup
|
|
||||||
// time. Even if we are suspended we want to use this target time so
|
|
||||||
// that it appears time passes while suspended.
|
|
||||||
timeout->mWhen = TimeStamp::Now() + delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're not suspended, then set the timer.
|
// If we're not suspended, then set the timer.
|
||||||
if (!mWindow.IsSuspended()) {
|
if (!mWindow.IsSuspended()) {
|
||||||
MOZ_ASSERT(!timeout->mWhen.IsNull());
|
MOZ_ASSERT(!timeout->When().IsNull());
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
timeout->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
timeout->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||||
|
@ -214,8 +204,6 @@ TimeoutManager::SetTimeout(nsITimeoutHandler* aHandler,
|
||||||
Unused << copy.forget();
|
Unused << copy.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout->mWindow = &mWindow;
|
|
||||||
|
|
||||||
if (!aIsInterval) {
|
if (!aIsInterval) {
|
||||||
timeout->mNestingLevel = nestingLevel;
|
timeout->mNestingLevel = nestingLevel;
|
||||||
}
|
}
|
||||||
|
@ -335,23 +323,23 @@ TimeoutManager::RunTimeout(Timeout* aTimeout)
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
TimeStamp deadline;
|
TimeStamp deadline;
|
||||||
|
|
||||||
if (aTimeout && aTimeout->mWhen > now) {
|
if (aTimeout && aTimeout->When() > now) {
|
||||||
// The OS timer fired early (which can happen due to the timers
|
// The OS timer fired early (which can happen due to the timers
|
||||||
// having lower precision than TimeStamp does). Set |deadline| to
|
// having lower precision than TimeStamp does). Set |deadline| to
|
||||||
// be the time when the OS timer *should* have fired so that any
|
// be the time when the OS timer *should* have fired so that any
|
||||||
// timers that *should* have fired before aTimeout *will* be fired
|
// timers that *should* have fired before aTimeout *will* be fired
|
||||||
// now.
|
// now.
|
||||||
|
|
||||||
deadline = aTimeout->mWhen;
|
deadline = aTimeout->When();
|
||||||
} else {
|
} else {
|
||||||
deadline = now;
|
deadline = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The timeout list is kept in deadline order. Discover the latest timeout
|
// The timeout list is kept in deadline order. Discover the latest timeout
|
||||||
// whose deadline has expired. On some platforms, native timeout events fire
|
// whose deadline has expired. On some platforms, native timeout events fire
|
||||||
// "early", but we handled that above by setting deadline to aTimeout->mWhen
|
// "early", but we handled that above by setting deadline to aTimeout->When()
|
||||||
// if the timer fired early. So we can stop walking if we get to timeouts
|
// if the timer fired early. So we can stop walking if we get to timeouts
|
||||||
// whose mWhen is greater than deadline, since once that happens we know
|
// whose When() is greater than deadline, since once that happens we know
|
||||||
// nothing past that point is expired.
|
// nothing past that point is expired.
|
||||||
{
|
{
|
||||||
// Use a nested scope in order to make sure the strong references held by
|
// Use a nested scope in order to make sure the strong references held by
|
||||||
|
@ -362,7 +350,7 @@ TimeoutManager::RunTimeout(Timeout* aTimeout)
|
||||||
nullptr);
|
nullptr);
|
||||||
while (true) {
|
while (true) {
|
||||||
Timeout* timeout = expiredIter.Next();
|
Timeout* timeout = expiredIter.Next();
|
||||||
if (!timeout || timeout->mWhen > deadline) {
|
if (!timeout || timeout->When() > deadline) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,14 +398,14 @@ TimeoutManager::RunTimeout(Timeout* aTimeout)
|
||||||
// list for any timeouts inserted as a result of running a timeout.
|
// list for any timeouts inserted as a result of running a timeout.
|
||||||
RefPtr<Timeout> dummy_normal_timeout = new Timeout();
|
RefPtr<Timeout> dummy_normal_timeout = new Timeout();
|
||||||
dummy_normal_timeout->mFiringDepth = firingDepth;
|
dummy_normal_timeout->mFiringDepth = firingDepth;
|
||||||
dummy_normal_timeout->mWhen = now;
|
dummy_normal_timeout->SetDummyWhen(now);
|
||||||
if (last_expired_timeout_is_normal) {
|
if (last_expired_timeout_is_normal) {
|
||||||
last_expired_normal_timeout->setNext(dummy_normal_timeout);
|
last_expired_normal_timeout->setNext(dummy_normal_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Timeout> dummy_tracking_timeout = new Timeout();
|
RefPtr<Timeout> dummy_tracking_timeout = new Timeout();
|
||||||
dummy_tracking_timeout->mFiringDepth = firingDepth;
|
dummy_tracking_timeout->mFiringDepth = firingDepth;
|
||||||
dummy_tracking_timeout->mWhen = now;
|
dummy_tracking_timeout->SetDummyWhen(now);
|
||||||
if (!last_expired_timeout_is_normal) {
|
if (!last_expired_timeout_is_normal) {
|
||||||
last_expired_tracking_timeout->setNext(dummy_tracking_timeout);
|
last_expired_tracking_timeout->setNext(dummy_tracking_timeout);
|
||||||
}
|
}
|
||||||
|
@ -702,7 +690,7 @@ TimeoutManager::RescheduleTimeout(Timeout* aTimeout, const TimeStamp& now,
|
||||||
if (aRunningPendingTimeouts) {
|
if (aRunningPendingTimeouts) {
|
||||||
firingTime = now + nextInterval;
|
firingTime = now + nextInterval;
|
||||||
} else {
|
} else {
|
||||||
firingTime = aTimeout->mWhen + nextInterval;
|
firingTime = aTimeout->When() + nextInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeStamp currentNow = TimeStamp::Now();
|
TimeStamp currentNow = TimeStamp::Now();
|
||||||
|
@ -715,26 +703,13 @@ TimeoutManager::RescheduleTimeout(Timeout* aTimeout, const TimeStamp& now,
|
||||||
delay = TimeDuration(0);
|
delay = TimeDuration(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aTimeout->SetWhenOrTimeRemaining(currentNow, delay);
|
||||||
|
|
||||||
if (!aTimeout->mTimer) {
|
if (!aTimeout->mTimer) {
|
||||||
if (mWindow.IsFrozen()) {
|
MOZ_DIAGNOSTIC_ASSERT(mWindow.IsFrozen() || mWindow.IsSuspended());
|
||||||
// If we are frozen simply set timeout->mTimeRemaining to be the
|
|
||||||
// "time remaining" in the timeout (i.e., the interval itself). This
|
|
||||||
// will be used to create a new mWhen time when the window is thawed.
|
|
||||||
// The end effect is that time does not appear to pass for frozen windows.
|
|
||||||
aTimeout->mTimeRemaining = delay;
|
|
||||||
} else if (mWindow.IsSuspended()) {
|
|
||||||
// Since we are not frozen we must set a precise mWhen target wakeup
|
|
||||||
// time. Even if we are suspended we want to use this target time so
|
|
||||||
// that it appears time passes while suspended.
|
|
||||||
aTimeout->mWhen = currentNow + delay;
|
|
||||||
} else {
|
|
||||||
MOZ_ASSERT_UNREACHABLE("Window should be frozen or suspended.");
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
aTimeout->mWhen = currentNow + delay;
|
|
||||||
|
|
||||||
// Reschedule the OS timer. Don't bother returning any error codes if
|
// Reschedule the OS timer. Don't bother returning any error codes if
|
||||||
// this fails since the callers of this method don't care about them.
|
// this fails since the callers of this method don't care about them.
|
||||||
nsresult rv = aTimeout->InitTimer(mWindow.EventTargetFor(TaskCategory::Timer),
|
nsresult rv = aTimeout->InitTimer(mWindow.EventTargetFor(TaskCategory::Timer),
|
||||||
|
@ -806,7 +781,7 @@ TimeoutManager::Timeouts::ResetTimersForThrottleReduction(int32_t aPreviousThrot
|
||||||
|
|
||||||
// If insertion point is non-null, we're in the middle of firing timers and
|
// If insertion point is non-null, we're in the middle of firing timers and
|
||||||
// the timers we're planning to fire all come before insertion point;
|
// the timers we're planning to fire all come before insertion point;
|
||||||
// insertion point itself is a dummy timeout with an mWhen that may be
|
// insertion point itself is a dummy timeout with an When() that may be
|
||||||
// semi-bogus. In that case, we don't need to do anything with insertion
|
// semi-bogus. In that case, we don't need to do anything with insertion
|
||||||
// point or anything before it, so should start at the timer after insertion
|
// point or anything before it, so should start at the timer after insertion
|
||||||
// point, if there is one.
|
// point, if there is one.
|
||||||
|
@ -816,15 +791,15 @@ TimeoutManager::Timeouts::ResetTimersForThrottleReduction(int32_t aPreviousThrot
|
||||||
timeout; ) {
|
timeout; ) {
|
||||||
// It's important that this check be <= so that we guarantee that
|
// It's important that this check be <= so that we guarantee that
|
||||||
// taking std::max with |now| won't make a quantity equal to
|
// taking std::max with |now| won't make a quantity equal to
|
||||||
// timeout->mWhen below.
|
// timeout->When() below.
|
||||||
if (timeout->mWhen <= now) {
|
if (timeout->When() <= now) {
|
||||||
timeout = timeout->getNext();
|
timeout = timeout->getNext();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout->mWhen - now >
|
if (timeout->When() - now >
|
||||||
TimeDuration::FromMilliseconds(aPreviousThrottleDelayMS)) {
|
TimeDuration::FromMilliseconds(aPreviousThrottleDelayMS)) {
|
||||||
// No need to loop further. Timeouts are sorted in mWhen order
|
// No need to loop further. Timeouts are sorted in When() order
|
||||||
// and the ones after this point were all set up for at least
|
// and the ones after this point were all set up for at least
|
||||||
// gMinBackgroundTimeoutValue ms and hence were not clamped.
|
// gMinBackgroundTimeoutValue ms and hence were not clamped.
|
||||||
break;
|
break;
|
||||||
|
@ -842,26 +817,27 @@ TimeoutManager::Timeouts::ResetTimersForThrottleReduction(int32_t aPreviousThrot
|
||||||
if (oldInterval > interval) {
|
if (oldInterval > interval) {
|
||||||
// unclamp
|
// unclamp
|
||||||
TimeStamp firingTime =
|
TimeStamp firingTime =
|
||||||
std::max(timeout->mWhen - oldInterval + interval, now);
|
std::max(timeout->When() - oldInterval + interval, now);
|
||||||
|
|
||||||
NS_ASSERTION(firingTime < timeout->mWhen,
|
NS_ASSERTION(firingTime < timeout->When(),
|
||||||
"Our firing time should strictly decrease!");
|
"Our firing time should strictly decrease!");
|
||||||
|
|
||||||
TimeDuration delay = firingTime - now;
|
TimeDuration delay = firingTime - now;
|
||||||
timeout->mWhen = firingTime;
|
timeout->SetWhenOrTimeRemaining(now, delay);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(timeout->When() == firingTime);
|
||||||
|
|
||||||
// Since we reset mWhen we need to move |timeout| to the right
|
// Since we reset When() we need to move |timeout| to the right
|
||||||
// place in the list so that it remains sorted by mWhen.
|
// place in the list so that it remains sorted by When().
|
||||||
|
|
||||||
// Get the pointer to the next timeout now, before we move the
|
// Get the pointer to the next timeout now, before we move the
|
||||||
// current timeout in the list.
|
// current timeout in the list.
|
||||||
Timeout* nextTimeout = timeout->getNext();
|
Timeout* nextTimeout = timeout->getNext();
|
||||||
|
|
||||||
// It is safe to remove and re-insert because mWhen is now
|
// It is safe to remove and re-insert because When() is now
|
||||||
// strictly smaller than it used to be, so we know we'll insert
|
// strictly smaller than it used to be, so we know we'll insert
|
||||||
// |timeout| before nextTimeout.
|
// |timeout| before nextTimeout.
|
||||||
NS_ASSERTION(!nextTimeout ||
|
NS_ASSERTION(!nextTimeout ||
|
||||||
timeout->mWhen < nextTimeout->mWhen, "How did that happen?");
|
timeout->When() < nextTimeout->When(), "How did that happen?");
|
||||||
timeout->remove();
|
timeout->remove();
|
||||||
// Insert() will addref |timeout| and reset mFiringDepth. Make sure to
|
// Insert() will addref |timeout| and reset mFiringDepth. Make sure to
|
||||||
// undo that after calling it.
|
// undo that after calling it.
|
||||||
|
@ -937,10 +913,10 @@ TimeoutManager::Timeouts::Insert(Timeout* aTimeout, SortBy aSortBy)
|
||||||
for (prevSibling = GetLast();
|
for (prevSibling = GetLast();
|
||||||
prevSibling && prevSibling != InsertionPoint() &&
|
prevSibling && prevSibling != InsertionPoint() &&
|
||||||
// This condition needs to match the one in SetTimeoutOrInterval that
|
// This condition needs to match the one in SetTimeoutOrInterval that
|
||||||
// determines whether to set mWhen or mTimeRemaining.
|
// determines whether to set When() or TimeRemaining().
|
||||||
(aSortBy == SortBy::TimeRemaining ?
|
(aSortBy == SortBy::TimeRemaining ?
|
||||||
prevSibling->mTimeRemaining > aTimeout->mTimeRemaining :
|
prevSibling->TimeRemaining() > aTimeout->TimeRemaining() :
|
||||||
prevSibling->mWhen > aTimeout->mWhen);
|
prevSibling->When() > aTimeout->When());
|
||||||
prevSibling = prevSibling->getPrevious()) {
|
prevSibling = prevSibling->getPrevious()) {
|
||||||
/* Do nothing; just searching */
|
/* Do nothing; just searching */
|
||||||
}
|
}
|
||||||
|
@ -1028,15 +1004,15 @@ TimeoutManager::Resume()
|
||||||
|
|
||||||
MOZ_ASSERT(!aTimeout->mTimer);
|
MOZ_ASSERT(!aTimeout->mTimer);
|
||||||
|
|
||||||
// The timeout mWhen is set to the absolute time when the timer should
|
// The timeout When() is set to the absolute time when the timer should
|
||||||
// fire. Recalculate the delay from now until that deadline. If the
|
// fire. Recalculate the delay from now until that deadline. If the
|
||||||
// the deadline has already passed or falls within our minimum delay
|
// the deadline has already passed or falls within our minimum delay
|
||||||
// deadline, then clamp the resulting value to the minimum delay. The
|
// deadline, then clamp the resulting value to the minimum delay. The
|
||||||
// mWhen will remain at its absolute time, but we won'aTimeout fire the OS
|
// When() will remain at its absolute time, but we won'aTimeout fire the OS
|
||||||
// timer until our calculated delay has passed.
|
// timer until our calculated delay has passed.
|
||||||
int32_t remaining = 0;
|
int32_t remaining = 0;
|
||||||
if (aTimeout->mWhen > now) {
|
if (aTimeout->When() > now) {
|
||||||
remaining = static_cast<int32_t>((aTimeout->mWhen - now).ToMilliseconds());
|
remaining = static_cast<int32_t>((aTimeout->When() - now).ToMilliseconds());
|
||||||
}
|
}
|
||||||
uint32_t delay = std::max(remaining, DOMMinTimeoutValue());
|
uint32_t delay = std::max(remaining, DOMMinTimeoutValue());
|
||||||
|
|
||||||
|
@ -1068,11 +1044,12 @@ TimeoutManager::Freeze()
|
||||||
// re-apply it when the window is Thaw()'d. This effectively
|
// re-apply it when the window is Thaw()'d. This effectively
|
||||||
// shifts timers to the right as if time does not pass while
|
// shifts timers to the right as if time does not pass while
|
||||||
// the window is frozen.
|
// the window is frozen.
|
||||||
if (aTimeout->mWhen > now) {
|
TimeDuration delta(0);
|
||||||
aTimeout->mTimeRemaining = aTimeout->mWhen - now;
|
if (aTimeout->When() > now) {
|
||||||
} else {
|
delta = aTimeout->When() - now;
|
||||||
aTimeout->mTimeRemaining = TimeDuration(0);
|
|
||||||
}
|
}
|
||||||
|
aTimeout->SetWhenOrTimeRemaining(now, delta);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aTimeout->TimeRemaining() == delta);
|
||||||
|
|
||||||
// Since we are suspended there should be no OS timer set for
|
// Since we are suspended there should be no OS timer set for
|
||||||
// this timeout entry.
|
// this timeout entry.
|
||||||
|
@ -1096,8 +1073,9 @@ TimeoutManager::Thaw()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set mWhen back to the time when the timer is supposed to fire.
|
// Set When() back to the time when the timer is supposed to fire.
|
||||||
aTimeout->mWhen = now + aTimeout->mTimeRemaining;
|
aTimeout->SetWhenOrTimeRemaining(now, aTimeout->TimeRemaining());
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!aTimeout->When().IsNull());
|
||||||
|
|
||||||
MOZ_ASSERT(!aTimeout->mTimer);
|
MOZ_ASSERT(!aTimeout->mTimer);
|
||||||
});
|
});
|
||||||
|
|
|
@ -874,9 +874,6 @@ nsOuterWindowProxy::getOwnPropertyDescriptor(JSContext* cx,
|
||||||
}
|
}
|
||||||
// else fall through to js::Wrapper
|
// else fall through to js::Wrapper
|
||||||
|
|
||||||
// When we change this to always claim the property is configurable (bug
|
|
||||||
// 1178639), update the comments in nsOuterWindowProxy::defineProperty
|
|
||||||
// accordingly.
|
|
||||||
return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
|
return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,29 +891,6 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
|
||||||
return result.failCantDefineWindowElement();
|
return result.failCantDefineWindowElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef RELEASE_OR_BETA // To be turned on in bug 1178638.
|
|
||||||
// For now, allow chrome code to define non-configurable properties
|
|
||||||
// on windows, until we sort out what exactly the addon SDK is
|
|
||||||
// doing. In the meantime, this still allows us to test web compat
|
|
||||||
// behavior.
|
|
||||||
if (desc.hasConfigurable() && !desc.configurable() &&
|
|
||||||
!nsContentUtils::IsCallerChrome()) {
|
|
||||||
return ThrowErrorMessage(cx, MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that if hasConfigurable() is false we do NOT want to
|
|
||||||
// setConfigurable(true). That would make this code:
|
|
||||||
//
|
|
||||||
// var x;
|
|
||||||
// window.x = 5;
|
|
||||||
//
|
|
||||||
// fail, because the JS engine ends up converting the assignment into a define
|
|
||||||
// with !hasConfigurable(), but the var actually declared a non-configurable
|
|
||||||
// property on our underlying Window object, so the set would fail if we
|
|
||||||
// forced setConfigurable(true) here. What we want to do instead is change
|
|
||||||
// getOwnPropertyDescriptor to always claim configurable. See bug 1178639.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
|
return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -779,7 +779,6 @@ skip-if = toolkit == 'android'
|
||||||
[test_window_constructor.html]
|
[test_window_constructor.html]
|
||||||
[test_window_cross_origin_props.html]
|
[test_window_cross_origin_props.html]
|
||||||
[test_window_define_nonconfigurable.html]
|
[test_window_define_nonconfigurable.html]
|
||||||
skip-if = release_or_beta
|
|
||||||
[test_window_define_symbol.html]
|
[test_window_define_symbol.html]
|
||||||
[test_window_element_enumeration.html]
|
[test_window_element_enumeration.html]
|
||||||
[test_window_enumeration.html]
|
[test_window_enumeration.html]
|
||||||
|
|
|
@ -10,31 +10,78 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1107443
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
|
|
||||||
/** Test for Bug 1107443 **/
|
/**
|
||||||
try {
|
* Test for Bug 1107443, modified when it was backed out in bug 1329323.
|
||||||
Object.defineProperty(window, "nosuchprop", { value: 5, configurable: false });
|
* This is now testing the _current_ behavior, not the desired one; expect
|
||||||
throw "didn't throw";
|
* failures in this test and needing to update it when bug 1329324 is
|
||||||
} catch (e) {
|
* fixed.
|
||||||
is(e instanceof TypeError, true,
|
*/
|
||||||
"defineProperty(window) with a non-configurable property should " +
|
var retval = Object.defineProperty(window, "nosuchprop",
|
||||||
"throw a TypeError, instead got: " + e);
|
{ value: 5, configurable: false });
|
||||||
is(Object.getOwnPropertyDescriptor(window, "nosuchprop"), undefined,
|
todo_is(retval, false,
|
||||||
'Window should not have property after an attempt to define it failed');
|
"Should return false when 'failing' to define non-configurable property via Object.defineProperty.")
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(window, "nosuchprop", { value: 6 });
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(window, "nosuchprop");
|
var desc = Object.getOwnPropertyDescriptor(window, "nosuchprop");
|
||||||
is(typeof(desc), "object", "Should have a property now");
|
is(typeof(desc), "object", "Should have a property 'nosuchprop' now");
|
||||||
todo_is(desc.configurable, true, "Property should be configurable");
|
todo_is(desc.configurable, true,
|
||||||
is(desc.writable, false, "Property should be readonly");
|
"Property 'nosuchprop' should be configurable");
|
||||||
is(desc.value, 6, "Property should have the right value");
|
is(desc.writable, false, "Property 'nosuchprop' should be readonly");
|
||||||
|
is(desc.value, 5, "Property 'nosuchprop' should have the right value");
|
||||||
|
|
||||||
Object.defineProperty(window, "nosuchprop2", { value: 7, configurable: true });
|
retval = Object.defineProperty(window, "nosuchprop2", { value: 6 });
|
||||||
|
is(retval, window,
|
||||||
|
"Should return object when succesfully defining 'nosuchprop2'");
|
||||||
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop2");
|
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop2");
|
||||||
is(typeof(desc), "object", "Should have a property now");
|
is(typeof(desc), "object", "Should have a property 'nosuchprop2' now");
|
||||||
is(desc.configurable, true, "Property should be configurable");
|
todo_is(desc.configurable, true,
|
||||||
is(desc.writable, false, "Property should be readonly");
|
"Property 'nosuchprop2' should be configurable");
|
||||||
is(desc.value, 7, "Property should have the right value");
|
is(desc.writable, false, "Property 'nosuchprop2' should be readonly");
|
||||||
|
is(desc.value, 6, "Property 'nosuchprop2' should have the right value");
|
||||||
|
|
||||||
|
retval = Object.defineProperty(window, "nosuchprop3",
|
||||||
|
{ value: 7, configurable: true });
|
||||||
|
is(retval, window,
|
||||||
|
"Should return object when succesfully defining 'nosuchprop3'");
|
||||||
|
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop3");
|
||||||
|
is(typeof(desc), "object", "Should have a property 'nosuchprop3' now");
|
||||||
|
is(desc.configurable, true,
|
||||||
|
"Property 'nosuchprop3' should be configurable");
|
||||||
|
is(desc.writable, false, "Property 'nosuchprop3' should be readonly");
|
||||||
|
is(desc.value, 7, "Property 'nosuchprop3' should have the right value");
|
||||||
|
|
||||||
|
// XXXbz it's not actually entirely clear what behavior the
|
||||||
|
// Reflect.defineProperty bits should have. Check it carefully once there's a
|
||||||
|
// spec.
|
||||||
|
retval = Reflect.defineProperty(window, "nosuchprop4",
|
||||||
|
{ value: 8, configurable: false });
|
||||||
|
todo_is(retval, false,
|
||||||
|
"Should not be able to Reflect.defineProperty if non-configurable");
|
||||||
|
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop4");
|
||||||
|
is(typeof(desc), "object", "Should have a property 'nosuchprop4' now");
|
||||||
|
todo_is(desc.configurable, true,
|
||||||
|
"Property 'nosuchprop4' should be configurable");
|
||||||
|
is(desc.writable, false, "Property 'nosuchprop4' should be readonly");
|
||||||
|
is(desc.value, 8, "Property 'nosuchprop4' should have the right value");
|
||||||
|
|
||||||
|
retval = Reflect.defineProperty(window, "nosuchprop5",
|
||||||
|
{ value: 9 });
|
||||||
|
is(retval, true,
|
||||||
|
"Should be able to Reflect.defineProperty with default configurability");
|
||||||
|
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop5");
|
||||||
|
is(typeof(desc), "object", "Should have a property 'nosuchprop5' now");
|
||||||
|
todo_is(desc.configurable, true,
|
||||||
|
"Property 'nosuchprop5' should be configurable");
|
||||||
|
is(desc.writable, false, "Property 'nosuchprop5' should be readonly");
|
||||||
|
is(desc.value, 9, "Property 'nosuchprop5' should have the right value");
|
||||||
|
|
||||||
|
retval = Reflect.defineProperty(window, "nosuchprop6",
|
||||||
|
{ value: 10, configurable: true });
|
||||||
|
is(retval, true,
|
||||||
|
"Should be able to Reflect.defineProperty if configurable");
|
||||||
|
desc = Object.getOwnPropertyDescriptor(window, "nosuchprop6");
|
||||||
|
is(typeof(desc), "object", "Should have a property 'nosuchprop6' now");
|
||||||
|
is(desc.configurable, true, "Property 'nosuchprop6' should be configurable");
|
||||||
|
is(desc.writable, false, "Property 'nosuchprop6' should be readonly");
|
||||||
|
is(desc.value, 10, "Property 'nosuchprop6' should have the right value");
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -1375,10 +1375,16 @@ def UnionTypes(unionTypes, config):
|
||||||
# And if it needs rooting, we need RootedDictionary too
|
# And if it needs rooting, we need RootedDictionary too
|
||||||
if typeNeedsRooting(f):
|
if typeNeedsRooting(f):
|
||||||
headers.add("mozilla/dom/RootedDictionary.h")
|
headers.add("mozilla/dom/RootedDictionary.h")
|
||||||
|
elif f.isFloat() and not f.isUnrestricted():
|
||||||
|
# Restricted floats are tested for finiteness
|
||||||
|
implheaders.add("mozilla/FloatingPoint.h")
|
||||||
|
implheaders.add("mozilla/dom/PrimitiveConversions.h")
|
||||||
elif f.isEnum():
|
elif f.isEnum():
|
||||||
# Need to see the actual definition of the enum,
|
# Need to see the actual definition of the enum,
|
||||||
# unfortunately.
|
# unfortunately.
|
||||||
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
||||||
|
elif f.isPrimitive():
|
||||||
|
implheaders.add("mozilla/dom/PrimitiveConversions.h")
|
||||||
elif f.isCallback():
|
elif f.isCallback():
|
||||||
# Callbacks always use strong refs, so we need to include
|
# Callbacks always use strong refs, so we need to include
|
||||||
# the right header to be able to Release() in our inlined
|
# the right header to be able to Release() in our inlined
|
||||||
|
@ -1446,6 +1452,10 @@ def UnionConversions(unionTypes, config):
|
||||||
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
||||||
elif f.isDictionary():
|
elif f.isDictionary():
|
||||||
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
||||||
|
elif f.isFloat() and not f.isUnrestricted():
|
||||||
|
# Restricted floats are tested for finiteness
|
||||||
|
headers.add("mozilla/FloatingPoint.h")
|
||||||
|
headers.add("mozilla/dom/PrimitiveConversions.h")
|
||||||
elif f.isPrimitive():
|
elif f.isPrimitive():
|
||||||
headers.add("mozilla/dom/PrimitiveConversions.h")
|
headers.add("mozilla/dom/PrimitiveConversions.h")
|
||||||
elif f.isMozMap():
|
elif f.isMozMap():
|
||||||
|
@ -16786,7 +16796,6 @@ class GlobalGenRoots():
|
||||||
# If it stops being inlined or stops calling CallerSubsumes
|
# If it stops being inlined or stops calling CallerSubsumes
|
||||||
# both this bit and the bit in CGBindingRoot can be removed.
|
# both this bit and the bit in CGBindingRoot can be removed.
|
||||||
includes.add("mozilla/dom/BindingUtils.h")
|
includes.add("mozilla/dom/BindingUtils.h")
|
||||||
implincludes.add("mozilla/dom/PrimitiveConversions.h")
|
|
||||||
|
|
||||||
# Wrap all of that in our namespaces.
|
# Wrap all of that in our namespaces.
|
||||||
curr = CGNamespace.build(['mozilla', 'dom'], unions)
|
curr = CGNamespace.build(['mozilla', 'dom'], unions)
|
||||||
|
|
|
@ -100,3 +100,4 @@ MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the suppo
|
||||||
MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
|
MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
|
||||||
MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
|
MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
|
||||||
MSG_DEF(MSG_WORKER_THREAD_SHUTTING_DOWN, 0, JSEXN_TYPEERR, "The Worker thread is shutting down.")
|
MSG_DEF(MSG_WORKER_THREAD_SHUTTING_DOWN, 0, JSEXN_TYPEERR, "The Worker thread is shutting down.")
|
||||||
|
MSG_DEF(MSG_CACHE_OPEN_FAILED, 0, JSEXN_TYPEERR, "CacheStorage.open() failed to access the storage system.")
|
||||||
|
|
|
@ -51,21 +51,12 @@ struct GCPolicy<mozilla::OwningNonNull<T>>
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
template<typename T>
|
template<typename T, typename Wrapper>
|
||||||
struct RootedBase<mozilla::OwningNonNull<T>>
|
struct WrappedPtrOperations<mozilla::OwningNonNull<T>, Wrapper>
|
||||||
{
|
{
|
||||||
typedef mozilla::OwningNonNull<T> SmartPtrType;
|
|
||||||
|
|
||||||
operator SmartPtrType& () const
|
|
||||||
{
|
|
||||||
auto& self = *static_cast<const JS::Rooted<SmartPtrType>*>(this);
|
|
||||||
return self.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
operator T& () const
|
operator T& () const
|
||||||
{
|
{
|
||||||
auto& self = *static_cast<const JS::Rooted<SmartPtrType>*>(this);
|
return static_cast<const Wrapper*>(this)->get();
|
||||||
return self.get();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
|
@ -39,19 +39,12 @@ struct GCPolicy<RefPtr<T>>
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
template<typename T>
|
template<typename T, typename Wrapper>
|
||||||
struct RootedBase<RefPtr<T>>
|
struct WrappedPtrOperations<RefPtr<T>, Wrapper>
|
||||||
{
|
{
|
||||||
operator RefPtr<T>& () const
|
|
||||||
{
|
|
||||||
auto& self = *static_cast<const JS::Rooted<RefPtr<T>>*>(this);
|
|
||||||
return self.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
operator T*() const
|
operator T*() const
|
||||||
{
|
{
|
||||||
auto& self = *static_cast<const JS::Rooted<RefPtr<T>>*>(this);
|
return static_cast<const Wrapper*>(this)->get();
|
||||||
return self.get();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
|
@ -155,6 +155,17 @@ CacheOpChild::Recv__delete__(const ErrorResult& aRv,
|
||||||
{
|
{
|
||||||
auto actor = static_cast<CacheChild*>(
|
auto actor = static_cast<CacheChild*>(
|
||||||
aResult.get_StorageOpenResult().actorChild());
|
aResult.get_StorageOpenResult().actorChild());
|
||||||
|
|
||||||
|
// If we have a success status then we should have an actor. Gracefully
|
||||||
|
// reject instead of crashing, though, if we get a nullptr here.
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(actor);
|
||||||
|
if (!actor) {
|
||||||
|
ErrorResult status;
|
||||||
|
status.ThrowTypeError<MSG_CACHE_OPEN_FAILED>();
|
||||||
|
mPromise->MaybeReject(status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
actor->SetWorkerHolder(GetWorkerHolder());
|
actor->SetWorkerHolder(GetWorkerHolder());
|
||||||
RefPtr<Cache> cache = new Cache(mGlobal, actor);
|
RefPtr<Cache> cache = new Cache(mGlobal, actor);
|
||||||
mPromise->MaybeResolve(cache);
|
mPromise->MaybeResolve(cache);
|
||||||
|
|
|
@ -501,6 +501,8 @@ void
|
||||||
CacheStorage::ActorCreated(PBackgroundChild* aActor)
|
CacheStorage::ActorCreated(PBackgroundChild* aActor)
|
||||||
{
|
{
|
||||||
NS_ASSERT_OWNINGTHREAD(CacheStorage);
|
NS_ASSERT_OWNINGTHREAD(CacheStorage);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(mStatus));
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!mActor);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aActor);
|
MOZ_DIAGNOSTIC_ASSERT(aActor);
|
||||||
|
|
||||||
if (NS_WARN_IF(mWorkerHolder && mWorkerHolder->Notified())) {
|
if (NS_WARN_IF(mWorkerHolder && mWorkerHolder->Notified())) {
|
||||||
|
@ -511,19 +513,22 @@ CacheStorage::ActorCreated(PBackgroundChild* aActor)
|
||||||
// WorkerHolder ownership is passed to the CacheStorageChild actor and any
|
// WorkerHolder ownership is passed to the CacheStorageChild actor and any
|
||||||
// actors it may create. The WorkerHolder will keep the worker thread alive
|
// actors it may create. The WorkerHolder will keep the worker thread alive
|
||||||
// until the actors can gracefully shutdown.
|
// until the actors can gracefully shutdown.
|
||||||
CacheStorageChild* newActor = new CacheStorageChild(this, mWorkerHolder);
|
mActor = new CacheStorageChild(this, mWorkerHolder);
|
||||||
PCacheStorageChild* constructedActor =
|
mWorkerHolder = nullptr;
|
||||||
aActor->SendPCacheStorageConstructor(newActor, mNamespace, *mPrincipalInfo);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!constructedActor)) {
|
// Pass the actor construction message to the parent. Note, if this fails
|
||||||
ActorFailed();
|
// we can get DestroyInternal() and ActorFailed() called synchronously. This
|
||||||
|
// will null out mActor and set an error mStatus.
|
||||||
|
PCacheStorageChild* constructedActor =
|
||||||
|
aActor->SendPCacheStorageConstructor(mActor, mNamespace, *mPrincipalInfo);
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(mStatus))) {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!mActor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mWorkerHolder = nullptr;
|
MOZ_DIAGNOSTIC_ASSERT(mActor);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(constructedActor == mActor);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(constructedActor == newActor);
|
|
||||||
mActor = newActor;
|
|
||||||
|
|
||||||
MaybeRunPendingRequests();
|
MaybeRunPendingRequests();
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mPendingRequests.IsEmpty());
|
MOZ_DIAGNOSTIC_ASSERT(mPendingRequests.IsEmpty());
|
||||||
|
@ -533,7 +538,7 @@ void
|
||||||
CacheStorage::ActorFailed()
|
CacheStorage::ActorFailed()
|
||||||
{
|
{
|
||||||
NS_ASSERT_OWNINGTHREAD(CacheStorage);
|
NS_ASSERT_OWNINGTHREAD(CacheStorage);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!NS_FAILED(mStatus));
|
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(mStatus));
|
||||||
|
|
||||||
mStatus = NS_ERROR_UNEXPECTED;
|
mStatus = NS_ERROR_UNEXPECTED;
|
||||||
mWorkerHolder = nullptr;
|
mWorkerHolder = nullptr;
|
||||||
|
|
|
@ -85,6 +85,11 @@ CacheStreamControlParent::ActorDestroy(ActorDestroyReason aReason)
|
||||||
{
|
{
|
||||||
NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
|
NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
|
||||||
CloseAllReadStreamsWithoutReporting();
|
CloseAllReadStreamsWithoutReporting();
|
||||||
|
// If the initial SendPStreamControlConstructor() fails we will
|
||||||
|
// be called before mStreamList is set.
|
||||||
|
if (!mStreamList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mStreamList->RemoveStreamControl(this);
|
mStreamList->RemoveStreamControl(this);
|
||||||
mStreamList->NoteClosedAll();
|
mStreamList->NoteClosedAll();
|
||||||
mStreamList = nullptr;
|
mStreamList = nullptr;
|
||||||
|
|
|
@ -1215,6 +1215,7 @@ public:
|
||||||
&cacheFound, &mCacheId);
|
&cacheFound, &mCacheId);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||||
if (cacheFound) {
|
if (cacheFound) {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mCacheId != INVALID_CACHE_ID);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,12 +1228,14 @@ public:
|
||||||
rv = trans.Commit();
|
rv = trans.Commit();
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mCacheId != INVALID_CACHE_ID);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
Complete(Listener* aListener, ErrorResult&& aRv) override
|
Complete(Listener* aListener, ErrorResult&& aRv) override
|
||||||
{
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aRv.Failed() || mCacheId != INVALID_CACHE_ID);
|
||||||
aListener->OnOpComplete(Move(aRv), StorageOpenResult(), mCacheId);
|
aListener->OnOpComplete(Move(aRv), StorageOpenResult(), mCacheId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1292,6 +1292,7 @@ CrossProcessSafeEvent(const WidgetEvent& aEvent)
|
||||||
case eContextMenu:
|
case eContextMenu:
|
||||||
case eMouseEnterIntoWidget:
|
case eMouseEnterIntoWidget:
|
||||||
case eMouseExitFromWidget:
|
case eMouseExitFromWidget:
|
||||||
|
case eMouseTouchDrag:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -193,6 +193,39 @@ uint32_t
|
||||||
GetMajorStorageVersion(int32_t aStorageVersion)
|
GetMajorStorageVersion(int32_t aStorageVersion)
|
||||||
{
|
{
|
||||||
return uint32_t(aStorageVersion >> 16);
|
return uint32_t(aStorageVersion >> 16);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CreateTables(mozIStorageConnection* aConnection)
|
||||||
|
{
|
||||||
|
AssertIsOnIOThread();
|
||||||
|
MOZ_ASSERT(aConnection);
|
||||||
|
|
||||||
|
// The database doesn't have any tables for now. It's only used for storage
|
||||||
|
// version checking.
|
||||||
|
// However, this is the place where any future tables should be created.
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
int32_t storageVersion;
|
||||||
|
rv = aConnection->GetSchemaVersion(&storageVersion);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(storageVersion == 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rv = aConnection->SetSchemaVersion(kStorageVersion);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -4094,12 +4127,25 @@ QuotaManager::MaybeRemoveOldDirectories()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
QuotaManager::UpgradeStorageFrom0ToCurrent(mozIStorageConnection* aConnection)
|
QuotaManager::UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
MOZ_ASSERT(aConnection);
|
MOZ_ASSERT(aConnection);
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv = MaybeUpgradeIndexedDBDirectory();
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = MaybeUpgradePersistentStorageDirectory();
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = MaybeRemoveOldDirectories();
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
for (const PersistenceType persistenceType : kAllPersistenceTypes) {
|
for (const PersistenceType persistenceType : kAllPersistenceTypes) {
|
||||||
nsCOMPtr<nsIFile> directory =
|
nsCOMPtr<nsIFile> directory =
|
||||||
|
@ -4145,12 +4191,26 @@ QuotaManager::UpgradeStorageFrom0ToCurrent(mozIStorageConnection* aConnection)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
nsresult
|
nsresult
|
||||||
QuotaManager::UpgradeStorageFrom1To2(mozIStorageConnection* aConnection)
|
QuotaManager::UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection)
|
||||||
{
|
{
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
MOZ_ASSERT(aConnection);
|
MOZ_ASSERT(aConnection);
|
||||||
|
|
||||||
nsresult rv = aConnection->SetSchemaVersion(MakeStorageVersion(2, 0));
|
nsresult rv;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
int32_t storageVersion;
|
||||||
|
rv = aConnection->GetSchemaVersion(&storageVersion);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(storageVersion == MakeStorageVersion(1, 0));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rv = aConnection->SetSchemaVersion(MakeStorageVersion(2, 0));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -4231,6 +4291,43 @@ QuotaManager::EnsureStorageIsInitialized()
|
||||||
if (storageVersion < kStorageVersion) {
|
if (storageVersion < kStorageVersion) {
|
||||||
const bool newDatabase = !storageVersion;
|
const bool newDatabase = !storageVersion;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> storageDir =
|
||||||
|
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = storageDir->InitWithPath(mStoragePath);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool exists;
|
||||||
|
rv = storageDir->Exists(&exists);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
nsCOMPtr<nsIFile> indexedDBDir =
|
||||||
|
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = indexedDBDir->InitWithPath(mIndexedDBPath);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = indexedDBDir->Exists(&exists);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool newDirectory = !exists;
|
||||||
|
|
||||||
if (newDatabase) {
|
if (newDatabase) {
|
||||||
// Set the page size first.
|
// Set the page size first.
|
||||||
if (kSQLitePageSizeOverride) {
|
if (kSQLitePageSizeOverride) {
|
||||||
|
@ -4245,23 +4342,12 @@ QuotaManager::EnsureStorageIsInitialized()
|
||||||
|
|
||||||
mozStorageTransaction transaction(connection, false,
|
mozStorageTransaction transaction(connection, false,
|
||||||
mozIStorageConnection::TRANSACTION_IMMEDIATE);
|
mozIStorageConnection::TRANSACTION_IMMEDIATE);
|
||||||
if (newDatabase) {
|
|
||||||
rv = MaybeUpgradeIndexedDBDirectory();
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = MaybeUpgradePersistentStorageDirectory();
|
// An upgrade method can upgrade the database, the storage or both.
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
// The upgrade loop below can only be avoided when there's no database and
|
||||||
return rv;
|
// no storage yet (e.g. new profile).
|
||||||
}
|
if (newDatabase && newDirectory) {
|
||||||
|
rv = CreateTables(connection);
|
||||||
rv = MaybeRemoveOldDirectories();
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = UpgradeStorageFrom0ToCurrent(connection);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -4274,9 +4360,13 @@ QuotaManager::EnsureStorageIsInitialized()
|
||||||
"Upgrade function needed due to storage version increase.");
|
"Upgrade function needed due to storage version increase.");
|
||||||
|
|
||||||
while (storageVersion != kStorageVersion) {
|
while (storageVersion != kStorageVersion) {
|
||||||
/* if (storageVersion == MakeStorageVersion(1, 0)) {
|
if (storageVersion == 0) {
|
||||||
rv = UpgradeStorageFrom1To2(connection);
|
rv = UpgradeStorageFrom0_0To1_0(connection);
|
||||||
} else */ {
|
#if 0
|
||||||
|
} else if (storageVersion == MakeStorageVersion(1, 0)) {
|
||||||
|
rv = UpgradeStorageFrom1_0To2_0(connection);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
NS_WARNING("Unable to initialize storage, no upgrade path is "
|
NS_WARNING("Unable to initialize storage, no upgrade path is "
|
||||||
"available!");
|
"available!");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
|
@ -455,11 +455,11 @@ private:
|
||||||
MaybeRemoveOldDirectories();
|
MaybeRemoveOldDirectories();
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
UpgradeStorageFrom0ToCurrent(mozIStorageConnection* aConnection);
|
UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
nsresult
|
nsresult
|
||||||
UpgradeStorageFrom1To2(mozIStorageConnection* aConnection);
|
UpgradeStorageFrom1_0To2_0(mozIStorageConnection* aConnection);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -1579,13 +1579,17 @@ CacheCreator::DeleteCache()
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
ErrorResult rv;
|
// This is called when the load is canceled which can occur before
|
||||||
|
// mCacheStorage is initialized.
|
||||||
|
if (!mCacheStorage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// It's safe to do this while Cache::Match() and Cache::Put() calls are
|
// It's safe to do this while Cache::Match() and Cache::Put() calls are
|
||||||
// running.
|
// running.
|
||||||
|
IgnoredErrorResult rv;
|
||||||
RefPtr<Promise> promise = mCacheStorage->Delete(mCacheName, rv);
|
RefPtr<Promise> promise = mCacheStorage->Delete(mCacheName, rv);
|
||||||
if (NS_WARN_IF(rv.Failed())) {
|
if (NS_WARN_IF(rv.Failed())) {
|
||||||
rv.SuppressException();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,15 +127,15 @@ struct IsHeapConstructibleType<nsXBLMaybeCompiled<T>>
|
||||||
static constexpr bool value = true;
|
static constexpr bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class UncompiledT>
|
template <class UncompiledT, class Wrapper>
|
||||||
class HeapBase<nsXBLMaybeCompiled<UncompiledT>>
|
class HeapBase<nsXBLMaybeCompiled<UncompiledT>, Wrapper>
|
||||||
{
|
{
|
||||||
const JS::Heap<nsXBLMaybeCompiled<UncompiledT>>& wrapper() const {
|
const Wrapper& wrapper() const {
|
||||||
return *static_cast<const JS::Heap<nsXBLMaybeCompiled<UncompiledT>>*>(this);
|
return *static_cast<const Wrapper*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Heap<nsXBLMaybeCompiled<UncompiledT>>& wrapper() {
|
Wrapper& wrapper() {
|
||||||
return *static_cast<JS::Heap<nsXBLMaybeCompiled<UncompiledT>>*>(this);
|
return *static_cast<Wrapper*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsXBLMaybeCompiled<UncompiledT>* extract() const {
|
const nsXBLMaybeCompiled<UncompiledT>* extract() const {
|
||||||
|
|
|
@ -1559,8 +1559,6 @@ public:
|
||||||
bool aUseEmbeddedBitmap,
|
bool aUseEmbeddedBitmap,
|
||||||
bool aForceGDIMode);
|
bool aForceGDIMode);
|
||||||
|
|
||||||
static void UpdateSystemTextQuality();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static ID2D1Device *mD2D1Device;
|
static ID2D1Device *mD2D1Device;
|
||||||
static ID3D11Device *mD3D11Device;
|
static ID3D11Device *mD3D11Device;
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "NativeFontResourceDWrite.h"
|
#include "NativeFontResourceDWrite.h"
|
||||||
#include <d3d10_1.h>
|
#include <d3d10_1.h>
|
||||||
#include "HelpersD2D.h"
|
#include "HelpersD2D.h"
|
||||||
#include "HelpersWinFonts.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "DrawTargetDual.h"
|
#include "DrawTargetDual.h"
|
||||||
|
@ -710,15 +709,6 @@ Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams)
|
||||||
return MakeAndAddRef<GlyphRenderingOptionsDWrite>(aParams);
|
return MakeAndAddRef<GlyphRenderingOptionsDWrite>(aParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE sSystemTextQuality = CLEARTYPE_QUALITY;
|
|
||||||
void
|
|
||||||
Factory::UpdateSystemTextQuality()
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
gfx::UpdateSystemTextQuality();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Factory::GetD2DVRAMUsageDrawTarget()
|
Factory::GetD2DVRAMUsageDrawTarget()
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,45 +6,32 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
|
||||||
|
// Cleartype can be dynamically enabled/disabled, so we have to check it
|
||||||
extern BYTE sSystemTextQuality;
|
// everytime we want to render some text.
|
||||||
|
|
||||||
static BYTE
|
static BYTE
|
||||||
GetSystemTextQuality()
|
GetSystemTextQuality()
|
||||||
{
|
|
||||||
return sSystemTextQuality;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleartype can be dynamically enabled/disabled, so we have to allow for dynamically
|
|
||||||
// updating it.
|
|
||||||
static void
|
|
||||||
UpdateSystemTextQuality()
|
|
||||||
{
|
{
|
||||||
BOOL font_smoothing;
|
BOOL font_smoothing;
|
||||||
UINT smoothing_type;
|
UINT smoothing_type;
|
||||||
|
|
||||||
if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
|
if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
|
||||||
sSystemTextQuality = DEFAULT_QUALITY;
|
return DEFAULT_QUALITY;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font_smoothing) {
|
if (font_smoothing) {
|
||||||
if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE,
|
if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE,
|
||||||
0, &smoothing_type, 0)) {
|
0, &smoothing_type, 0)) {
|
||||||
sSystemTextQuality = DEFAULT_QUALITY;
|
return DEFAULT_QUALITY;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) {
|
if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) {
|
||||||
sSystemTextQuality = CLEARTYPE_QUALITY;
|
return CLEARTYPE_QUALITY;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sSystemTextQuality = ANTIALIASED_QUALITY;
|
return ANTIALIASED_QUALITY;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sSystemTextQuality = DEFAULT_QUALITY;
|
return DEFAULT_QUALITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AntialiasMode
|
static AntialiasMode
|
||||||
|
|
|
@ -51,8 +51,38 @@ class TokenLexer : public Lexer
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
class MacroExpander::ScopedMacroReenabler final : angle::NonCopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScopedMacroReenabler(MacroExpander *expander);
|
||||||
|
~ScopedMacroReenabler();
|
||||||
|
|
||||||
|
private:
|
||||||
|
MacroExpander *mExpander;
|
||||||
|
};
|
||||||
|
|
||||||
|
MacroExpander::ScopedMacroReenabler::ScopedMacroReenabler(MacroExpander *expander)
|
||||||
|
: mExpander(expander)
|
||||||
|
{
|
||||||
|
mExpander->mDeferReenablingMacros = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroExpander::ScopedMacroReenabler::~ScopedMacroReenabler()
|
||||||
|
{
|
||||||
|
mExpander->mDeferReenablingMacros = false;
|
||||||
|
for (auto *macro : mExpander->mMacrosToReenable)
|
||||||
|
{
|
||||||
|
macro->disabled = false;
|
||||||
|
}
|
||||||
|
mExpander->mMacrosToReenable.clear();
|
||||||
|
}
|
||||||
|
|
||||||
MacroExpander::MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics)
|
MacroExpander::MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics)
|
||||||
: mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mTotalTokensInContexts(0)
|
: mLexer(lexer),
|
||||||
|
mMacroSet(macroSet),
|
||||||
|
mDiagnostics(diagnostics),
|
||||||
|
mTotalTokensInContexts(0),
|
||||||
|
mDeferReenablingMacros(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +217,14 @@ void MacroExpander::popMacro()
|
||||||
ASSERT(context->empty());
|
ASSERT(context->empty());
|
||||||
ASSERT(context->macro->disabled);
|
ASSERT(context->macro->disabled);
|
||||||
ASSERT(context->macro->expansionCount > 0);
|
ASSERT(context->macro->expansionCount > 0);
|
||||||
|
if (mDeferReenablingMacros)
|
||||||
|
{
|
||||||
|
mMacrosToReenable.push_back(context->macro);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
context->macro->disabled = false;
|
context->macro->disabled = false;
|
||||||
|
}
|
||||||
context->macro->expansionCount--;
|
context->macro->expansionCount--;
|
||||||
mTotalTokensInContexts -= context->replacements.size();
|
mTotalTokensInContexts -= context->replacements.size();
|
||||||
delete context;
|
delete context;
|
||||||
|
@ -263,6 +300,11 @@ bool MacroExpander::collectMacroArgs(const Macro ¯o,
|
||||||
|
|
||||||
args->push_back(MacroArg());
|
args->push_back(MacroArg());
|
||||||
|
|
||||||
|
// Defer reenabling macros until args collection is finished to avoid the possibility of
|
||||||
|
// infinite recursion. Otherwise infinite recursion might happen when expanding the args after
|
||||||
|
// macros have been popped from the context stack when parsing the args.
|
||||||
|
ScopedMacroReenabler deferReenablingMacros(this);
|
||||||
|
|
||||||
int openParens = 1;
|
int openParens = 1;
|
||||||
while (openParens != 0)
|
while (openParens != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,11 @@ class MacroExpander : public Lexer
|
||||||
std::unique_ptr<Token> mReserveToken;
|
std::unique_ptr<Token> mReserveToken;
|
||||||
std::vector<MacroContext *> mContextStack;
|
std::vector<MacroContext *> mContextStack;
|
||||||
size_t mTotalTokensInContexts;
|
size_t mTotalTokensInContexts;
|
||||||
|
|
||||||
|
bool mDeferReenablingMacros;
|
||||||
|
std::vector<const Macro *> mMacrosToReenable;
|
||||||
|
|
||||||
|
class ScopedMacroReenabler;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pp
|
} // namespace pp
|
||||||
|
|
|
@ -971,3 +971,18 @@ TEST_F(DefineTest, UndefineInInvocationPreLParen)
|
||||||
|
|
||||||
preprocess(input, expected);
|
preprocess(input, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The name of the macro "a" is inside an incomplete macro invocation of macro "m()" in its own
|
||||||
|
// expansion. This should not result in infinite recursion.
|
||||||
|
TEST_F(DefineTest, RecursiveMacroNameInsideIncompleteMacroInvocationInMacroExpansion)
|
||||||
|
{
|
||||||
|
const char *input =
|
||||||
|
"#define m(a)\n"
|
||||||
|
"#define a m((a)\n"
|
||||||
|
"a)\n";
|
||||||
|
const char *expected =
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"\n";
|
||||||
|
preprocess(input, expected);
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#endif
|
#endif
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||||
#include "gfxDWriteFonts.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -290,14 +289,6 @@ ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
|
||||||
{
|
{
|
||||||
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Rasterization);
|
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Rasterization);
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
if (aCallbackData) {
|
|
||||||
// Content processes don't get OnPaint called. So update here whenever we
|
|
||||||
// may do Thebes drawing.
|
|
||||||
gfxDWriteFont::UpdateClearTypeUsage();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal",
|
PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal",
|
||||||
js::ProfileEntry::Category::GRAPHICS);
|
js::ProfileEntry::Category::GRAPHICS);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
#o_1 {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
#o_2 {
|
||||||
|
height: 10000px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function boom(){
|
||||||
|
let doc = document.documentElement;
|
||||||
|
o_2.style.MozBorderEndStyle = "dotted";
|
||||||
|
doc.style.MozPerspective = "24.5pt";
|
||||||
|
o_0.style.MozTransformStyle = "preserve-3d";
|
||||||
|
doc.style.overflow = "-moz-scrollbars-horizontal";
|
||||||
|
doc.style.textOverflow = "''";
|
||||||
|
o_0.style.offsetInlineStart = "calc(3*25px)";
|
||||||
|
doc.style.paddingTop = "calc(67108864%)";
|
||||||
|
doc.style.width = "3e-0%";
|
||||||
|
o_0.style.display = "-moz-stack";
|
||||||
|
o_0.style.position = "relative";
|
||||||
|
}
|
||||||
|
addEventListener("DOMContentLoaded", boom);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body id=o_0><div id=o_1></div><div id=o_2></div></body>
|
||||||
|
</html>
|
|
@ -132,3 +132,4 @@ load 1216832-1.html
|
||||||
load 1225125-1.html
|
load 1225125-1.html
|
||||||
asserts-if(stylo,2) load 1308394.html # bug 1324669
|
asserts-if(stylo,2) load 1308394.html # bug 1324669
|
||||||
load 1317403-1.html
|
load 1317403-1.html
|
||||||
|
load 1325159-1.html
|
||||||
|
|
|
@ -123,7 +123,6 @@ gfxDWriteFont::~gfxDWriteFont()
|
||||||
void
|
void
|
||||||
gfxDWriteFont::UpdateClearTypeUsage()
|
gfxDWriteFont::UpdateClearTypeUsage()
|
||||||
{
|
{
|
||||||
Factory::UpdateSystemTextQuality();
|
|
||||||
mUseClearType = UsingClearType();
|
mUseClearType = UsingClearType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -538,13 +538,6 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
|
||||||
" with type " << m.type();
|
" with type " << m.type();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_TASK_TRACER
|
|
||||||
AutoSaveCurTraceInfo saveCurTraceInfo;
|
|
||||||
SetCurTraceInfo(m.header()->source_event_id,
|
|
||||||
m.header()->parent_task_id,
|
|
||||||
m.header()->source_event_type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m.routing_id() == MSG_ROUTING_NONE &&
|
if (m.routing_id() == MSG_ROUTING_NONE &&
|
||||||
m.type() == HELLO_MESSAGE_TYPE) {
|
m.type() == HELLO_MESSAGE_TYPE) {
|
||||||
// The Hello message contains only the process id.
|
// The Hello message contains only the process id.
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "chrome/common/file_descriptor_set_posix.h"
|
#include "chrome/common/file_descriptor_set_posix.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_TASK_TRACER
|
#ifdef MOZ_TASK_TRACER
|
||||||
#include "GeckoTaskTracer.h"
|
#include "GeckoTaskTracerImpl.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mozilla/Move.h"
|
#include "mozilla/Move.h"
|
||||||
|
@ -145,4 +145,39 @@ uint32_t Message::num_fds() const {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
void *MessageTask() {
|
||||||
|
return reinterpret_cast<void*>(&MessageTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Message::TaskTracerDispatch() {
|
||||||
|
header()->task_id = GenNewUniqueTaskId();
|
||||||
|
uintptr_t* vtab = reinterpret_cast<uintptr_t*>(&MessageTask);
|
||||||
|
LogVirtualTablePtr(header()->task_id,
|
||||||
|
header()->source_event_id,
|
||||||
|
vtab);
|
||||||
|
LogDispatch(header()->task_id,
|
||||||
|
header()->parent_task_id,
|
||||||
|
header()->source_event_id,
|
||||||
|
header()->source_event_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::AutoTaskTracerRun::AutoTaskTracerRun(Message& aMsg)
|
||||||
|
: mMsg(aMsg)
|
||||||
|
, mTaskId(mMsg.header()->task_id)
|
||||||
|
, mSourceEventId(mMsg.header()->source_event_id) {
|
||||||
|
LogBegin(mMsg.header()->task_id,
|
||||||
|
mMsg.header()->source_event_id);
|
||||||
|
SetCurTraceInfo(mMsg.header()->source_event_id,
|
||||||
|
mMsg.header()->task_id,
|
||||||
|
mMsg.header()->source_event_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::AutoTaskTracerRun::~AutoTaskTracerRun() {
|
||||||
|
AddLabel("IPC Message %s", mMsg.name());
|
||||||
|
LogEnd(mTaskId, mSourceEventId);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace IPC
|
} // namespace IPC
|
||||||
|
|
|
@ -272,6 +272,19 @@ class Message : public Pickle {
|
||||||
header()->flags |= INTERRUPT_BIT;
|
header()->flags |= INTERRUPT_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
void TaskTracerDispatch();
|
||||||
|
class AutoTaskTracerRun
|
||||||
|
: public mozilla::tasktracer::AutoSaveCurTraceInfo {
|
||||||
|
Message& mMsg;
|
||||||
|
uint64_t mTaskId;
|
||||||
|
uint64_t mSourceEventId;
|
||||||
|
public:
|
||||||
|
explicit AutoTaskTracerRun(Message& aMsg);
|
||||||
|
~AutoTaskTracerRun();
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(OS_MACOSX)
|
#if !defined(OS_MACOSX)
|
||||||
protected:
|
protected:
|
||||||
#endif
|
#endif
|
||||||
|
@ -311,6 +324,7 @@ class Message : public Pickle {
|
||||||
// Sequence number
|
// Sequence number
|
||||||
int32_t seqno;
|
int32_t seqno;
|
||||||
#ifdef MOZ_TASK_TRACER
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
uint64_t task_id;
|
||||||
uint64_t source_event_id;
|
uint64_t source_event_id;
|
||||||
uint64_t parent_task_id;
|
uint64_t parent_task_id;
|
||||||
mozilla::tasktracer::SourceEventType source_event_type;
|
mozilla::tasktracer::SourceEventType source_event_type;
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
#include "GeckoTaskTracer.h"
|
||||||
|
using namespace mozilla::tasktracer;
|
||||||
|
#endif
|
||||||
|
|
||||||
using mozilla::Move;
|
using mozilla::Move;
|
||||||
|
|
||||||
// Undo the damage done by mozzconf.h
|
// Undo the damage done by mozzconf.h
|
||||||
|
@ -979,6 +984,9 @@ MessageChannel::OnMessageReceivedFromLink(Message&& aMsg)
|
||||||
// blocked. This is okay, since we always check for pending events before
|
// blocked. This is okay, since we always check for pending events before
|
||||||
// blocking again.
|
// blocking again.
|
||||||
|
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
aMsg.TaskTracerDispatch();
|
||||||
|
#endif
|
||||||
RefPtr<MessageTask> task = new MessageTask(this, Move(aMsg));
|
RefPtr<MessageTask> task = new MessageTask(this, Move(aMsg));
|
||||||
mPending.insertBack(task);
|
mPending.insertBack(task);
|
||||||
|
|
||||||
|
@ -1079,6 +1087,9 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
||||||
SyncStackFrame frame(this, false);
|
SyncStackFrame frame(this, false);
|
||||||
NeuteredWindowRegion neuteredRgn(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION);
|
NeuteredWindowRegion neuteredRgn(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
AutoScopedLabel autolabel("sync message %s", aMsg->name());
|
||||||
|
#endif
|
||||||
|
|
||||||
CxxStackFrame f(*this, OUT_MESSAGE, msg);
|
CxxStackFrame f(*this, OUT_MESSAGE, msg);
|
||||||
|
|
||||||
|
@ -1271,6 +1282,9 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
||||||
#ifdef OS_WIN
|
#ifdef OS_WIN
|
||||||
SyncStackFrame frame(this, true);
|
SyncStackFrame frame(this, true);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
AutoScopedLabel autolabel("sync message %s", aMsg->name());
|
||||||
|
#endif
|
||||||
|
|
||||||
// This must come before MonitorAutoLock, as its destructor acquires the
|
// This must come before MonitorAutoLock, as its destructor acquires the
|
||||||
// monitor lock.
|
// monitor lock.
|
||||||
|
@ -1416,6 +1430,9 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
||||||
// own the monitor.
|
// own the monitor.
|
||||||
size_t stackDepth = InterruptStackDepth();
|
size_t stackDepth = InterruptStackDepth();
|
||||||
{
|
{
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
Message::AutoTaskTracerRun tasktracerRun(recvd);
|
||||||
|
#endif
|
||||||
MonitorAutoUnlock unlock(*mMonitor);
|
MonitorAutoUnlock unlock(*mMonitor);
|
||||||
|
|
||||||
CxxStackFrame frame(*this, IN_MESSAGE, &recvd);
|
CxxStackFrame frame(*this, IN_MESSAGE, &recvd);
|
||||||
|
@ -1675,6 +1692,9 @@ MessageChannel::DispatchMessage(Message &&aMsg)
|
||||||
MOZ_RELEASE_ASSERT(!aMsg.is_sync() || id == transaction.TransactionID());
|
MOZ_RELEASE_ASSERT(!aMsg.is_sync() || id == transaction.TransactionID());
|
||||||
|
|
||||||
{
|
{
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
Message::AutoTaskTracerRun tasktracerRun(aMsg);
|
||||||
|
#endif
|
||||||
MonitorAutoUnlock unlock(*mMonitor);
|
MonitorAutoUnlock unlock(*mMonitor);
|
||||||
CxxStackFrame frame(*this, IN_MESSAGE, &aMsg);
|
CxxStackFrame frame(*this, IN_MESSAGE, &aMsg);
|
||||||
|
|
||||||
|
@ -1711,6 +1731,9 @@ MessageChannel::DispatchSyncMessage(const Message& aMsg, Message*& aReply)
|
||||||
int nestedLevel = aMsg.nested_level();
|
int nestedLevel = aMsg.nested_level();
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(nestedLevel == IPC::Message::NOT_NESTED || NS_IsMainThread());
|
MOZ_RELEASE_ASSERT(nestedLevel == IPC::Message::NOT_NESTED || NS_IsMainThread());
|
||||||
|
#ifdef MOZ_TASK_TRACER
|
||||||
|
AutoScopedLabel autolabel("sync message %s", aMsg.name());
|
||||||
|
#endif
|
||||||
|
|
||||||
MessageChannel* dummy;
|
MessageChannel* dummy;
|
||||||
MessageChannel*& blockingVar = mSide == ChildSide && NS_IsMainThread() ? gParentProcessBlocker : dummy;
|
MessageChannel*& blockingVar = mSide == ChildSide && NS_IsMainThread() ? gParentProcessBlocker : dummy;
|
||||||
|
|
|
@ -134,13 +134,13 @@ class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, AllocPol
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename... Args>
|
template <typename Wrapper, typename... Args>
|
||||||
class GCHashMapOperations
|
class WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper>
|
||||||
{
|
{
|
||||||
using Map = JS::GCHashMap<Args...>;
|
using Map = JS::GCHashMap<Args...>;
|
||||||
using Lookup = typename Map::Lookup;
|
using Lookup = typename Map::Lookup;
|
||||||
|
|
||||||
const Map& map() const { return static_cast<const Outer*>(this)->get(); }
|
const Map& map() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using AddPtr = typename Map::AddPtr;
|
using AddPtr = typename Map::AddPtr;
|
||||||
|
@ -163,18 +163,18 @@ class GCHashMapOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename... Args>
|
template <typename Wrapper, typename... Args>
|
||||||
class MutableGCHashMapOperations
|
class MutableWrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper>
|
||||||
: public GCHashMapOperations<Outer, Args...>
|
: public WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper>
|
||||||
{
|
{
|
||||||
using Map = JS::GCHashMap<Args...>;
|
using Map = JS::GCHashMap<Args...>;
|
||||||
using Lookup = typename Map::Lookup;
|
using Lookup = typename Map::Lookup;
|
||||||
|
|
||||||
Map& map() { return static_cast<Outer*>(this)->get(); }
|
Map& map() { return static_cast<Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using AddPtr = typename Map::AddPtr;
|
using AddPtr = typename Map::AddPtr;
|
||||||
struct Enum : public Map::Enum { explicit Enum(Outer& o) : Map::Enum(o.map()) {} };
|
struct Enum : public Map::Enum { explicit Enum(Wrapper& o) : Map::Enum(o.map()) {} };
|
||||||
using Ptr = typename Map::Ptr;
|
using Ptr = typename Map::Ptr;
|
||||||
using Range = typename Map::Range;
|
using Range = typename Map::Range;
|
||||||
|
|
||||||
|
@ -211,26 +211,6 @@ class MutableGCHashMapOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A, typename B, typename C, typename D, typename E>
|
|
||||||
class RootedBase<JS::GCHashMap<A,B,C,D,E>>
|
|
||||||
: public MutableGCHashMapOperations<JS::Rooted<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename A, typename B, typename C, typename D, typename E>
|
|
||||||
class MutableHandleBase<JS::GCHashMap<A,B,C,D,E>>
|
|
||||||
: public MutableGCHashMapOperations<JS::MutableHandle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename A, typename B, typename C, typename D, typename E>
|
|
||||||
class HandleBase<JS::GCHashMap<A,B,C,D,E>>
|
|
||||||
: public GCHashMapOperations<JS::Handle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename A, typename B, typename C, typename D, typename E>
|
|
||||||
class WeakCacheBase<JS::GCHashMap<A,B,C,D,E>>
|
|
||||||
: public MutableGCHashMapOperations<JS::WeakCache<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
|
||||||
{};
|
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
@ -292,13 +272,13 @@ class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy>
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
template <typename Outer, typename... Args>
|
template <typename Wrapper, typename... Args>
|
||||||
class GCHashSetOperations
|
class WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper>
|
||||||
{
|
{
|
||||||
using Set = JS::GCHashSet<Args...>;
|
using Set = JS::GCHashSet<Args...>;
|
||||||
using Lookup = typename Set::Lookup;
|
using Lookup = typename Set::Lookup;
|
||||||
|
|
||||||
const Set& set() const { return static_cast<const Outer*>(this)->get(); }
|
const Set& set() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using AddPtr = typename Set::AddPtr;
|
using AddPtr = typename Set::AddPtr;
|
||||||
|
@ -322,19 +302,19 @@ class GCHashSetOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename... Args>
|
template <typename Wrapper, typename... Args>
|
||||||
class MutableGCHashSetOperations
|
class MutableWrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper>
|
||||||
: public GCHashSetOperations<Outer, Args...>
|
: public WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper>
|
||||||
{
|
{
|
||||||
using Set = JS::GCHashSet<Args...>;
|
using Set = JS::GCHashSet<Args...>;
|
||||||
using Lookup = typename Set::Lookup;
|
using Lookup = typename Set::Lookup;
|
||||||
|
|
||||||
Set& set() { return static_cast<Outer*>(this)->get(); }
|
Set& set() { return static_cast<Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using AddPtr = typename Set::AddPtr;
|
using AddPtr = typename Set::AddPtr;
|
||||||
using Entry = typename Set::Entry;
|
using Entry = typename Set::Entry;
|
||||||
struct Enum : public Set::Enum { explicit Enum(Outer& o) : Set::Enum(o.set()) {} };
|
struct Enum : public Set::Enum { explicit Enum(Wrapper& o) : Set::Enum(o.set()) {} };
|
||||||
using Ptr = typename Set::Ptr;
|
using Ptr = typename Set::Ptr;
|
||||||
using Range = typename Set::Range;
|
using Range = typename Set::Range;
|
||||||
|
|
||||||
|
@ -370,30 +350,6 @@ class MutableGCHashSetOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename HP, typename AP>
|
|
||||||
class RootedBase<JS::GCHashSet<T, HP, AP>>
|
|
||||||
: public MutableGCHashSetOperations<JS::Rooted<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename HP, typename AP>
|
|
||||||
class MutableHandleBase<JS::GCHashSet<T, HP, AP>>
|
|
||||||
: public MutableGCHashSetOperations<JS::MutableHandle<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename HP, typename AP>
|
|
||||||
class HandleBase<JS::GCHashSet<T, HP, AP>>
|
|
||||||
: public GCHashSetOperations<JS::Handle<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename HP, typename AP>
|
|
||||||
class WeakCacheBase<JS::GCHashSet<T, HP, AP>>
|
|
||||||
: public MutableGCHashSetOperations<JS::WeakCache<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* GCHashTable_h */
|
#endif /* GCHashTable_h */
|
||||||
|
|
|
@ -124,13 +124,13 @@ struct GCPolicy<mozilla::Variant<Ts...>>
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
template <typename Outer, typename... Ts>
|
template <typename Wrapper, typename... Ts>
|
||||||
class GCVariantOperations
|
class WrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper>
|
||||||
{
|
{
|
||||||
using Impl = JS::detail::GCVariantImplementation<Ts...>;
|
using Impl = JS::detail::GCVariantImplementation<Ts...>;
|
||||||
using Variant = mozilla::Variant<Ts...>;
|
using Variant = mozilla::Variant<Ts...>;
|
||||||
|
|
||||||
const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
|
const Variant& variant() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -150,15 +150,15 @@ class GCVariantOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename... Ts>
|
template <typename Wrapper, typename... Ts>
|
||||||
class MutableGCVariantOperations
|
class MutableWrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper>
|
||||||
: public GCVariantOperations<Outer, Ts...>
|
: public WrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper>
|
||||||
{
|
{
|
||||||
using Impl = JS::detail::GCVariantImplementation<Ts...>;
|
using Impl = JS::detail::GCVariantImplementation<Ts...>;
|
||||||
using Variant = mozilla::Variant<Ts...>;
|
using Variant = mozilla::Variant<Ts...>;
|
||||||
|
|
||||||
const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
|
const Variant& variant() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
Variant& variant() { return static_cast<Outer*>(this)->get(); }
|
Variant& variant() { return static_cast<Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -173,26 +173,6 @@ class MutableGCVariantOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
class RootedBase<mozilla::Variant<Ts...>>
|
|
||||||
: public MutableGCVariantOperations<JS::Rooted<mozilla::Variant<Ts...>>, Ts...>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
class MutableHandleBase<mozilla::Variant<Ts...>>
|
|
||||||
: public MutableGCVariantOperations<JS::MutableHandle<mozilla::Variant<Ts...>>, Ts...>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
class HandleBase<mozilla::Variant<Ts...>>
|
|
||||||
: public GCVariantOperations<JS::Handle<mozilla::Variant<Ts...>>, Ts...>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template <typename... Ts>
|
|
||||||
class PersistentRootedBase<mozilla::Variant<Ts...>>
|
|
||||||
: public MutableGCVariantOperations<JS::PersistentRooted<mozilla::Variant<Ts...>>, Ts...>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
#endif // js_GCVariant_h
|
#endif // js_GCVariant_h
|
||||||
|
|
|
@ -135,11 +135,11 @@ class GCVector
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
|
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
|
||||||
class GCVectorOperations
|
class WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
|
||||||
{
|
{
|
||||||
using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
|
using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
|
||||||
const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
|
const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
|
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
|
||||||
|
@ -155,13 +155,13 @@ class GCVectorOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
|
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
|
||||||
class MutableGCVectorOperations
|
class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
|
||||||
: public GCVectorOperations<Outer, T, Capacity, AllocPolicy>
|
: public WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
|
||||||
{
|
{
|
||||||
using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
|
using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
|
||||||
const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
|
const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
Vec& vec() { return static_cast<Outer*>(this)->get(); }
|
Vec& vec() { return static_cast<Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
|
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
|
||||||
|
@ -224,26 +224,6 @@ class MutableGCVectorOperations
|
||||||
void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
|
void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t N, typename AP>
|
|
||||||
class RootedBase<JS::GCVector<T,N,AP>>
|
|
||||||
: public MutableGCVectorOperations<JS::Rooted<JS::GCVector<T,N,AP>>, T,N,AP>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename T, size_t N, typename AP>
|
|
||||||
class MutableHandleBase<JS::GCVector<T,N,AP>>
|
|
||||||
: public MutableGCVectorOperations<JS::MutableHandle<JS::GCVector<T,N,AP>>, T,N,AP>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename T, size_t N, typename AP>
|
|
||||||
class HandleBase<JS::GCVector<T,N,AP>>
|
|
||||||
: public GCVectorOperations<JS::Handle<JS::GCVector<T,N,AP>>, T,N,AP>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <typename T, size_t N, typename AP>
|
|
||||||
class PersistentRootedBase<JS::GCVector<T,N,AP>>
|
|
||||||
: public MutableGCVectorOperations<JS::PersistentRooted<JS::GCVector<T,N,AP>>, T,N,AP>
|
|
||||||
{};
|
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
#endif // js_GCVector_h
|
#endif // js_GCVector_h
|
||||||
|
|
|
@ -113,17 +113,23 @@ template <typename T>
|
||||||
struct BarrierMethods {
|
struct BarrierMethods {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename Element, typename Wrapper>
|
||||||
class RootedBase {};
|
class WrappedPtrOperations {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename Element, typename Wrapper>
|
||||||
class HandleBase {};
|
class MutableWrappedPtrOperations : public WrappedPtrOperations<Element, Wrapper> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Wrapper>
|
||||||
class MutableHandleBase {};
|
class RootedBase : public MutableWrappedPtrOperations<T, Wrapper> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Wrapper>
|
||||||
class HeapBase {};
|
class HandleBase : public WrappedPtrOperations<T, Wrapper> {};
|
||||||
|
|
||||||
|
template <typename T, typename Wrapper>
|
||||||
|
class MutableHandleBase : public MutableWrappedPtrOperations<T, Wrapper> {};
|
||||||
|
|
||||||
|
template <typename T, typename Wrapper>
|
||||||
|
class HeapBase : public MutableWrappedPtrOperations<T, Wrapper> {};
|
||||||
|
|
||||||
// Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many macros into scope
|
// Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many macros into scope
|
||||||
template <typename T> struct IsHeapConstructibleType { static constexpr bool value = false; };
|
template <typename T> struct IsHeapConstructibleType { static constexpr bool value = false; };
|
||||||
|
@ -133,8 +139,8 @@ FOR_EACH_PUBLIC_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
|
||||||
FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
|
FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
|
||||||
#undef DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
|
#undef DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Wrapper>
|
||||||
class PersistentRootedBase {};
|
class PersistentRootedBase : public MutableWrappedPtrOperations<T, Wrapper> {};
|
||||||
|
|
||||||
static void* const ConstNullValue = nullptr;
|
static void* const ConstNullValue = nullptr;
|
||||||
|
|
||||||
|
@ -223,7 +229,7 @@ AssertGCThingIsNotAnObjectSubclass(js::gc::Cell* cell) {}
|
||||||
* Type T must be a public GC pointer type.
|
* Type T must be a public GC pointer type.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Heap : public js::HeapBase<T>
|
class Heap : public js::HeapBase<T, Heap<T>>
|
||||||
{
|
{
|
||||||
// Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons.
|
// Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons.
|
||||||
static_assert(js::IsHeapConstructibleType<T>::value,
|
static_assert(js::IsHeapConstructibleType<T>::value,
|
||||||
|
@ -362,7 +368,7 @@ ScriptIsMarkedGray(const Heap<JSScript*>& script)
|
||||||
* - It is not possible to store flag bits in a Heap<T>.
|
* - It is not possible to store flag bits in a Heap<T>.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TenuredHeap : public js::HeapBase<T>
|
class TenuredHeap : public js::HeapBase<T, TenuredHeap<T>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ElementType = T;
|
using ElementType = T;
|
||||||
|
@ -445,7 +451,7 @@ class TenuredHeap : public js::HeapBase<T>
|
||||||
* specialization, define a HandleBase<T> specialization containing them.
|
* specialization, define a HandleBase<T> specialization containing them.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
|
class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T, Handle<T>>
|
||||||
{
|
{
|
||||||
friend class JS::MutableHandle<T>;
|
friend class JS::MutableHandle<T>;
|
||||||
|
|
||||||
|
@ -535,7 +541,7 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
|
||||||
* them.
|
* them.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
|
class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T, MutableHandle<T>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ElementType = T;
|
using ElementType = T;
|
||||||
|
@ -747,7 +753,7 @@ namespace JS {
|
||||||
* specialization, define a RootedBase<T> specialization containing them.
|
* specialization, define a RootedBase<T> specialization containing them.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MOZ_RAII Rooted : public js::RootedBase<T>
|
class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>>
|
||||||
{
|
{
|
||||||
inline void registerWithRootLists(js::RootedListHeads& roots) {
|
inline void registerWithRootLists(js::RootedListHeads& roots) {
|
||||||
this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
|
this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
|
||||||
|
@ -845,8 +851,8 @@ namespace js {
|
||||||
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
|
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
|
||||||
* Handle<StringObject*> h = rooted;
|
* Handle<StringObject*> h = rooted;
|
||||||
*/
|
*/
|
||||||
template <>
|
template <typename Container>
|
||||||
class RootedBase<JSObject*>
|
class RootedBase<JSObject*, Container> : public MutableWrappedPtrOperations<JSObject*, Container>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <class U>
|
template <class U>
|
||||||
|
@ -863,8 +869,8 @@ class RootedBase<JSObject*>
|
||||||
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
|
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
|
||||||
* Handle<StringObject*> h = rooted;
|
* Handle<StringObject*> h = rooted;
|
||||||
*/
|
*/
|
||||||
template <>
|
template <typename Container>
|
||||||
class HandleBase<JSObject*>
|
class HandleBase<JSObject*, Container> : public WrappedPtrOperations<JSObject*, Container>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <class U>
|
template <class U>
|
||||||
|
@ -873,7 +879,7 @@ class HandleBase<JSObject*>
|
||||||
|
|
||||||
/** Interface substitute for Rooted<T> which does not root the variable's memory. */
|
/** Interface substitute for Rooted<T> which does not root the variable's memory. */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MOZ_RAII FakeRooted : public RootedBase<T>
|
class MOZ_RAII FakeRooted : public RootedBase<T, FakeRooted<T>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ElementType = T;
|
using ElementType = T;
|
||||||
|
@ -901,7 +907,7 @@ class MOZ_RAII FakeRooted : public RootedBase<T>
|
||||||
|
|
||||||
/** Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */
|
/** Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class FakeMutableHandle : public js::MutableHandleBase<T>
|
class FakeMutableHandle : public js::MutableHandleBase<T, FakeMutableHandle<T>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using ElementType = T;
|
using ElementType = T;
|
||||||
|
@ -1070,7 +1076,7 @@ MutableHandle<T>::MutableHandle(PersistentRooted<T>* root)
|
||||||
* marked when the object itself is marked.
|
* marked when the object itself is marked.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class PersistentRooted : public js::PersistentRootedBase<T>,
|
class PersistentRooted : public js::RootedBase<T, PersistentRooted<T>>,
|
||||||
private mozilla::LinkedListElement<PersistentRooted<T>>
|
private mozilla::LinkedListElement<PersistentRooted<T>>
|
||||||
{
|
{
|
||||||
using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>;
|
using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>;
|
||||||
|
@ -1230,44 +1236,25 @@ class JS_PUBLIC_API(ObjectPtr)
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
template <typename Outer, typename T, typename D>
|
template <typename T, typename D, typename Container>
|
||||||
class UniquePtrOperations
|
class WrappedPtrOperations<UniquePtr<T, D>, Container>
|
||||||
{
|
{
|
||||||
const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Outer*>(this)->get(); }
|
const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Container*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit operator bool() const { return !!uniquePtr(); }
|
explicit operator bool() const { return !!uniquePtr(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename T, typename D>
|
template <typename T, typename D, typename Container>
|
||||||
class MutableUniquePtrOperations : public UniquePtrOperations<Outer, T, D>
|
class MutableWrappedPtrOperations<UniquePtr<T, D>, Container>
|
||||||
|
: public WrappedPtrOperations<UniquePtr<T, D>, Container>
|
||||||
{
|
{
|
||||||
UniquePtr<T, D>& uniquePtr() { return static_cast<Outer*>(this)->get(); }
|
UniquePtr<T, D>& uniquePtr() { return static_cast<Container*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() { return uniquePtr().release(); }
|
MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() { return uniquePtr().release(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename D>
|
|
||||||
class RootedBase<UniquePtr<T, D>>
|
|
||||||
: public MutableUniquePtrOperations<JS::Rooted<UniquePtr<T, D>>, T, D>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template <typename T, typename D>
|
|
||||||
class MutableHandleBase<UniquePtr<T, D>>
|
|
||||||
: public MutableUniquePtrOperations<JS::MutableHandle<UniquePtr<T, D>>, T, D>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template <typename T, typename D>
|
|
||||||
class HandleBase<UniquePtr<T, D>>
|
|
||||||
: public UniquePtrOperations<JS::Handle<UniquePtr<T, D>>, T, D>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template <typename T, typename D>
|
|
||||||
class PersistentRootedBase<UniquePtr<T, D>>
|
|
||||||
: public MutableUniquePtrOperations<JS::PersistentRooted<UniquePtr<T, D>>, T, D>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
namespace gc {
|
namespace gc {
|
||||||
|
|
||||||
template <typename T, typename TraceCallbacks>
|
template <typename T, typename TraceCallbacks>
|
||||||
|
|
|
@ -9,11 +9,6 @@
|
||||||
|
|
||||||
#include "js/HeapAPI.h"
|
#include "js/HeapAPI.h"
|
||||||
|
|
||||||
namespace js {
|
|
||||||
template <typename T>
|
|
||||||
class WeakCacheBase {};
|
|
||||||
} // namespace js
|
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
template <typename T> class WeakCache;
|
template <typename T> class WeakCache;
|
||||||
|
|
||||||
|
@ -25,7 +20,7 @@ RegisterWeakCache(JS::Zone* zone, JS::WeakCache<void*>* cachep);
|
||||||
// A WeakCache stores the given Sweepable container and links itself into a
|
// A WeakCache stores the given Sweepable container and links itself into a
|
||||||
// list of such caches that are swept during each GC.
|
// list of such caches that are swept during each GC.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class WeakCache : public js::WeakCacheBase<T>,
|
class WeakCache : public js::MutableWrappedPtrOperations<T, WeakCache<T>>,
|
||||||
private mozilla::LinkedListElement<WeakCache<T>>
|
private mozilla::LinkedListElement<WeakCache<T>>
|
||||||
{
|
{
|
||||||
friend class mozilla::LinkedListElement<WeakCache<T>>;
|
friend class mozilla::LinkedListElement<WeakCache<T>>;
|
||||||
|
|
|
@ -1288,20 +1288,18 @@ struct BarrierMethods<JS::Value>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Outer> class MutableValueOperations;
|
template <class Wrapper> class MutableValueOperations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class designed for CRTP use in implementing the non-mutating parts of the
|
* A class designed for CRTP use in implementing the non-mutating parts of the
|
||||||
* Value interface in Value-like classes. Outer must be a class inheriting
|
* Value interface in Value-like classes. Wrapper must be a class inheriting
|
||||||
* ValueOperations<Outer> with a visible get() method returning a const
|
* ValueOperations<Wrapper> with a visible get() method returning a const
|
||||||
* reference to the Value abstracted by Outer.
|
* reference to the Value abstracted by Wrapper.
|
||||||
*/
|
*/
|
||||||
template <class Outer>
|
template <class Wrapper>
|
||||||
class ValueOperations
|
class WrappedPtrOperations<JS::Value, Wrapper>
|
||||||
{
|
{
|
||||||
friend class MutableValueOperations<Outer>;
|
const JS::Value& value() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
const JS::Value& value() const { return static_cast<const Outer*>(this)->get(); }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool isUndefined() const { return value().isUndefined(); }
|
bool isUndefined() const { return value().isUndefined(); }
|
||||||
|
@ -1346,14 +1344,14 @@ class ValueOperations
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class designed for CRTP use in implementing all the mutating parts of the
|
* A class designed for CRTP use in implementing all the mutating parts of the
|
||||||
* Value interface in Value-like classes. Outer must be a class inheriting
|
* Value interface in Value-like classes. Wrapper must be a class inheriting
|
||||||
* MutableValueOperations<Outer> with visible get() methods returning const and
|
* MutableWrappedPtrOperations<Wrapper> with visible get() methods returning const and
|
||||||
* non-const references to the Value abstracted by Outer.
|
* non-const references to the Value abstracted by Wrapper.
|
||||||
*/
|
*/
|
||||||
template <class Outer>
|
template <class Wrapper>
|
||||||
class MutableValueOperations : public ValueOperations<Outer>
|
class MutableWrappedPtrOperations<JS::Value, Wrapper> : public WrappedPtrOperations<JS::Value, Wrapper>
|
||||||
{
|
{
|
||||||
JS::Value& value() { return static_cast<Outer*>(this)->get(); }
|
JS::Value& value() { return static_cast<Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setNull() { value().setNull(); }
|
void setNull() { value().setNull(); }
|
||||||
|
@ -1378,13 +1376,9 @@ class MutableValueOperations : public ValueOperations<Outer>
|
||||||
* Augment the generic Heap<T> interface when T = Value with
|
* Augment the generic Heap<T> interface when T = Value with
|
||||||
* type-querying, value-extracting, and mutating operations.
|
* type-querying, value-extracting, and mutating operations.
|
||||||
*/
|
*/
|
||||||
template <>
|
template <typename Wrapper>
|
||||||
class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
|
class HeapBase<JS::Value, Wrapper> : public WrappedPtrOperations<JS::Value, Wrapper>
|
||||||
{
|
{
|
||||||
typedef JS::Heap<JS::Value> Outer;
|
|
||||||
|
|
||||||
friend class ValueOperations<Outer>;
|
|
||||||
|
|
||||||
void setBarriered(const JS::Value& v) {
|
void setBarriered(const JS::Value& v) {
|
||||||
*static_cast<JS::Heap<JS::Value>*>(this) = v;
|
*static_cast<JS::Heap<JS::Value>*>(this) = v;
|
||||||
}
|
}
|
||||||
|
@ -1431,22 +1425,6 @@ class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
class HandleBase<JS::Value> : public ValueOperations<JS::Handle<JS::Value> >
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHandle<JS::Value> >
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value> >
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class PersistentRootedBase<JS::Value> : public MutableValueOperations<JS::PersistentRooted<JS::Value>>
|
|
||||||
{};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the Value is a GC pointer type, convert to that type and call |f| with
|
* If the Value is a GC pointer type, convert to that type and call |f| with
|
||||||
* the pointer. If the Value is not a GC type, calls F::defaultValue.
|
* the pointer. If the Value is not a GC type, calls F::defaultValue.
|
||||||
|
|
|
@ -53,14 +53,22 @@ class HashableValue
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename Wrapper>
|
||||||
class RootedBase<HashableValue> {
|
class WrappedPtrOperations<HashableValue, Wrapper>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Value value() const {
|
||||||
|
return static_cast<const Wrapper*>(this)->get().get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Wrapper>
|
||||||
|
class MutableWrappedPtrOperations<HashableValue, Wrapper>
|
||||||
|
: public WrappedPtrOperations<HashableValue, Wrapper>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
MOZ_MUST_USE bool setValue(JSContext* cx, HandleValue v) {
|
MOZ_MUST_USE bool setValue(JSContext* cx, HandleValue v) {
|
||||||
return static_cast<JS::Rooted<HashableValue>*>(this)->get().setValue(cx, v);
|
return static_cast<Wrapper*>(this)->get().setValue(cx, v);
|
||||||
}
|
|
||||||
Value value() const {
|
|
||||||
return static_cast<const JS::Rooted<HashableValue>*>(this)->get().get();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -786,7 +786,17 @@ ScheduleGC(JSContext* cx, unsigned argc, Value* vp)
|
||||||
PrepareZoneForGC(zone);
|
PrepareZoneForGC(zone);
|
||||||
} else if (args[0].isString()) {
|
} else if (args[0].isString()) {
|
||||||
/* This allows us to schedule the atoms zone for GC. */
|
/* This allows us to schedule the atoms zone for GC. */
|
||||||
PrepareZoneForGC(args[0].toString()->zone());
|
Zone* zone = args[0].toString()->zoneFromAnyThread();
|
||||||
|
if (!CurrentThreadCanAccessZone(zone)) {
|
||||||
|
RootedObject callee(cx, &args.callee());
|
||||||
|
ReportUsageErrorASCII(cx, callee, "Specified zone not accessible for GC");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PrepareZoneForGC(zone);
|
||||||
|
} else {
|
||||||
|
RootedObject callee(cx, &args.callee());
|
||||||
|
ReportUsageErrorASCII(cx, callee, "Bad argument - expecting integer, object or string");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t zealBits;
|
uint32_t zealBits;
|
||||||
|
@ -4219,9 +4229,10 @@ JS_FN_HELP("rejectPromise", RejectPromise, 2, 0,
|
||||||
gc::ZealModeHelpText),
|
gc::ZealModeHelpText),
|
||||||
|
|
||||||
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
|
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,
|
||||||
"schedulegc([num | obj])",
|
"schedulegc([num | obj | string])",
|
||||||
" If num is given, schedule a GC after num allocations.\n"
|
" If num is given, schedule a GC after num allocations.\n"
|
||||||
" If obj is given, schedule a GC of obj's zone.\n"
|
" If obj is given, schedule a GC of obj's zone.\n"
|
||||||
|
" If string is given, schedule a GC of the string's zone if possible.\n"
|
||||||
" Returns the number of allocations before the next trigger."),
|
" Returns the number of allocations before the next trigger."),
|
||||||
|
|
||||||
JS_FN_HELP("selectforgc", SelectForGC, 0, 0,
|
JS_FN_HELP("selectforgc", SelectForGC, 0, 0,
|
||||||
|
|
|
@ -52,11 +52,11 @@ class TraceableFifo : public js::Fifo<T, MinInlineCapacity, AllocPolicy>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
|
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
|
||||||
class TraceableFifoOperations
|
class WrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>, Wrapper>
|
||||||
{
|
{
|
||||||
using TF = TraceableFifo<T, Capacity, AllocPolicy>;
|
using TF = TraceableFifo<T, Capacity, AllocPolicy>;
|
||||||
const TF& fifo() const { return static_cast<const Outer*>(this)->extract(); }
|
const TF& fifo() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
size_t length() const { return fifo().length(); }
|
size_t length() const { return fifo().length(); }
|
||||||
|
@ -64,12 +64,12 @@ class TraceableFifoOperations
|
||||||
const T& front() const { return fifo().front(); }
|
const T& front() const { return fifo().front(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
|
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
|
||||||
class MutableTraceableFifoOperations
|
class MutableWrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>, Wrapper>
|
||||||
: public TraceableFifoOperations<Outer, T, Capacity, AllocPolicy>
|
: public WrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>, Wrapper>
|
||||||
{
|
{
|
||||||
using TF = TraceableFifo<T, Capacity, AllocPolicy>;
|
using TF = TraceableFifo<T, Capacity, AllocPolicy>;
|
||||||
TF& fifo() { return static_cast<Outer*>(this)->extract(); }
|
TF& fifo() { return static_cast<Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
T& front() { return fifo().front(); }
|
T& front() { return fifo().front(); }
|
||||||
|
@ -83,46 +83,6 @@ class MutableTraceableFifoOperations
|
||||||
void clear() { fifo().clear(); }
|
void clear() { fifo().clear(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A, size_t B, typename C>
|
|
||||||
class RootedBase<TraceableFifo<A,B,C>>
|
|
||||||
: public MutableTraceableFifoOperations<JS::Rooted<TraceableFifo<A,B,C>>, A,B,C>
|
|
||||||
{
|
|
||||||
using TF = TraceableFifo<A,B,C>;
|
|
||||||
|
|
||||||
friend class TraceableFifoOperations<JS::Rooted<TF>, A,B,C>;
|
|
||||||
const TF& extract() const { return *static_cast<const JS::Rooted<TF>*>(this)->address(); }
|
|
||||||
|
|
||||||
friend class MutableTraceableFifoOperations<JS::Rooted<TF>, A,B,C>;
|
|
||||||
TF& extract() { return *static_cast<JS::Rooted<TF>*>(this)->address(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename A, size_t B, typename C>
|
|
||||||
class MutableHandleBase<TraceableFifo<A,B,C>>
|
|
||||||
: public MutableTraceableFifoOperations<JS::MutableHandle<TraceableFifo<A,B,C>>, A,B,C>
|
|
||||||
{
|
|
||||||
using TF = TraceableFifo<A,B,C>;
|
|
||||||
|
|
||||||
friend class TraceableFifoOperations<JS::MutableHandle<TF>, A,B,C>;
|
|
||||||
const TF& extract() const {
|
|
||||||
return *static_cast<const JS::MutableHandle<TF>*>(this)->address();
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class MutableTraceableFifoOperations<JS::MutableHandle<TF>, A,B,C>;
|
|
||||||
TF& extract() { return *static_cast<JS::MutableHandle<TF>*>(this)->address(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename A, size_t B, typename C>
|
|
||||||
class HandleBase<TraceableFifo<A,B,C>>
|
|
||||||
: public TraceableFifoOperations<JS::Handle<TraceableFifo<A,B,C>>, A,B,C>
|
|
||||||
{
|
|
||||||
using TF = TraceableFifo<A,B,C>;
|
|
||||||
|
|
||||||
friend class TraceableFifoOperations<JS::Handle<TF>, A,B,C>;
|
|
||||||
const TF& extract() const {
|
|
||||||
return *static_cast<const JS::Handle<TF>*>(this)->address();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
#endif // js_TraceableFifo_h
|
#endif // js_TraceableFifo_h
|
||||||
|
|
|
@ -316,15 +316,9 @@ struct InternalBarrierMethods<jsid>
|
||||||
static void postBarrier(jsid* idp, jsid prev, jsid next) {}
|
static void postBarrier(jsid* idp, jsid prev, jsid next) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Barrier classes can use Mixins to add methods to a set of barrier
|
|
||||||
// instantiations, to make the barriered thing look and feel more like the
|
|
||||||
// thing itself.
|
|
||||||
template <typename T>
|
|
||||||
class BarrieredBaseMixins {};
|
|
||||||
|
|
||||||
// Base class of all barrier types.
|
// Base class of all barrier types.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class BarrieredBase : public BarrieredBaseMixins<T>
|
class BarrieredBase
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
// BarrieredBase is not directly instantiable.
|
// BarrieredBase is not directly instantiable.
|
||||||
|
@ -345,9 +339,12 @@ class BarrieredBase : public BarrieredBaseMixins<T>
|
||||||
|
|
||||||
// Base class for barriered pointer types that intercept only writes.
|
// Base class for barriered pointer types that intercept only writes.
|
||||||
template <class T>
|
template <class T>
|
||||||
class WriteBarrieredBase : public BarrieredBase<T>
|
class WriteBarrieredBase : public BarrieredBase<T>,
|
||||||
|
public WrappedPtrOperations<T, WriteBarrieredBase<T>>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
using BarrieredBase<T>::value;
|
||||||
|
|
||||||
// WriteBarrieredBase is not directly instantiable.
|
// WriteBarrieredBase is not directly instantiable.
|
||||||
explicit WriteBarrieredBase(const T& v) : BarrieredBase<T>(v) {}
|
explicit WriteBarrieredBase(const T& v) : BarrieredBase<T>(v) {}
|
||||||
|
|
||||||
|
@ -566,8 +563,12 @@ class ReadBarrieredBase : public BarrieredBase<T>
|
||||||
// insert manual post-barriers on the table for rekeying if the key is based in
|
// insert manual post-barriers on the table for rekeying if the key is based in
|
||||||
// any way on the address of the object.
|
// any way on the address of the object.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ReadBarriered : public ReadBarrieredBase<T>
|
class ReadBarriered : public ReadBarrieredBase<T>,
|
||||||
|
public WrappedPtrOperations<T, ReadBarriered<T>>
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
using ReadBarrieredBase<T>::value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ReadBarriered() : ReadBarrieredBase<T>(JS::GCPolicy<T>::initial()) {}
|
ReadBarriered() : ReadBarrieredBase<T>(JS::GCPolicy<T>::initial()) {}
|
||||||
|
|
||||||
|
@ -634,12 +635,6 @@ class ReadBarriered : public ReadBarrieredBase<T>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using WeakRef = ReadBarriered<T>;
|
using WeakRef = ReadBarriered<T>;
|
||||||
|
|
||||||
// Add Value operations to all Barrier types. Note, this must be defined before
|
|
||||||
// HeapSlot for HeapSlot's base to get these operations.
|
|
||||||
template <>
|
|
||||||
class BarrieredBaseMixins<JS::Value> : public ValueOperations<WriteBarrieredBase<JS::Value>>
|
|
||||||
{};
|
|
||||||
|
|
||||||
// A pre- and post-barriered Value that is specialized to be aware that it
|
// A pre- and post-barriered Value that is specialized to be aware that it
|
||||||
// resides in a slots or elements vector. This allows it to be relocated in
|
// resides in a slots or elements vector. This allows it to be relocated in
|
||||||
// memory, but with substantially less overhead than a HeapPtr.
|
// memory, but with substantially less overhead than a HeapPtr.
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
if (helperThreadCount() === 0)
|
||||||
|
quit();
|
||||||
|
evalInWorker(`schedulegc("s1");`);
|
|
@ -0,0 +1,15 @@
|
||||||
|
if (!('gczeal' in this))
|
||||||
|
quit();
|
||||||
|
var lfGlobal = newGlobal();
|
||||||
|
lfGlobal.evaluate(`
|
||||||
|
for (var i = 0; i < 600; i++)
|
||||||
|
eval('function f' + i + '() {}');
|
||||||
|
`);
|
||||||
|
var lfGlobal = newGlobal();
|
||||||
|
lfGlobal.evaluate(`
|
||||||
|
if (!('gczeal' in this))
|
||||||
|
quit();
|
||||||
|
var dbg = new Debugger();
|
||||||
|
gczeal(9, 10);
|
||||||
|
dbg.findScripts({});
|
||||||
|
`);
|
|
@ -0,0 +1,15 @@
|
||||||
|
if (!('gczeal' in this))
|
||||||
|
quit();
|
||||||
|
var lfGlobal = newGlobal();
|
||||||
|
lfGlobal.evaluate(`
|
||||||
|
for (var i = 0; i < 600; i++)
|
||||||
|
eval('function f' + i + '() {}');
|
||||||
|
`);
|
||||||
|
var lfGlobal = newGlobal();
|
||||||
|
lfGlobal.evaluate(`
|
||||||
|
if (!('gczeal' in this))
|
||||||
|
quit();
|
||||||
|
var dbg = new Debugger();
|
||||||
|
gczeal(9, 1);
|
||||||
|
dbg.findScripts({});
|
||||||
|
`);
|
|
@ -207,33 +207,68 @@ assertEq(testTrunc(13.37), 1);
|
||||||
testTrap64('rem_s', 10, 0, /integer divide by zero/);
|
testTrap64('rem_s', 10, 0, /integer divide by zero/);
|
||||||
testTrap64('rem_u', 10, 0, /integer divide by zero/);
|
testTrap64('rem_u', 10, 0, /integer divide by zero/);
|
||||||
|
|
||||||
testBinary64('and', 42, 6, 2);
|
// Bitops.
|
||||||
testBinary64('or', 42, 6, 46);
|
testBinary64('or', 42, 6, 46);
|
||||||
testBinary64('xor', 42, 2, 40);
|
|
||||||
testBinary64('and', "0x8765432112345678", "0xffff0000ffff0000", "0x8765000012340000");
|
|
||||||
testBinary64('or', "0x8765432112345678", "0xffff0000ffff0000", "0xffff4321ffff5678");
|
testBinary64('or', "0x8765432112345678", "0xffff0000ffff0000", "0xffff4321ffff5678");
|
||||||
|
|
||||||
|
testBinary64('xor', 42, 2, 40);
|
||||||
testBinary64('xor', "0x8765432112345678", "0xffff0000ffff0000", "0x789a4321edcb5678");
|
testBinary64('xor', "0x8765432112345678", "0xffff0000ffff0000", "0x789a4321edcb5678");
|
||||||
testBinary64('shl', 40, 2, 160);
|
|
||||||
testBinary64('shr_s', -40, 2, -10);
|
testBinary64('shl', 0xff00ff, 28, "0x0ff00ff0000000");
|
||||||
testBinary64('shr_u', -40, 2, "0x3ffffffffffffff6");
|
testBinary64('shl', 0xff00ff, 30, "0x3fc03fc0000000");
|
||||||
testBinary64('shl', 0xff00ff, 28, "0xff00ff0000000");
|
testBinary64('shl', 0xff00ff, 31, "0x7f807f80000000");
|
||||||
|
testBinary64('shl', 0xff00ff, 32, "0xff00ff00000000");
|
||||||
testBinary64('shl', 1, 63, "0x8000000000000000");
|
testBinary64('shl', 1, 63, "0x8000000000000000");
|
||||||
testBinary64('shl', 1, 64, 1);
|
testBinary64('shl', 1, 64, 1);
|
||||||
testBinary64('shr_s', "0xff00ff0000000", 28, 0xff00ff);
|
testBinary64('shl', 40, 2, 160);
|
||||||
testBinary64('shr_u', "0x8ffff00ff0000000", 56, 0x8f);
|
|
||||||
testBinary64('rotl', 40, 2, 160);
|
|
||||||
testBinary64('rotr', 40, 2, 10);
|
|
||||||
testBinary64('rotr', "0x1234567812345678", 4, "0x8123456781234567");
|
|
||||||
testBinary64('rotl', "0x1234567812345678", 4, "0x2345678123456781");
|
|
||||||
testBinary64('rotl', "0x1234567812345678", 60, "0x8123456781234567");
|
|
||||||
testBinary64('rotr', "0x1234567812345678", 60, "0x2345678123456781");
|
|
||||||
testBinary64('rotl', "0x0000000000001000", 127, "0x0000000000000800");
|
|
||||||
testBinary64('rotr', "0x0000000000001000", 127, "0x0000000000002000");
|
|
||||||
testBinary64('rotr', 40, 0, 40);
|
|
||||||
testBinary64('rotl', 40, 0, 40);
|
|
||||||
testBinary64('and', 42, 0, 0);
|
|
||||||
testBinary64('and', "0x0000000012345678", "0xffff0000ffff0000", "0x0000000012340000");
|
|
||||||
|
|
||||||
|
testBinary64('shr_s', -40, 2, -10);
|
||||||
|
testBinary64('shr_s', "0xff00ff0000000", 28, 0xff00ff);
|
||||||
|
testBinary64('shr_s', "0xff00ff0000000", 30, 0x3fc03f);
|
||||||
|
testBinary64('shr_s', "0xff00ff0000000", 31, 0x1fe01f);
|
||||||
|
testBinary64('shr_s', "0xff00ff0000000", 32, 0x0ff00f);
|
||||||
|
|
||||||
|
testBinary64('shr_u', -40, 2, "0x3ffffffffffffff6");
|
||||||
|
testBinary64('shr_u', "0x8ffff00ff0000000", 30, "0x23fffc03f");
|
||||||
|
testBinary64('shr_u', "0x8ffff00ff0000000", 31, "0x11fffe01f");
|
||||||
|
testBinary64('shr_u', "0x8ffff00ff0000000", 32, "0x08ffff00f");
|
||||||
|
testBinary64('shr_u', "0x8ffff00ff0000000", 56, 0x8f);
|
||||||
|
|
||||||
|
testBinary64('and', 42, 0, 0);
|
||||||
|
testBinary64('and', 42, 6, 2);
|
||||||
|
testBinary64('and', "0x0000000012345678", "0xffff0000ffff0000", "0x0000000012340000");
|
||||||
|
testBinary64('and', "0x8765432112345678", "0xffff0000ffff0000", "0x8765000012340000");
|
||||||
|
|
||||||
|
// Rotations.
|
||||||
|
testBinary64('rotl', 40, 0, 0x28);
|
||||||
|
testBinary64('rotl', 40, 2, 0xA0);
|
||||||
|
testBinary64('rotl', 40, 8, 0x2800);
|
||||||
|
testBinary64('rotl', 40, 30, "0xA00000000");
|
||||||
|
testBinary64('rotl', 40, 31, "0x1400000000");
|
||||||
|
testBinary64('rotl', 40, 32, "0x2800000000");
|
||||||
|
|
||||||
|
testBinary64('rotl', "0x1234567812345678", 4, "0x2345678123456781");
|
||||||
|
testBinary64('rotl', "0x1234567812345678", 30, "0x048D159E048D159E");
|
||||||
|
testBinary64('rotl', "0x1234567812345678", 31, "0x091A2B3C091A2B3C");
|
||||||
|
testBinary64('rotl', "0x1234567812345678", 32, "0x1234567812345678");
|
||||||
|
|
||||||
|
testBinary64('rotl', "0x0000000000001000", 127, "0x0000000000000800");
|
||||||
|
|
||||||
|
testBinary64('rotr', 40, 0, 0x28);
|
||||||
|
testBinary64('rotr', 40, 2, 0x0A);
|
||||||
|
testBinary64('rotr', 40, 30, "0xA000000000");
|
||||||
|
testBinary64('rotr', 40, 31, "0x5000000000");
|
||||||
|
testBinary64('rotr', 40, 32, "0x2800000000");
|
||||||
|
|
||||||
|
testBinary64('rotr', "0x1234567812345678", 4, "0x8123456781234567");
|
||||||
|
testBinary64('rotr', "0x1234567812345678", 30, "0x48D159E048D159E0");
|
||||||
|
testBinary64('rotr', "0x1234567812345678", 31, "0x2468ACF02468ACF0");
|
||||||
|
testBinary64('rotr', "0x1234567812345678", 32, "0x1234567812345678");
|
||||||
|
testBinary64('rotr', "0x1234567812345678", 60, "0x2345678123456781");
|
||||||
|
|
||||||
|
testBinary64('rotr', "0x0000000000001000", 127, "0x0000000000002000");
|
||||||
|
|
||||||
|
// Comparisons.
|
||||||
testComparison64('eq', 40, 40, 1);
|
testComparison64('eq', 40, 40, 1);
|
||||||
testComparison64('ne', 40, 40, 0);
|
testComparison64('ne', 40, 40, 0);
|
||||||
testComparison64('lt_s', 40, 40, 0);
|
testComparison64('lt_s', 40, 40, 0);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
if (typeof enableSPSProfiling === 'undefined' || !isAsmJSCompilationAvailable())
|
||||||
|
quit();
|
||||||
|
|
||||||
|
enableSPSProfiling();
|
||||||
|
var code = evaluate("(function() { 'use asm'; function g() { return 43 } return g })", {
|
||||||
|
fileName: null
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEq(code()(), 43);
|
|
@ -4729,6 +4729,9 @@ IonBuilder::getSingletonPrototype(JSFunction* target)
|
||||||
MDefinition*
|
MDefinition*
|
||||||
IonBuilder::createThisScriptedSingleton(JSFunction* target, MDefinition* callee)
|
IonBuilder::createThisScriptedSingleton(JSFunction* target, MDefinition* callee)
|
||||||
{
|
{
|
||||||
|
if (!target->hasScript())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// Get the singleton prototype (if exists)
|
// Get the singleton prototype (if exists)
|
||||||
JSObject* proto = getSingletonPrototype(target);
|
JSObject* proto = getSingletonPrototype(target);
|
||||||
if (!proto)
|
if (!proto)
|
||||||
|
|
|
@ -539,7 +539,7 @@ MacroAssembler::rotateLeft64(Imm32 count, Register64 src, Register64 dest, Regis
|
||||||
MOZ_ASSERT(src == dest, "defineReuseInput");
|
MOZ_ASSERT(src == dest, "defineReuseInput");
|
||||||
|
|
||||||
int32_t amount = count.value & 0x3f;
|
int32_t amount = count.value & 0x3f;
|
||||||
if (amount % 0x1f != 0) {
|
if ((amount & 0x1f) != 0) {
|
||||||
movl(dest.high, temp);
|
movl(dest.high, temp);
|
||||||
shldl(Imm32(amount & 0x1f), dest.low, dest.high);
|
shldl(Imm32(amount & 0x1f), dest.low, dest.high);
|
||||||
shldl(Imm32(amount & 0x1f), temp, dest.low);
|
shldl(Imm32(amount & 0x1f), temp, dest.low);
|
||||||
|
|
|
@ -57,19 +57,10 @@ struct MyContainer
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
template <>
|
template <typename Wrapper>
|
||||||
struct RootedBase<MyContainer> {
|
struct MutableWrappedPtrOperations<MyContainer, Wrapper> {
|
||||||
HeapPtr<JSObject*>& obj() { return static_cast<Rooted<MyContainer>*>(this)->get().obj; }
|
HeapPtr<JSObject*>& obj() { return static_cast<Wrapper*>(this)->get().obj; }
|
||||||
HeapPtr<JSString*>& str() { return static_cast<Rooted<MyContainer>*>(this)->get().str; }
|
HeapPtr<JSString*>& str() { return static_cast<Wrapper*>(this)->get().str; }
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct PersistentRootedBase<MyContainer> {
|
|
||||||
HeapPtr<JSObject*>& obj() {
|
|
||||||
return static_cast<PersistentRooted<MyContainer>*>(this)->get().obj;
|
|
||||||
}
|
|
||||||
HeapPtr<JSString*>& str() {
|
|
||||||
return static_cast<PersistentRooted<MyContainer>*>(this)->get().str;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
|
|
@ -2569,10 +2569,14 @@ struct JS_PUBLIC_API(PropertyDescriptor) {
|
||||||
void trace(JSTracer* trc);
|
void trace(JSTracer* trc);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer>
|
} // namespace JS
|
||||||
class PropertyDescriptorOperations
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
|
template <typename Wrapper>
|
||||||
|
class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
|
||||||
{
|
{
|
||||||
const PropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
|
const JS::PropertyDescriptor& desc() const { return static_cast<const Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
bool has(unsigned bit) const {
|
bool has(unsigned bit) const {
|
||||||
MOZ_ASSERT(bit != 0);
|
MOZ_ASSERT(bit != 0);
|
||||||
|
@ -2701,10 +2705,11 @@ class PropertyDescriptorOperations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Outer>
|
template <typename Wrapper>
|
||||||
class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer>
|
class MutableWrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
|
||||||
|
: public js::WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
|
||||||
{
|
{
|
||||||
PropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
|
JS::PropertyDescriptor& desc() { return static_cast<Wrapper*>(this)->get(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void clear() {
|
void clear() {
|
||||||
|
@ -2715,7 +2720,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
|
||||||
value().setUndefined();
|
value().setUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initFields(HandleObject obj, HandleValue v, unsigned attrs,
|
void initFields(JS::HandleObject obj, JS::HandleValue v, unsigned attrs,
|
||||||
JSGetterOp getterOp, JSSetterOp setterOp) {
|
JSGetterOp getterOp, JSSetterOp setterOp) {
|
||||||
MOZ_ASSERT(getterOp != JS_PropertyStub);
|
MOZ_ASSERT(getterOp != JS_PropertyStub);
|
||||||
MOZ_ASSERT(setterOp != JS_StrictPropertyStub);
|
MOZ_ASSERT(setterOp != JS_StrictPropertyStub);
|
||||||
|
@ -2727,7 +2732,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
|
||||||
setSetter(setterOp);
|
setSetter(setterOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign(PropertyDescriptor& other) {
|
void assign(JS::PropertyDescriptor& other) {
|
||||||
object().set(other.obj);
|
object().set(other.obj);
|
||||||
setAttributes(other.attrs);
|
setAttributes(other.attrs);
|
||||||
setGetter(other.getter);
|
setGetter(other.getter);
|
||||||
|
@ -2735,7 +2740,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
|
||||||
value().set(other.value);
|
value().set(other.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDataDescriptor(HandleValue v, unsigned attrs) {
|
void setDataDescriptor(JS::HandleValue v, unsigned attrs) {
|
||||||
MOZ_ASSERT((attrs & ~(JSPROP_ENUMERATE |
|
MOZ_ASSERT((attrs & ~(JSPROP_ENUMERATE |
|
||||||
JSPROP_PERMANENT |
|
JSPROP_PERMANENT |
|
||||||
JSPROP_READONLY |
|
JSPROP_READONLY |
|
||||||
|
@ -2810,26 +2815,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace JS */
|
} // namespace js
|
||||||
|
|
||||||
namespace js {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RootedBase<JS::PropertyDescriptor>
|
|
||||||
: public JS::MutablePropertyDescriptorOperations<JS::Rooted<JS::PropertyDescriptor>>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class HandleBase<JS::PropertyDescriptor>
|
|
||||||
: public JS::PropertyDescriptorOperations<JS::Handle<JS::PropertyDescriptor>>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class MutableHandleBase<JS::PropertyDescriptor>
|
|
||||||
: public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JS::PropertyDescriptor>>
|
|
||||||
{};
|
|
||||||
|
|
||||||
} /* namespace js */
|
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
|
|
@ -571,7 +571,10 @@ JSCompartment::getNonSyntacticLexicalEnvironment(JSObject* enclosing) const
|
||||||
bool
|
bool
|
||||||
JSCompartment::addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name)
|
JSCompartment::addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name)
|
||||||
{
|
{
|
||||||
if (varNames_.put(name.get()))
|
MOZ_ASSERT(name);
|
||||||
|
MOZ_ASSERT(!isAtomsCompartment());
|
||||||
|
|
||||||
|
if (varNames_.put(name))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
|
@ -720,8 +723,9 @@ JSCompartment::sweepAfterMinorGC(JSTracer* trc)
|
||||||
{
|
{
|
||||||
globalWriteBarriered = 0;
|
globalWriteBarriered = 0;
|
||||||
|
|
||||||
if (innerViews.needsSweepAfterMinorGC())
|
InnerViewTable& table = innerViews.get();
|
||||||
innerViews.sweepAfterMinorGC();
|
if (table.needsSweepAfterMinorGC())
|
||||||
|
table.sweepAfterMinorGC();
|
||||||
|
|
||||||
crossCompartmentWrappers.sweepAfterMinorGC(trc);
|
crossCompartmentWrappers.sweepAfterMinorGC(trc);
|
||||||
}
|
}
|
||||||
|
@ -803,6 +807,12 @@ JSCompartment::sweepCrossCompartmentWrappers()
|
||||||
crossCompartmentWrappers.sweep();
|
crossCompartmentWrappers.sweep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JSCompartment::sweepVarNames()
|
||||||
|
{
|
||||||
|
varNames_.sweep();
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct TraceRootFunctor {
|
struct TraceRootFunctor {
|
||||||
JSTracer* trc;
|
JSTracer* trc;
|
||||||
|
|
|
@ -654,6 +654,7 @@ struct JSCompartment
|
||||||
void sweepDebugEnvironments();
|
void sweepDebugEnvironments();
|
||||||
void sweepNativeIterators();
|
void sweepNativeIterators();
|
||||||
void sweepTemplateObjects();
|
void sweepTemplateObjects();
|
||||||
|
void sweepVarNames();
|
||||||
|
|
||||||
void purge();
|
void purge();
|
||||||
void clearTables();
|
void clearTables();
|
||||||
|
|
|
@ -4870,6 +4870,8 @@ MAKE_GC_SWEEP_TASK(SweepMiscTask);
|
||||||
SweepAtomsTask::run()
|
SweepAtomsTask::run()
|
||||||
{
|
{
|
||||||
runtime->sweepAtoms();
|
runtime->sweepAtoms();
|
||||||
|
for (CompartmentsIter comp(runtime, SkipAtoms); !comp.done(); comp.next())
|
||||||
|
comp->sweepVarNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ void
|
/* virtual */ void
|
||||||
|
|
|
@ -592,21 +592,23 @@ class JSObject : public js::gc::Cell
|
||||||
void operator=(const JSObject& other) = delete;
|
void operator=(const JSObject& other) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class U>
|
template <typename Wrapper>
|
||||||
|
template <typename U>
|
||||||
MOZ_ALWAYS_INLINE JS::Handle<U*>
|
MOZ_ALWAYS_INLINE JS::Handle<U*>
|
||||||
js::RootedBase<JSObject*>::as() const
|
js::RootedBase<JSObject*, Wrapper>::as() const
|
||||||
{
|
{
|
||||||
const JS::Rooted<JSObject*>& self = *static_cast<const JS::Rooted<JSObject*>*>(this);
|
const Wrapper& self = *static_cast<const Wrapper*>(this);
|
||||||
MOZ_ASSERT(self->is<U>());
|
MOZ_ASSERT(self->template is<U>());
|
||||||
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
|
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Wrapper>
|
||||||
template <class U>
|
template <class U>
|
||||||
MOZ_ALWAYS_INLINE JS::Handle<U*>
|
MOZ_ALWAYS_INLINE JS::Handle<U*>
|
||||||
js::HandleBase<JSObject*>::as() const
|
js::HandleBase<JSObject*, Wrapper>::as() const
|
||||||
{
|
{
|
||||||
const JS::Handle<JSObject*>& self = *static_cast<const JS::Handle<JSObject*>*>(this);
|
const JS::Handle<JSObject*>& self = *static_cast<const JS::Handle<JSObject*>*>(this);
|
||||||
MOZ_ASSERT(self->is<U>());
|
MOZ_ASSERT(self->template is<U>());
|
||||||
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
|
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ ArrayBufferObject::detach(JSContext* cx, Handle<ArrayBufferObject*> buffer,
|
||||||
// Update all views of the buffer to account for the buffer having been
|
// Update all views of the buffer to account for the buffer having been
|
||||||
// detached, and clear the buffer's data and list of views.
|
// detached, and clear the buffer's data and list of views.
|
||||||
|
|
||||||
auto& innerViews = cx->compartment()->innerViews;
|
auto& innerViews = cx->compartment()->innerViews.get();
|
||||||
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(buffer)) {
|
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(buffer)) {
|
||||||
for (size_t i = 0; i < views->length(); i++)
|
for (size_t i = 0; i < views->length(); i++)
|
||||||
NoteViewBufferWasDetached((*views)[i], newContents, cx);
|
NoteViewBufferWasDetached((*views)[i], newContents, cx);
|
||||||
|
@ -425,7 +425,7 @@ ArrayBufferObject::changeContents(JSContext* cx, BufferContents newContents,
|
||||||
setNewData(cx->runtime()->defaultFreeOp(), newContents, ownsState);
|
setNewData(cx->runtime()->defaultFreeOp(), newContents, ownsState);
|
||||||
|
|
||||||
// Update all views.
|
// Update all views.
|
||||||
auto& innerViews = cx->compartment()->innerViews;
|
auto& innerViews = cx->compartment()->innerViews.get();
|
||||||
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) {
|
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) {
|
||||||
for (size_t i = 0; i < views->length(); i++)
|
for (size_t i = 0; i < views->length(); i++)
|
||||||
changeViewContents(cx, (*views)[i], oldDataPointer, newContents);
|
changeViewContents(cx, (*views)[i], oldDataPointer, newContents);
|
||||||
|
|
|
@ -555,7 +555,6 @@ class InnerViewTable
|
||||||
typedef Vector<ArrayBufferViewObject*, 1, SystemAllocPolicy> ViewVector;
|
typedef Vector<ArrayBufferViewObject*, 1, SystemAllocPolicy> ViewVector;
|
||||||
|
|
||||||
friend class ArrayBufferObject;
|
friend class ArrayBufferObject;
|
||||||
friend class WeakCacheBase<InnerViewTable>;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MapGCPolicy {
|
struct MapGCPolicy {
|
||||||
|
@ -616,23 +615,15 @@ class InnerViewTable
|
||||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <typename Wrapper>
|
||||||
class WeakCacheBase<InnerViewTable>
|
class MutableWrappedPtrOperations<InnerViewTable, Wrapper>
|
||||||
|
: public WrappedPtrOperations<InnerViewTable, Wrapper>
|
||||||
{
|
{
|
||||||
InnerViewTable& table() {
|
InnerViewTable& table() {
|
||||||
return static_cast<JS::WeakCache<InnerViewTable>*>(this)->get();
|
return static_cast<Wrapper*>(this)->get();
|
||||||
}
|
|
||||||
const InnerViewTable& table() const {
|
|
||||||
return static_cast<const JS::WeakCache<InnerViewTable>*>(this)->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InnerViewTable::ViewVector* maybeViewsUnbarriered(ArrayBufferObject* obj) {
|
|
||||||
return table().maybeViewsUnbarriered(obj);
|
|
||||||
}
|
|
||||||
void removeViews(ArrayBufferObject* obj) { table().removeViews(obj); }
|
|
||||||
void sweepAfterMinorGC() { table().sweepAfterMinorGC(); }
|
|
||||||
bool needsSweepAfterMinorGC() const { return table().needsSweepAfterMinorGC(); }
|
|
||||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
|
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
|
||||||
return table().sizeOfExcludingThis(mallocSizeOf);
|
return table().sizeOfExcludingThis(mallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1538,11 +1538,7 @@ GetSuperEnvFunction(JSContext* cx, InterpreterRegs& regs)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class ReservedRootedBase {
|
class ReservedRooted : public RootedBase<T, ReservedRooted<T>>
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class ReservedRooted : public ReservedRootedBase<T>
|
|
||||||
{
|
{
|
||||||
Rooted<T>* savedRoot;
|
Rooted<T>* savedRoot;
|
||||||
|
|
||||||
|
@ -1570,14 +1566,6 @@ class ReservedRooted : public ReservedRootedBase<T>
|
||||||
DECLARE_POINTER_ASSIGN_OPS(ReservedRooted, T)
|
DECLARE_POINTER_ASSIGN_OPS(ReservedRooted, T)
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
class ReservedRootedBase<Value> : public ValueOperations<ReservedRooted<Value>>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class ReservedRootedBase<Scope*> : public ScopeCastOperation<ReservedRooted<Scope*>>
|
|
||||||
{};
|
|
||||||
|
|
||||||
static MOZ_NEVER_INLINE bool
|
static MOZ_NEVER_INLINE bool
|
||||||
Interpret(JSContext* cx, RunState& state)
|
Interpret(JSContext* cx, RunState& state)
|
||||||
{
|
{
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче