зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central. r=merge a=merge
MozReview-Commit-ID: 36L7JL73CzG
This commit is contained in:
Коммит
c2d6023454
|
@ -11,3 +11,4 @@ skip-if = (os == 'win' && bits == 32) # Bug 1352791
|
|||
[browser_notification_remove_permission.js]
|
||||
[browser_notification_replace.js]
|
||||
[browser_notification_tab_switching.js]
|
||||
skip-if = os == "win" || os == "linux" # Bug 1243263
|
||||
|
|
|
@ -25,4 +25,7 @@ add_task(async function test_remove_history() {
|
|||
await BrowserTestUtils.waitForCondition(
|
||||
() => !gURLBar.popup.richlistbox.children.some(c => !c.collapsed && c.getAttribute("ac-value") == TEST_URL),
|
||||
"Waiting for the result to disappear");
|
||||
|
||||
gURLBar.popup.hidePopup();
|
||||
await promisePopupHidden(gURLBar.popup);
|
||||
});
|
||||
|
|
|
@ -131,6 +131,7 @@ skip-if = !e10s || debug || asan
|
|||
[browser_ext_tabs_audio.js]
|
||||
[browser_ext_tabs_captureVisibleTab.js]
|
||||
[browser_ext_tabs_create.js]
|
||||
skip-if = os == "linux" && debug && bits == 32 # Bug 1350189
|
||||
[browser_ext_tabs_create_invalid_url.js]
|
||||
[browser_ext_tabs_detectLanguage.js]
|
||||
[browser_ext_tabs_discarded.js]
|
||||
|
|
|
@ -1040,11 +1040,12 @@ Experiments.Experiments.prototype = {
|
|||
let result = await loadJSONAsync(path, { compression: "lz4" });
|
||||
this._populateFromCache(result);
|
||||
} catch (e) {
|
||||
this._experiments = new Map();
|
||||
if (e instanceof OS.File.Error && e.becauseNoSuchFile) {
|
||||
// No cached manifest yet.
|
||||
this._experiments = new Map();
|
||||
this._log.trace("_loadFromCache - no cached manifest yet");
|
||||
} else {
|
||||
throw e;
|
||||
this._log.error("_loadFromCache - caught error", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -393,3 +393,19 @@ add_task(async function test_expiration() {
|
|||
await promiseRestartManager();
|
||||
await removeCacheFile();
|
||||
});
|
||||
|
||||
add_task(async function test_invalid_cache() {
|
||||
// Save uncompressed data to the cache file to trigger a loading error.
|
||||
let encoder = new TextEncoder();
|
||||
let data = encoder.encode("foo");
|
||||
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir, "experiments.json");
|
||||
let options = { tmpPath: path + ".tmp" };
|
||||
await OS.File.writeAtomic(path, data, options);
|
||||
|
||||
// Trigger loading from the cache. This should not throw and gracefully recover.
|
||||
let experiments = new Experiments.Experiments(gPolicy);
|
||||
let list = await experiments.getExperiments();
|
||||
|
||||
Assert.deepEqual(list, [], "The experiments cache should be empty.");
|
||||
});
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Taken from upstream commit: 6a34276ba4e2e4f8dfb2123eb4e6795ae658486a
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
||||
- babel-preset-react @6.24.1
|
||||
- react @15.6.2
|
||||
- react-dom @15.6.2
|
||||
- webpack @3.6.0
|
|
@ -412,7 +412,7 @@ body {
|
|||
.modal-wrapper {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
|
@ -423,7 +423,7 @@ body {
|
|||
|
||||
.modal {
|
||||
top: 0;
|
||||
height: 230px;
|
||||
margin: auto;
|
||||
width: 500px;
|
||||
background-color: var(--theme-toolbar-background);
|
||||
transform: translateY(-250px);
|
||||
|
@ -438,7 +438,7 @@ body {
|
|||
|
||||
.modal.entered,
|
||||
.modal.exiting {
|
||||
transform: translateY(30px);
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
|
@ -490,7 +490,6 @@ body {
|
|||
}
|
||||
|
||||
.shortcuts-modal {
|
||||
height: fit-content;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
|
@ -973,7 +972,7 @@ html .arrow.expanded svg {
|
|||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
vertical-align: bottom;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
.theme-dark .webpack {
|
||||
|
@ -1428,6 +1427,7 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
display: flex;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
.sources-list .managed-tree {
|
||||
|
@ -1462,6 +1462,11 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.sources-list .tree .node .no-arrow {
|
||||
width: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.no-sources-message {
|
||||
font-size: 12px;
|
||||
color: var(--theme-comment-alt);
|
||||
|
@ -1497,7 +1502,7 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
position: relative;
|
||||
transition: all 0.25s ease;
|
||||
overflow: hidden;
|
||||
padding: 6.5px;
|
||||
padding: 8px 8px 7px 8px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: -1px;
|
||||
cursor: default;
|
||||
|
@ -2353,11 +2358,6 @@ html[dir="rtl"] .arrow svg,
|
|||
--theme-conditional-breakpoint-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.paused .CodeMirror-line,
|
||||
.paused .CodeMirror-linenumber {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/**
|
||||
* There's a known codemirror flex issue with chrome that this addresses.
|
||||
* BUG https://github.com/devtools-html/debugger.html/issues/63
|
||||
|
@ -2629,6 +2629,7 @@ html .breakpoints-list .breakpoint.paused {
|
|||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding: 1px 0;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.breakpoints-list .pause-indicator {
|
||||
|
@ -3216,12 +3217,26 @@ html .command-bar > button:disabled {
|
|||
offset-inline-start: auto;
|
||||
}
|
||||
|
||||
.welcomebox .small-size-layout {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.welcomebox .normal-layout {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.shortcutKeys {
|
||||
text-align: right;
|
||||
float: left;
|
||||
font-family: Courier;
|
||||
}
|
||||
|
||||
.shortcutKey {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
font-family: Courier;
|
||||
}
|
||||
|
||||
.shortcutFunction {
|
||||
text-align: left;
|
||||
float: left;
|
||||
|
@ -3231,6 +3246,24 @@ html .command-bar > button:disabled {
|
|||
html .welcomebox .toggle-button-end.collapsed {
|
||||
bottom: 1px;
|
||||
}
|
||||
|
||||
@media (max-width: 430px) {
|
||||
.welcomebox .small-size-layout {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.welcomebox .normal-layout {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.shortcutFunction {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.shortcutKey {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.source-header {
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
width: 100%;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -70,17 +70,74 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
/******/ __webpack_require__.p = "/assets/build";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 380);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 1282);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ 380:
|
||||
/***/ 1282:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(964);
|
||||
module.exports = __webpack_require__(1283);
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1283:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _prettyFast = __webpack_require__(802);
|
||||
|
||||
var _prettyFast2 = _interopRequireDefault(_prettyFast);
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(900);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
|
||||
|
||||
|
||||
function prettyPrint(_ref) {
|
||||
var url = _ref.url,
|
||||
indent = _ref.indent,
|
||||
source = _ref.source;
|
||||
|
||||
var prettified = (0, _prettyFast2.default)(source, {
|
||||
url: url,
|
||||
indent: " ".repeat(indent)
|
||||
});
|
||||
|
||||
return {
|
||||
code: prettified.code,
|
||||
mappings: invertMappings(prettified.map._mappings)
|
||||
};
|
||||
}
|
||||
|
||||
function invertMappings(mappings) {
|
||||
return mappings._array.map(m => {
|
||||
var mapping = {
|
||||
generated: {
|
||||
line: m.originalLine,
|
||||
column: m.originalColumn
|
||||
}
|
||||
};
|
||||
if (m.source) {
|
||||
mapping.source = m.source;
|
||||
mapping.original = {
|
||||
line: m.generatedLine,
|
||||
column: m.generatedColumn
|
||||
};
|
||||
mapping.name = m.name;
|
||||
}
|
||||
return mapping;
|
||||
});
|
||||
}
|
||||
|
||||
self.onmessage = workerHandler({ prettyPrint });
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 381:
|
||||
|
@ -7532,63 +7589,6 @@ module.exports = {
|
|||
streamingWorkerHandler
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 964:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _prettyFast = __webpack_require__(802);
|
||||
|
||||
var _prettyFast2 = _interopRequireDefault(_prettyFast);
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(900);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
|
||||
|
||||
|
||||
function prettyPrint(_ref) {
|
||||
var url = _ref.url,
|
||||
indent = _ref.indent,
|
||||
source = _ref.source;
|
||||
|
||||
var prettified = (0, _prettyFast2.default)(source, {
|
||||
url: url,
|
||||
indent: " ".repeat(indent)
|
||||
});
|
||||
|
||||
return {
|
||||
code: prettified.code,
|
||||
mappings: invertMappings(prettified.map._mappings)
|
||||
};
|
||||
}
|
||||
|
||||
function invertMappings(mappings) {
|
||||
return mappings._array.map(m => {
|
||||
var mapping = {
|
||||
generated: {
|
||||
line: m.originalLine,
|
||||
column: m.originalColumn
|
||||
}
|
||||
};
|
||||
if (m.source) {
|
||||
mapping.source = m.source;
|
||||
mapping.original = {
|
||||
line: m.generatedLine,
|
||||
column: m.generatedColumn
|
||||
};
|
||||
mapping.name = m.name;
|
||||
}
|
||||
return mapping;
|
||||
});
|
||||
}
|
||||
|
||||
self.onmessage = workerHandler({ prettyPrint });
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
|
|
|
@ -70,7 +70,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
/******/ __webpack_require__.p = "/assets/build";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 382);
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 1284);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
@ -262,168 +262,6 @@ function arrayMap(array, iteratee) {
|
|||
module.exports = arrayMap;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1123:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _getMatches = __webpack_require__(1173);
|
||||
|
||||
var _getMatches2 = _interopRequireDefault(_getMatches);
|
||||
|
||||
var _projectSearch = __webpack_require__(1140);
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(900);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
|
||||
|
||||
|
||||
self.onmessage = workerHandler({ getMatches: _getMatches2.default, findSourceMatches: _projectSearch.findSourceMatches });
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1138:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = buildQuery;
|
||||
|
||||
var _escapeRegExp = __webpack_require__(259);
|
||||
|
||||
var _escapeRegExp2 = _interopRequireDefault(_escapeRegExp);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/**
|
||||
* Ignore doing outline matches for less than 3 whitespaces
|
||||
*
|
||||
* @memberof utils/source-search
|
||||
* @static
|
||||
*/
|
||||
function ignoreWhiteSpace(str) {
|
||||
return (/^\s{0,2}$/.test(str) ? "(?!\\s*.*)" : str
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function wholeMatch(query, wholeWord) {
|
||||
if (query === "" || !wholeWord) {
|
||||
return query;
|
||||
}
|
||||
|
||||
return `\\b${query}\\b`;
|
||||
}
|
||||
|
||||
function buildFlags(caseSensitive, isGlobal) {
|
||||
if (caseSensitive && isGlobal) {
|
||||
return "g";
|
||||
}
|
||||
|
||||
if (!caseSensitive && isGlobal) {
|
||||
return "gi";
|
||||
}
|
||||
|
||||
if (!caseSensitive && !isGlobal) {
|
||||
return "i";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
function buildQuery(originalQuery, modifiers, _ref) {
|
||||
var _ref$isGlobal = _ref.isGlobal,
|
||||
isGlobal = _ref$isGlobal === undefined ? false : _ref$isGlobal,
|
||||
_ref$ignoreSpaces = _ref.ignoreSpaces,
|
||||
ignoreSpaces = _ref$ignoreSpaces === undefined ? false : _ref$ignoreSpaces;
|
||||
var caseSensitive = modifiers.caseSensitive,
|
||||
regexMatch = modifiers.regexMatch,
|
||||
wholeWord = modifiers.wholeWord;
|
||||
|
||||
|
||||
if (originalQuery === "") {
|
||||
return new RegExp(originalQuery);
|
||||
}
|
||||
|
||||
var query = originalQuery;
|
||||
if (ignoreSpaces) {
|
||||
query = ignoreWhiteSpace(query);
|
||||
}
|
||||
|
||||
if (!regexMatch) {
|
||||
query = (0, _escapeRegExp2.default)(query);
|
||||
}
|
||||
|
||||
query = wholeMatch(query, wholeWord);
|
||||
var flags = buildFlags(caseSensitive, isGlobal);
|
||||
|
||||
if (flags) {
|
||||
return new RegExp(query, flags);
|
||||
}
|
||||
|
||||
return new RegExp(query);
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1140:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.findSourceMatches = findSourceMatches;
|
||||
|
||||
var _source = __webpack_require__(233);
|
||||
|
||||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } // Maybe reuse file search's functions?
|
||||
|
||||
|
||||
function findSourceMatches(source, queryText) {
|
||||
var _ref;
|
||||
|
||||
var text = source.text;
|
||||
|
||||
if (!(0, _source.isLoaded)(source) || !text || queryText == "") {
|
||||
return [];
|
||||
}
|
||||
|
||||
var lines = text.split("\n");
|
||||
var result = undefined;
|
||||
var query = new RegExp(queryText, "g");
|
||||
|
||||
var matches = lines.map((_text, line) => {
|
||||
var indices = [];
|
||||
|
||||
while (result = query.exec(_text)) {
|
||||
indices.push({
|
||||
sourceId: source.id,
|
||||
line: line + 1,
|
||||
column: result.index,
|
||||
match: result[0],
|
||||
value: _text,
|
||||
text: result.input
|
||||
});
|
||||
}
|
||||
return indices;
|
||||
}).filter(_matches => _matches.length > 0);
|
||||
|
||||
matches = (_ref = []).concat.apply(_ref, _toConsumableArray(matches));
|
||||
return matches;
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1165:
|
||||
|
@ -681,44 +519,6 @@ module.exports = {
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1173:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = getMatches;
|
||||
|
||||
var _buildQuery = __webpack_require__(1138);
|
||||
|
||||
var _buildQuery2 = _interopRequireDefault(_buildQuery);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function getMatches(query, text, modifiers) {
|
||||
if (!query || !text || !modifiers) {
|
||||
return [];
|
||||
}
|
||||
var regexQuery = (0, _buildQuery2.default)(query, modifiers, {
|
||||
isGlobal: true
|
||||
});
|
||||
var matchedLocations = [];
|
||||
var lines = text.split("\n");
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var singleMatch = void 0;
|
||||
var line = lines[i];
|
||||
while ((singleMatch = regexQuery.exec(line)) !== null) {
|
||||
matchedLocations.push({ line: i, ch: singleMatch.index });
|
||||
}
|
||||
}
|
||||
return matchedLocations;
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 121:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
|
@ -809,6 +609,94 @@ var isArray = Array.isArray || function (xs) {
|
|||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1211:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = buildQuery;
|
||||
|
||||
var _escapeRegExp = __webpack_require__(259);
|
||||
|
||||
var _escapeRegExp2 = _interopRequireDefault(_escapeRegExp);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/**
|
||||
* Ignore doing outline matches for less than 3 whitespaces
|
||||
*
|
||||
* @memberof utils/source-search
|
||||
* @static
|
||||
*/
|
||||
function ignoreWhiteSpace(str) {
|
||||
return (/^\s{0,2}$/.test(str) ? "(?!\\s*.*)" : str
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function wholeMatch(query, wholeWord) {
|
||||
if (query === "" || !wholeWord) {
|
||||
return query;
|
||||
}
|
||||
|
||||
return `\\b${query}\\b`;
|
||||
}
|
||||
|
||||
function buildFlags(caseSensitive, isGlobal) {
|
||||
if (caseSensitive && isGlobal) {
|
||||
return "g";
|
||||
}
|
||||
|
||||
if (!caseSensitive && isGlobal) {
|
||||
return "gi";
|
||||
}
|
||||
|
||||
if (!caseSensitive && !isGlobal) {
|
||||
return "i";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
function buildQuery(originalQuery, modifiers, _ref) {
|
||||
var _ref$isGlobal = _ref.isGlobal,
|
||||
isGlobal = _ref$isGlobal === undefined ? false : _ref$isGlobal,
|
||||
_ref$ignoreSpaces = _ref.ignoreSpaces,
|
||||
ignoreSpaces = _ref$ignoreSpaces === undefined ? false : _ref$ignoreSpaces;
|
||||
var caseSensitive = modifiers.caseSensitive,
|
||||
regexMatch = modifiers.regexMatch,
|
||||
wholeWord = modifiers.wholeWord;
|
||||
|
||||
|
||||
if (originalQuery === "") {
|
||||
return new RegExp(originalQuery);
|
||||
}
|
||||
|
||||
var query = originalQuery;
|
||||
if (ignoreSpaces) {
|
||||
query = ignoreWhiteSpace(query);
|
||||
}
|
||||
|
||||
if (!regexMatch) {
|
||||
query = (0, _escapeRegExp2.default)(query);
|
||||
}
|
||||
|
||||
query = wholeMatch(query, wholeWord);
|
||||
var flags = buildFlags(caseSensitive, isGlobal);
|
||||
|
||||
if (flags) {
|
||||
return new RegExp(query, flags);
|
||||
}
|
||||
|
||||
return new RegExp(query);
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 122:
|
||||
|
@ -902,6 +790,126 @@ var objectKeys = Object.keys || function (obj) {
|
|||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1284:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(1285);
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1285:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _getMatches = __webpack_require__(1286);
|
||||
|
||||
var _getMatches2 = _interopRequireDefault(_getMatches);
|
||||
|
||||
var _projectSearch = __webpack_require__(1287);
|
||||
|
||||
var _devtoolsUtils = __webpack_require__(900);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var workerHandler = _devtoolsUtils.workerUtils.workerHandler;
|
||||
|
||||
|
||||
self.onmessage = workerHandler({ getMatches: _getMatches2.default, findSourceMatches: _projectSearch.findSourceMatches });
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1286:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = getMatches;
|
||||
|
||||
var _buildQuery = __webpack_require__(1211);
|
||||
|
||||
var _buildQuery2 = _interopRequireDefault(_buildQuery);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function getMatches(query, text, modifiers) {
|
||||
if (!query || !text || !modifiers) {
|
||||
return [];
|
||||
}
|
||||
var regexQuery = (0, _buildQuery2.default)(query, modifiers, {
|
||||
isGlobal: true
|
||||
});
|
||||
var matchedLocations = [];
|
||||
var lines = text.split("\n");
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var singleMatch = void 0;
|
||||
var line = lines[i];
|
||||
while ((singleMatch = regexQuery.exec(line)) !== null) {
|
||||
matchedLocations.push({ line: i, ch: singleMatch.index });
|
||||
}
|
||||
}
|
||||
return matchedLocations;
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1287:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.findSourceMatches = findSourceMatches;
|
||||
|
||||
var _source = __webpack_require__(233);
|
||||
|
||||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } // Maybe reuse file search's functions?
|
||||
|
||||
|
||||
function findSourceMatches(source, queryText) {
|
||||
var _ref;
|
||||
|
||||
var text = source.text;
|
||||
|
||||
if (!(0, _source.isLoaded)(source) || !text || queryText == "") {
|
||||
return [];
|
||||
}
|
||||
|
||||
var lines = text.split("\n");
|
||||
var result = undefined;
|
||||
var query = new RegExp(queryText, "g");
|
||||
|
||||
var matches = lines.map((_text, line) => {
|
||||
var indices = [];
|
||||
|
||||
while (result = query.exec(_text)) {
|
||||
indices.push({
|
||||
sourceId: source.id,
|
||||
line: line + 1,
|
||||
column: result.index,
|
||||
match: result[0],
|
||||
value: _text,
|
||||
text: result.input
|
||||
});
|
||||
}
|
||||
return indices;
|
||||
}).filter(_matches => _matches.length > 0);
|
||||
|
||||
matches = (_ref = []).concat.apply(_ref, _toConsumableArray(matches));
|
||||
return matches;
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 14:
|
||||
|
@ -949,7 +957,7 @@ module.exports = isObjectLike;
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isThirdParty = exports.isPretty = exports.isJavaScript = undefined;
|
||||
exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFileURL = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isThirdParty = exports.isPretty = exports.isJavaScript = undefined;
|
||||
|
||||
var _devtoolsSourceMap = __webpack_require__(898);
|
||||
|
||||
|
@ -1048,12 +1056,23 @@ function getRawSourceURL(url) {
|
|||
return url.replace(/:formatted$/, "");
|
||||
}
|
||||
|
||||
function getFilenameFromURL(url) {
|
||||
function resolveFileURL(url) {
|
||||
var transformUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : initialUrl => initialUrl;
|
||||
|
||||
url = getRawSourceURL(url || "");
|
||||
var name = (0, _path.basename)(url) || "(index)";
|
||||
var name = transformUrl(url);
|
||||
return (0, _utils.endTruncateStr)(name, 50);
|
||||
}
|
||||
|
||||
function getFilenameFromURL(url) {
|
||||
return resolveFileURL(url, initialUrl => (0, _path.basename)(initialUrl) || "(index)");
|
||||
}
|
||||
|
||||
function getFormattedSourceId(id) {
|
||||
var sourceId = id.split("/")[1];
|
||||
return `SOURCE${sourceId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a source url's filename.
|
||||
* If the source does not have a url, use the source id.
|
||||
|
@ -1066,13 +1085,30 @@ function getFilename(source) {
|
|||
id = source.id;
|
||||
|
||||
if (!url) {
|
||||
var sourceId = id.split("/")[1];
|
||||
return `SOURCE${sourceId}`;
|
||||
return getFormattedSourceId(id);
|
||||
}
|
||||
|
||||
return getFilenameFromURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a source url.
|
||||
* If the source does not have a url, use the source id.
|
||||
*
|
||||
* @memberof utils/source
|
||||
* @static
|
||||
*/
|
||||
function getFileURL(source) {
|
||||
var url = source.url,
|
||||
id = source.id;
|
||||
|
||||
if (!url) {
|
||||
return getFormattedSourceId(id);
|
||||
}
|
||||
|
||||
return resolveFileURL(url);
|
||||
}
|
||||
|
||||
var contentTypeModeMap = {
|
||||
"text/javascript": { name: "javascript" },
|
||||
"text/typescript": { name: "javascript", typescript: true },
|
||||
|
@ -1184,6 +1220,7 @@ exports.getPrettySourceURL = getPrettySourceURL;
|
|||
exports.getRawSourceURL = getRawSourceURL;
|
||||
exports.getFilename = getFilename;
|
||||
exports.getFilenameFromURL = getFilenameFromURL;
|
||||
exports.getFileURL = getFileURL;
|
||||
exports.getSourcePath = getSourcePath;
|
||||
exports.getSourceLineCount = getSourceLineCount;
|
||||
exports.getMode = getMode;
|
||||
|
@ -2463,14 +2500,6 @@ module.exports = {
|
|||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 382:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(1123);
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6:
|
||||
|
|
|
@ -19,6 +19,9 @@ support-files =
|
|||
examples/sum/sum.js
|
||||
examples/sum/sum.min.js
|
||||
examples/sum/sum.min.js.map
|
||||
examples/reload/code_reload_1.js
|
||||
examples/reload/code_reload_2.js
|
||||
examples/reload/doc_reload.html
|
||||
examples/doc-async.html
|
||||
examples/doc-asm.html
|
||||
examples/doc-scripts.html
|
||||
|
@ -53,6 +56,7 @@ support-files =
|
|||
examples/script-switching-02.js
|
||||
examples/script-switching-01.js
|
||||
examples/times2.js
|
||||
examples/reload/sjs_code_reload.sjs
|
||||
|
||||
[browser_dbg-asm.js]
|
||||
[browser_dbg-async-stepping.js]
|
||||
|
@ -64,7 +68,6 @@ support-files =
|
|||
skip-if = true # Bug 1383576
|
||||
[browser_dbg-breakpoints-cond.js]
|
||||
[browser_dbg-call-stack.js]
|
||||
[browser_dbg-expressions.js]
|
||||
[browser_dbg-scopes.js]
|
||||
[browser_dbg-chrome-create.js]
|
||||
[browser_dbg-chrome-debugging.js]
|
||||
|
@ -74,6 +77,8 @@ skip-if = debug # bug 1374187
|
|||
[browser_dbg-editor-gutter.js]
|
||||
[browser_dbg-editor-select.js]
|
||||
[browser_dbg-editor-highlight.js]
|
||||
[browser_dbg-expressions.js]
|
||||
[browser_dbg-expressions-error.js]
|
||||
[browser_dbg-iframes.js]
|
||||
[browser_dbg_keyboard_navigation.js]
|
||||
[browser_dbg_keyboard-shortcuts.js]
|
||||
|
@ -102,4 +107,4 @@ skip-if = true # Bug 1393121, 1393299
|
|||
[browser_dbg-tabs.js]
|
||||
[browser_dbg-toggling-tools.js]
|
||||
[browser_dbg-wasm-sourcemaps.js]
|
||||
skip-if = true
|
||||
[browser_dbg-reload.js]
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* test pausing on an errored watch expression
|
||||
* assert that you can:
|
||||
* 1. resume
|
||||
* 2. still evalutate expressions
|
||||
* 3. expand properties
|
||||
*/
|
||||
|
||||
const expressionSelectors = {
|
||||
input: "input.input-expression"
|
||||
};
|
||||
|
||||
function getLabel(dbg, index) {
|
||||
return findElement(dbg, "expressionNode", index).innerText;
|
||||
}
|
||||
|
||||
function getValue(dbg, index) {
|
||||
return findElement(dbg, "expressionValue", index).innerText;
|
||||
}
|
||||
|
||||
function assertEmptyValue(dbg, index) {
|
||||
const value = findElement(dbg, "expressionValue", index);
|
||||
if (value) {
|
||||
is(value.innerText, "");
|
||||
return;
|
||||
}
|
||||
|
||||
is(value, null);
|
||||
}
|
||||
|
||||
function toggleExpression(dbg, index) {
|
||||
findElement(dbg, "expressionNode", index).click();
|
||||
}
|
||||
|
||||
async function addExpression(dbg, input) {
|
||||
info("Adding an expression");
|
||||
findElementWithSelector(dbg, expressionSelectors.input).focus();
|
||||
type(dbg, input);
|
||||
pressKey(dbg, "Enter");
|
||||
|
||||
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
|
||||
}
|
||||
|
||||
async function editExpression(dbg, input) {
|
||||
info("updating the expression");
|
||||
dblClickElement(dbg, "expressionNode", 1);
|
||||
// Position cursor reliably at the end of the text.
|
||||
pressKey(dbg, "End");
|
||||
type(dbg, input);
|
||||
pressKey(dbg, "Enter");
|
||||
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
|
||||
}
|
||||
|
||||
/*
|
||||
* When we add a bad expression, we'll pause,
|
||||
* resume, and wait for the expression to finish being evaluated.
|
||||
*/
|
||||
async function addBadExpression(dbg, input) {
|
||||
const paused = waitForPaused(dbg);
|
||||
const added = addExpression(dbg, input);
|
||||
|
||||
await paused;
|
||||
ok(dbg.selectors.isEvaluatingExpression(dbg.getState()));
|
||||
await resume(dbg);
|
||||
await added;
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-script-switching.html");
|
||||
|
||||
await togglePauseOnExceptions(dbg, true, false);
|
||||
|
||||
// add a good expression, 2 bad expressions, and another good one
|
||||
await addExpression(dbg, "location");
|
||||
await addBadExpression(dbg, "foo.bar");
|
||||
await addBadExpression(dbg, "foo.batt");
|
||||
await addExpression(dbg, "2");
|
||||
|
||||
// check the value of
|
||||
is(getValue(dbg, 2), "(unavailable)")
|
||||
is(getValue(dbg, 3), "(unavailable)")
|
||||
is(getValue(dbg, 4), 2);
|
||||
|
||||
toggleExpression(dbg, 1);
|
||||
await waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
|
||||
is(findAllElements(dbg, "expressionNodes").length, 20);
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* Test reloading:
|
||||
* 1. reload the source
|
||||
* 2. re-sync breakpoints
|
||||
*/
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("reload/doc_reload.html", "sjs_code_reload");
|
||||
|
||||
const sym = waitForDispatch(dbg, "SET_SYMBOLS");
|
||||
await selectSource(dbg, "sjs_code_reload");
|
||||
await sym;
|
||||
|
||||
await addBreakpoint(dbg, "sjs_code_reload", 2);
|
||||
|
||||
const sync = waitForDispatch(dbg, "SYNC_BREAKPOINT");
|
||||
await reload(dbg, "sjs_code_reload");
|
||||
await sync;
|
||||
|
||||
const breakpoints = dbg.selectors.getBreakpoints(dbg.getState());
|
||||
const breakpointList = breakpoints.valueSeq().toJS();
|
||||
const breakpoint = breakpointList[0];
|
||||
|
||||
is(breakpointList.length, 1);
|
||||
is(breakpoint.location.line, 6);
|
||||
});
|
|
@ -11,6 +11,7 @@ add_task(async function() {
|
|||
await waitForPaused(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
await waitForSource(dbg, "wasm-sourcemaps/average.c");
|
||||
await addBreakpoint(dbg, "wasm-sourcemaps/average.c", 12);
|
||||
|
||||
clickElement(dbg, "resume");
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
function foo(n) {
|
||||
console.log("yo")
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* comments
|
||||
*/
|
||||
|
||||
function foo() {
|
||||
console.log("YO")
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<script src="sjs_code_reload.sjs"></script>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Empty test page 1</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,32 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* globals getState, setState */
|
||||
/* exported handleRequest */
|
||||
|
||||
"use strict";
|
||||
|
||||
function _getUrl(request, counter) {
|
||||
const { scheme, host, path } = request;
|
||||
|
||||
const newPath = path.substr(0, path.lastIndexOf("/") + 1);
|
||||
const index = counter < 3 ? 1 : 2;
|
||||
return `${scheme}://${host}${newPath}/code_reload_${index}.js`
|
||||
}
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
response.setHeader("Access-Control-Allow-Origin", "*", false);
|
||||
response.setHeader("Content-Type", "text/javascript", false);
|
||||
|
||||
// Redirect to a different file each time.
|
||||
let counter = 1 + +getState("counter");
|
||||
|
||||
const newUrl = _getUrl(request, counter);
|
||||
|
||||
response.setStatusLine(request.httpVersion, 302, "Found");
|
||||
response.setHeader("Location", newUrl);
|
||||
setState("counter", "" + counter);
|
||||
}
|
|
@ -504,7 +504,7 @@ function stepOut(dbg) {
|
|||
function resume(dbg) {
|
||||
info("Resuming");
|
||||
dbg.actions.resume();
|
||||
return waitForThreadEvents(dbg, "resumed");
|
||||
return waitForState(dbg, (state) => !dbg.selectors.isPaused(state));
|
||||
}
|
||||
|
||||
function deleteExpression(dbg, input) {
|
||||
|
|
|
@ -790,3 +790,7 @@ shortcuts.projectSearch=Full Project Search
|
|||
# LOCALIZATION NOTE (shortcuts.functionSearch): text describing
|
||||
# keyboard shortcut action for function search
|
||||
shortcuts.functionSearch=Function Search
|
||||
|
||||
# LOCALIZATION NOTE (shortcuts.buttonName): text describing
|
||||
# keyboard shortcut button text
|
||||
shortcuts.buttonName=Keyboard shortcuts
|
||||
|
|
|
@ -31,7 +31,6 @@ pref("devtools.debugger.ui.variables-only-enum-visible", false);
|
|||
pref("devtools.debugger.ui.variables-searchbox-visible", false);
|
||||
pref("devtools.debugger.ui.framework-grouping-on", true);
|
||||
pref("devtools.debugger.call-stack-visible", false);
|
||||
pref("devtools.debugger.scopes-visible", false);
|
||||
pref("devtools.debugger.start-panel-collapsed", false);
|
||||
pref("devtools.debugger.end-panel-collapsed", false);
|
||||
pref("devtools.debugger.tabs", "[]");
|
||||
|
|
|
@ -814,10 +814,8 @@ NetworkMonitor.prototype = {
|
|||
|
||||
this.interceptedChannels.add(subject);
|
||||
|
||||
// On e10s, we never receive http-on-examine-cached-response, so fake one.
|
||||
if (Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT) {
|
||||
this._httpResponseExaminer(channel, "http-on-examine-cached-response");
|
||||
}
|
||||
// Service workers never fire http-on-examine-cached-response, so fake one.
|
||||
this._httpResponseExaminer(channel, "http-on-examine-cached-response");
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -97,11 +97,6 @@ let expectedConsoleCalls = [
|
|||
filename: /helper_serviceworker/,
|
||||
arguments: ['fetch event: ' + SCOPE_FRAME_URL2],
|
||||
},
|
||||
{
|
||||
level: "log",
|
||||
filename: /helper_serviceworker/,
|
||||
arguments: ['message event: ' + MESSAGE],
|
||||
},
|
||||
];
|
||||
let consoleCalls = [];
|
||||
|
||||
|
@ -169,10 +164,9 @@ let onAttach = Task.async(function*(state, response) {
|
|||
|
||||
// Now postMessage() the service worker to trigger its message event
|
||||
// handler. This will generate 1 or 2 to console.log() statements
|
||||
// depending on if the worker thread needs to spin up again. Although we
|
||||
// don't have a controlled or registering document in both cases, we still
|
||||
// could get console calls since we only flush reports when the channel is
|
||||
// finally destroyed.
|
||||
// depending on if the worker thread needs to spin up again. In either
|
||||
// case, though, we should not get any console calls because we don't
|
||||
// have a controlled or registering document.
|
||||
info("Completed force refresh. Messaging service worker.");
|
||||
yield messageServiceWorker(currentFrame.contentWindow, SCOPE, MESSAGE);
|
||||
|
||||
|
|
|
@ -15066,7 +15066,7 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
|||
{
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
aChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
|
||||
aChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -513,10 +513,10 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
|
|||
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
|
||||
// even though the hardware supports much more. The
|
||||
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
|
||||
gl->GetUIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
|
||||
mGLMaxCombinedTextureImageUnits = mGLMaxTextureUnits;
|
||||
mGLMaxCombinedTextureImageUnits = gl->GetIntAs<GLuint>(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
|
||||
mGLMaxTextureUnits = mGLMaxCombinedTextureImageUnits;
|
||||
|
||||
if (mGLMaxTextureUnits < 8) {
|
||||
if (mGLMaxCombinedTextureImageUnits < 8) {
|
||||
const nsPrintfCString reason("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %u is < 8!",
|
||||
mGLMaxTextureUnits);
|
||||
*out_failReason = { "FEATURE_FAILURE_WEBGL_T_UNIT", reason };
|
||||
|
|
|
@ -1295,8 +1295,9 @@ EventStateManager::DispatchCrossProcessEvent(WidgetEvent* aEvent,
|
|||
return;
|
||||
}
|
||||
case eDragEventClass: {
|
||||
if (remote->Manager()->IsContentParent()) {
|
||||
remote->Manager()->AsContentParent()->MaybeInvokeDragSession(remote);
|
||||
RefPtr<TabParent> tabParent = remote;
|
||||
if (tabParent->Manager()->IsContentParent()) {
|
||||
tabParent->Manager()->AsContentParent()->MaybeInvokeDragSession(tabParent);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
|
||||
|
@ -1312,7 +1313,7 @@ EventStateManager::DispatchCrossProcessEvent(WidgetEvent* aEvent,
|
|||
}
|
||||
}
|
||||
|
||||
remote->SendRealDragEvent(*aEvent->AsDragEvent(), action, dropEffect);
|
||||
tabParent->SendRealDragEvent(*aEvent->AsDragEvent(), action, dropEffect);
|
||||
return;
|
||||
}
|
||||
case ePluginEventClass: {
|
||||
|
|
|
@ -872,26 +872,32 @@ FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|||
}
|
||||
|
||||
// "HTTP-redirect fetch": step 14 "Append locationURL to request's URL list."
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
MOZ_ALWAYS_SUCCEEDS(aNewChannel->GetURI(getter_AddRefs(uri)));
|
||||
// However, ignore internal redirects here. We don't want to flip
|
||||
// Response.redirected to true if an internal redirect occurs. These
|
||||
// should be transparent to script.
|
||||
if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
MOZ_ALWAYS_SUCCEEDS(aNewChannel->GetURI(getter_AddRefs(uri)));
|
||||
|
||||
nsCOMPtr<nsIURI> uriClone;
|
||||
nsresult rv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
|
||||
if(NS_WARN_IF(NS_FAILED(rv))){
|
||||
return rv;
|
||||
}
|
||||
nsCString spec;
|
||||
rv = uriClone->GetSpec(spec);
|
||||
if(NS_WARN_IF(NS_FAILED(rv))){
|
||||
return rv;
|
||||
}
|
||||
nsCString fragment;
|
||||
rv = uri->GetRef(fragment);
|
||||
if(NS_WARN_IF(NS_FAILED(rv))){
|
||||
return rv;
|
||||
nsCOMPtr<nsIURI> uriClone;
|
||||
nsresult rv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
|
||||
if(NS_WARN_IF(NS_FAILED(rv))){
|
||||
return rv;
|
||||
}
|
||||
nsCString spec;
|
||||
rv = uriClone->GetSpec(spec);
|
||||
if(NS_WARN_IF(NS_FAILED(rv))){
|
||||
return rv;
|
||||
}
|
||||
nsCString fragment;
|
||||
rv = uri->GetRef(fragment);
|
||||
if(NS_WARN_IF(NS_FAILED(rv))){
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRequest->AddURL(spec, fragment);
|
||||
}
|
||||
|
||||
mRequest->AddURL(spec, fragment);
|
||||
NS_ConvertUTF8toUTF16 tRPHeaderValue(tRPHeaderCValue);
|
||||
// updates request’s associated referrer policy according to the
|
||||
// Referrer-Policy header (if any).
|
||||
|
@ -902,10 +908,10 @@ FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|||
mRequest->SetReferrerPolicy(net_referrerPolicy);
|
||||
// Should update channel's referrer policy
|
||||
if (httpChannel) {
|
||||
rv = FetchUtil::SetRequestReferrer(mPrincipal,
|
||||
mDocument,
|
||||
httpChannel,
|
||||
mRequest);
|
||||
nsresult rv = FetchUtil::SetRequestReferrer(mPrincipal,
|
||||
mDocument,
|
||||
httpChannel,
|
||||
mRequest);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,6 +201,10 @@ public:
|
|||
{
|
||||
GetHTMLAttr(nsGkAtoms::name, aValue);
|
||||
}
|
||||
void GetName(nsAString& aValue)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::name, aValue);
|
||||
}
|
||||
void SetName(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::name, aValue, rv);
|
||||
|
|
|
@ -32,6 +32,8 @@ public:
|
|||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLBodyElement, body);
|
||||
|
||||
// Event listener stuff; we need to declare only the ones we need to
|
||||
// forward to window that don't come from nsIDOMHTMLBodyElement.
|
||||
#define EVENT(name_, id_, type_, struct_) /* nothing; handled by the shim */
|
||||
|
@ -112,6 +114,10 @@ public:
|
|||
{
|
||||
GetHTMLAttr(nsGkAtoms::background, aBackground);
|
||||
}
|
||||
void GetBackground(nsAString& aBackground)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::background, aBackground);
|
||||
}
|
||||
void SetBackground(const nsAString& aBackground, ErrorResult& aError)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::background, aBackground, aError);
|
||||
|
|
|
@ -1528,6 +1528,11 @@ CSPReportRedirectSink::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|||
uint32_t aRedirFlags,
|
||||
nsIAsyncVerifyRedirectCallback* aCallback)
|
||||
{
|
||||
if (aRedirFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
|
||||
aCallback->OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// cancel the old channel so XHR failure callback happens
|
||||
nsresult rv = aOldChannel->Cancel(NS_ERROR_ABORT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -34,9 +34,9 @@ public:
|
|||
: mKey(*aKey),
|
||||
mForceCompositing(false)
|
||||
{ }
|
||||
nsSMILCompositor(const nsSMILCompositor& toCopy)
|
||||
: mKey(toCopy.mKey),
|
||||
mAnimationFunctions(toCopy.mAnimationFunctions),
|
||||
nsSMILCompositor(nsSMILCompositor&& toMove)
|
||||
: mKey(mozilla::Move(toMove.mKey)),
|
||||
mAnimationFunctions(mozilla::Move(toMove.mAnimationFunctions)),
|
||||
mForceCompositing(false)
|
||||
{ }
|
||||
~nsSMILCompositor() { }
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
#include "nsSMILValue.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
/*static*/ nsSMILNullType*
|
||||
nsSMILNullType::Singleton()
|
||||
{
|
||||
static nsSMILNullType sSingleton;
|
||||
return &sSingleton;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSMILNullType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
|
||||
{
|
||||
|
|
|
@ -14,12 +14,7 @@ class nsSMILNullType : public nsISMILType
|
|||
{
|
||||
public:
|
||||
// Singleton for nsSMILValue objects to hold onto.
|
||||
static nsSMILNullType*
|
||||
Singleton()
|
||||
{
|
||||
static nsSMILNullType sSingleton;
|
||||
return &sSingleton;
|
||||
}
|
||||
static nsSMILNullType* Singleton();
|
||||
|
||||
protected:
|
||||
// nsISMILType Methods
|
||||
|
|
|
@ -9,11 +9,13 @@ interface XPathEvaluator {
|
|||
// Based on nsIDOMXPathEvaluator
|
||||
[NewObject, Throws]
|
||||
XPathExpression createExpression(DOMString expression,
|
||||
XPathNSResolver? resolver);
|
||||
optional XPathNSResolver? resolver = null);
|
||||
[Pure]
|
||||
Node createNSResolver(Node nodeResolver);
|
||||
[Throws]
|
||||
XPathResult evaluate(DOMString expression, Node contextNode,
|
||||
XPathNSResolver? resolver, unsigned short type,
|
||||
object? result);
|
||||
XPathResult evaluate(DOMString expression,
|
||||
Node contextNode,
|
||||
optional XPathNSResolver? resolver = null,
|
||||
optional unsigned short type = 0 /* XPathResult.ANY_TYPE */,
|
||||
optional object? result = null);
|
||||
};
|
||||
|
|
|
@ -9,7 +9,9 @@ interface XPathExpression {
|
|||
// returned by this method. If this is specified as null or it's not an
|
||||
// XPathResult object, a new result object will be constructed and returned.
|
||||
[Throws]
|
||||
XPathResult evaluate(Node contextNode, unsigned short type, object? result);
|
||||
XPathResult evaluate(Node contextNode,
|
||||
optional unsigned short type = 0 /* XPathResult.ANY_TYPE */,
|
||||
optional object? result = null);
|
||||
|
||||
// The result specifies a specific result object which may be reused and
|
||||
// returned by this method. If this is specified as null or it's not an
|
||||
|
@ -18,5 +20,6 @@ interface XPathExpression {
|
|||
XPathResult evaluateWithContext(Node contextNode,
|
||||
unsigned long contextPosition,
|
||||
unsigned long contextSize,
|
||||
unsigned short type, object? result);
|
||||
optional unsigned short type = 0 /* XPathResult.ANY_TYPE */,
|
||||
optional object? result = null);
|
||||
};
|
||||
|
|
|
@ -115,7 +115,7 @@ CancelChannelRunnable::Run()
|
|||
mChannel->SetHandleFetchEventEnd(TimeStamp::Now());
|
||||
mChannel->SaveTimeStamps();
|
||||
|
||||
mChannel->Cancel(mStatus);
|
||||
mChannel->CancelInterception(mStatus);
|
||||
mRegistration->MaybeScheduleUpdate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ public:
|
|||
nsCOMPtr<nsILoadInfo> loadInfo = underlyingChannel->GetLoadInfo();
|
||||
|
||||
if (!loadInfo || !CSPPermitsResponse(loadInfo)) {
|
||||
mChannel->Cancel(NS_ERROR_CONTENT_BLOCKED);
|
||||
mChannel->CancelInterception(NS_ERROR_CONTENT_BLOCKED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -213,14 +213,14 @@ public:
|
|||
}
|
||||
rv = mChannel->SetChannelInfo(&channelInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
|
||||
mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = mChannel->SynthesizeStatus(mInternalResponse->GetUnfilteredStatus(),
|
||||
mInternalResponse->GetUnfilteredStatusText());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
|
||||
mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ public:
|
|||
|
||||
rv = mChannel->FinishSynthesizedResponse(mResponseURLSpec);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
|
||||
mChannel->CancelInterception(NS_ERROR_INTERCEPTION_FAILED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body>
|
||||
<select>
|
||||
<script>document.documentElement.offsetHeight</script>
|
||||
<option>Hello there</option>
|
||||
</select>
|
||||
<script>
|
||||
document.querySelector("body").style.display = "inline";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -10,3 +10,4 @@ load 453278.html
|
|||
load 803586.xhtml
|
||||
load 994740-1.xhtml
|
||||
load 1038887.xhtml
|
||||
load 1405878.xml
|
||||
|
|
|
@ -1070,6 +1070,17 @@ nsXMLContentSink::HandleEndElement(const char16_t *aName,
|
|||
isTemplateElement, "Wrong element being closed");
|
||||
#endif
|
||||
|
||||
// Make sure to notify on our kids before we call out to any other code that
|
||||
// might reenter us and call FlushTags, in a state in which we've already
|
||||
// popped "content" from the stack but haven't notified on its kids yet.
|
||||
int32_t stackLen = mContentStack.Length();
|
||||
if (mNotifyLevel >= stackLen) {
|
||||
if (numFlushed < content->GetChildCount()) {
|
||||
NotifyAppend(content, numFlushed);
|
||||
}
|
||||
mNotifyLevel = stackLen - 1;
|
||||
}
|
||||
|
||||
result = CloseElement(content);
|
||||
|
||||
if (mCurrentHead == content) {
|
||||
|
@ -1085,13 +1096,6 @@ nsXMLContentSink::HandleEndElement(const char16_t *aName,
|
|||
MaybeStartLayout(false);
|
||||
}
|
||||
|
||||
int32_t stackLen = mContentStack.Length();
|
||||
if (mNotifyLevel >= stackLen) {
|
||||
if (numFlushed < content->GetChildCount()) {
|
||||
NotifyAppend(content, numFlushed);
|
||||
}
|
||||
mNotifyLevel = stackLen - 1;
|
||||
}
|
||||
DidAddContent();
|
||||
|
||||
if (content->IsSVGElement(nsGkAtoms::svg)) {
|
||||
|
|
|
@ -112,9 +112,9 @@ public:
|
|||
: nsRefPtrHashKey<PermissionKey>(aPermissionKey)
|
||||
{}
|
||||
|
||||
PermissionHashKey(const PermissionHashKey& toCopy)
|
||||
: nsRefPtrHashKey<PermissionKey>(toCopy)
|
||||
, mPermissions(toCopy.mPermissions)
|
||||
PermissionHashKey(PermissionHashKey&& toCopy)
|
||||
: nsRefPtrHashKey<PermissionKey>(mozilla::Move(toCopy))
|
||||
, mPermissions(mozilla::Move(toCopy.mPermissions))
|
||||
{}
|
||||
|
||||
bool KeyEquals(const PermissionKey* aKey) const
|
||||
|
|
|
@ -166,12 +166,12 @@ static gfx::IntRect ContainerVisibleRect(ContainerT* aContainer)
|
|||
/* all of the per-layer prepared data we need to maintain */
|
||||
struct PreparedLayer
|
||||
{
|
||||
PreparedLayer(LayerComposite *aLayer,
|
||||
PreparedLayer(Layer *aLayer,
|
||||
RenderTargetIntRect aClipRect,
|
||||
Maybe<gfx::Polygon>&& aGeometry)
|
||||
: mLayer(aLayer), mClipRect(aClipRect), mGeometry(Move(aGeometry)) {}
|
||||
|
||||
LayerComposite* mLayer;
|
||||
RefPtr<Layer> mLayer;
|
||||
RenderTargetIntRect mClipRect;
|
||||
Maybe<Polygon> mGeometry;
|
||||
};
|
||||
|
@ -235,7 +235,8 @@ ContainerPrepare(ContainerT* aContainer,
|
|||
CULLING_LOG("Preparing sublayer %p\n", layerToRender->GetLayer());
|
||||
|
||||
layerToRender->Prepare(clipRect);
|
||||
aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender, clipRect,
|
||||
aContainer->mPrepared->mLayers.AppendElement(PreparedLayer(layerToRender->GetLayer(),
|
||||
clipRect,
|
||||
Move(layer.geometry)));
|
||||
}
|
||||
|
||||
|
@ -413,7 +414,7 @@ RenderLayers(ContainerT* aContainer, LayerManagerComposite* aManager,
|
|||
PreparedLayer& preparedData = aContainer->mPrepared->mLayers[i];
|
||||
|
||||
const gfx::IntRect clipRect = preparedData.mClipRect.ToUnknownRect();
|
||||
LayerComposite* layerToRender = preparedData.mLayer;
|
||||
LayerComposite* layerToRender = static_cast<LayerComposite*>(preparedData.mLayer->ImplData());
|
||||
const Maybe<gfx::Polygon>& childGeometry = preparedData.mGeometry;
|
||||
|
||||
Layer* layer = layerToRender->GetLayer();
|
||||
|
|
|
@ -20,15 +20,12 @@ StackingContextHelper::StackingContextHelper()
|
|||
|
||||
StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
nsDisplayList* aDisplayList,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters,
|
||||
const gfx::Matrix4x4* aBoundTransform,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
gfx::Matrix4x4* aPerspectivePtr,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters,
|
||||
const gfx::CompositionOp& aMixBlendMode,
|
||||
bool aBackfaceVisible)
|
||||
: mBuilder(&aBuilder)
|
||||
|
|
|
@ -30,15 +30,12 @@ class MOZ_RAII StackingContextHelper
|
|||
public:
|
||||
StackingContextHelper(const StackingContextHelper& aParentSC,
|
||||
wr::DisplayListBuilder& aBuilder,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
nsDisplayItem* aItem,
|
||||
nsDisplayList* aDisplayList,
|
||||
const gfx::Matrix4x4* aBoundTransform,
|
||||
uint64_t aAnimationsId,
|
||||
float* aOpacityPtr,
|
||||
gfx::Matrix4x4* aTransformPtr,
|
||||
gfx::Matrix4x4* aPerspectivePtr = nullptr,
|
||||
const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
|
||||
const gfx::Matrix4x4* aBoundTransform = nullptr,
|
||||
uint64_t aAnimationsId = 0,
|
||||
float* aOpacityPtr = nullptr,
|
||||
gfx::Matrix4x4* aTransformPtr = nullptr,
|
||||
gfx::Matrix4x4* aPerspectivePtr = nullptr,
|
||||
const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
|
||||
bool aBackfaceVisible = true);
|
||||
// This version of the constructor should only be used at the root level
|
||||
|
|
|
@ -46,8 +46,11 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
|
|||
mLastCanvasDatas.Clear();
|
||||
mLastAsr = nullptr;
|
||||
|
||||
CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc,
|
||||
aBuilder, aResourceUpdates);
|
||||
{
|
||||
StackingContextHelper pageRootSc(sc, aBuilder);
|
||||
CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder,
|
||||
pageRootSc, aBuilder, aResourceUpdates);
|
||||
}
|
||||
|
||||
// Make a "root" layer data that has everything else as descendants
|
||||
mLayerScrollData.emplace_back();
|
||||
|
|
|
@ -237,7 +237,7 @@ AssertGCThingIsNotAnObjectSubclass(js::gc::Cell* cell) {}
|
|||
* Type T must be a public GC pointer type.
|
||||
*/
|
||||
template <typename T>
|
||||
class Heap : public js::HeapBase<T, Heap<T>>
|
||||
class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T, Heap<T>>
|
||||
{
|
||||
// Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons.
|
||||
static_assert(js::IsHeapConstructibleType<T>::value,
|
||||
|
@ -1173,6 +1173,14 @@ class JS_PUBLIC_API(ObjectPtr)
|
|||
|
||||
explicit ObjectPtr(JSObject* obj) : value(obj) {}
|
||||
|
||||
ObjectPtr(const ObjectPtr& other) : value(other.value) {}
|
||||
|
||||
ObjectPtr(ObjectPtr&& other)
|
||||
: value(other.value)
|
||||
{
|
||||
other.value = nullptr;
|
||||
}
|
||||
|
||||
/* Always call finalize before the destructor. */
|
||||
~ObjectPtr() { MOZ_ASSERT(!value); }
|
||||
|
||||
|
|
|
@ -1428,14 +1428,25 @@ auto
|
|||
DispatchTyped(F f, const JS::Value& val, Args&&... args)
|
||||
-> decltype(f(static_cast<JSObject*>(nullptr), mozilla::Forward<Args>(args)...))
|
||||
{
|
||||
if (val.isString())
|
||||
return f(val.toString(), mozilla::Forward<Args>(args)...);
|
||||
if (val.isObject())
|
||||
return f(&val.toObject(), mozilla::Forward<Args>(args)...);
|
||||
if (val.isSymbol())
|
||||
return f(val.toSymbol(), mozilla::Forward<Args>(args)...);
|
||||
if (MOZ_UNLIKELY(val.isPrivateGCThing()))
|
||||
if (val.isString()) {
|
||||
JSString* str = val.toString();
|
||||
MOZ_ASSERT(gc::IsCellPointerValid(str));
|
||||
return f(str, mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
if (val.isObject()) {
|
||||
JSObject* obj = &val.toObject();
|
||||
MOZ_ASSERT(gc::IsCellPointerValid(obj));
|
||||
return f(obj, mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
if (val.isSymbol()) {
|
||||
JS::Symbol* sym = val.toSymbol();
|
||||
MOZ_ASSERT(gc::IsCellPointerValid(sym));
|
||||
return f(sym, mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
if (MOZ_UNLIKELY(val.isPrivateGCThing())) {
|
||||
MOZ_ASSERT(gc::IsCellPointerValid(val.toGCThing()));
|
||||
return DispatchTyped(f, val.toGCCellPtr(), mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
MOZ_ASSERT(!val.isGCThing());
|
||||
return F::defaultValue(val);
|
||||
}
|
||||
|
|
|
@ -472,30 +472,30 @@ static bool ResolvePromiseFunction(JSContext* cx, unsigned argc, Value* vp);
|
|||
static bool RejectPromiseFunction(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// ES2016, 25.4.1.3.
|
||||
static MOZ_MUST_USE bool
|
||||
static MOZ_MUST_USE MOZ_ALWAYS_INLINE bool
|
||||
CreateResolvingFunctions(JSContext* cx, HandleObject promise,
|
||||
MutableHandleObject resolveFn,
|
||||
MutableHandleObject rejectFn)
|
||||
{
|
||||
RootedAtom funName(cx, cx->names().empty);
|
||||
RootedFunction resolve(cx, NewNativeFunction(cx, ResolvePromiseFunction, 1, funName,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
|
||||
if (!resolve)
|
||||
HandlePropertyName funName = cx->names().empty;
|
||||
resolveFn.set(NewNativeFunction(cx, ResolvePromiseFunction, 1, funName,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
|
||||
if (!resolveFn)
|
||||
return false;
|
||||
|
||||
RootedFunction reject(cx, NewNativeFunction(cx, RejectPromiseFunction, 1, funName,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
|
||||
if (!reject)
|
||||
rejectFn.set(NewNativeFunction(cx, RejectPromiseFunction, 1, funName,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
|
||||
if (!rejectFn)
|
||||
return false;
|
||||
|
||||
resolve->setExtendedSlot(ResolveFunctionSlot_Promise, ObjectValue(*promise));
|
||||
resolve->setExtendedSlot(ResolveFunctionSlot_RejectFunction, ObjectValue(*reject));
|
||||
JSFunction* resolveFun = &resolveFn->as<JSFunction>();
|
||||
JSFunction* rejectFun = &rejectFn->as<JSFunction>();
|
||||
|
||||
reject->setExtendedSlot(RejectFunctionSlot_Promise, ObjectValue(*promise));
|
||||
reject->setExtendedSlot(RejectFunctionSlot_ResolveFunction, ObjectValue(*resolve));
|
||||
resolveFun->initExtendedSlot(ResolveFunctionSlot_Promise, ObjectValue(*promise));
|
||||
resolveFun->initExtendedSlot(ResolveFunctionSlot_RejectFunction, ObjectValue(*rejectFun));
|
||||
|
||||
resolveFn.set(resolve);
|
||||
rejectFn.set(reject);
|
||||
rejectFun->initExtendedSlot(RejectFunctionSlot_Promise, ObjectValue(*promise));
|
||||
rejectFun->initExtendedSlot(RejectFunctionSlot_ResolveFunction, ObjectValue(*resolveFun));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1465,12 +1465,11 @@ ClearResolutionFunctionSlots(JSFunction* resolutionFun)
|
|||
}
|
||||
|
||||
// ES2016, 25.4.3.1. steps 3-7.
|
||||
static MOZ_MUST_USE PromiseObject*
|
||||
static MOZ_MUST_USE MOZ_ALWAYS_INLINE PromiseObject*
|
||||
CreatePromiseObjectInternal(JSContext* cx, HandleObject proto /* = nullptr */,
|
||||
bool protoIsWrapped /* = false */, bool informDebugger /* = true */)
|
||||
{
|
||||
// Step 3.
|
||||
Rooted<PromiseObject*> promise(cx);
|
||||
// Enter the unwrapped proto's compartment, if that's different from
|
||||
// the current one.
|
||||
// All state stored in a Promise's fixed slots must be created in the
|
||||
|
@ -1480,12 +1479,12 @@ CreatePromiseObjectInternal(JSContext* cx, HandleObject proto /* = nullptr */,
|
|||
if (protoIsWrapped)
|
||||
ac.emplace(cx, proto);
|
||||
|
||||
promise = NewObjectWithClassProto<PromiseObject>(cx, proto);
|
||||
PromiseObject* promise = NewObjectWithClassProto<PromiseObject>(cx, proto);
|
||||
if (!promise)
|
||||
return nullptr;
|
||||
|
||||
// Step 4.
|
||||
promise->setFixedSlot(PromiseSlot_Flags, Int32Value(0));
|
||||
promise->initFixedSlot(PromiseSlot_Flags, Int32Value(0));
|
||||
|
||||
// Steps 5-6.
|
||||
// Omitted, we allocate our single list of reaction records lazily.
|
||||
|
@ -1493,20 +1492,24 @@ CreatePromiseObjectInternal(JSContext* cx, HandleObject proto /* = nullptr */,
|
|||
// Step 7.
|
||||
// Implicit, the handled flag is unset by default.
|
||||
|
||||
if (MOZ_LIKELY(!ShouldCaptureDebugInfo(cx)))
|
||||
return promise;
|
||||
|
||||
// Store an allocation stack so we can later figure out what the
|
||||
// control flow was for some unexpected results. Frightfully expensive,
|
||||
// but oh well.
|
||||
if (ShouldCaptureDebugInfo(cx)) {
|
||||
PromiseDebugInfo* debugInfo = PromiseDebugInfo::create(cx, promise);
|
||||
if (!debugInfo)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rooted<PromiseObject*> promiseRoot(cx, promise);
|
||||
|
||||
PromiseDebugInfo* debugInfo = PromiseDebugInfo::create(cx, promiseRoot);
|
||||
if (!debugInfo)
|
||||
return nullptr;
|
||||
|
||||
// Let the Debugger know about this Promise.
|
||||
if (informDebugger)
|
||||
Debugger::onNewPromise(cx, promise);
|
||||
Debugger::onNewPromise(cx, promiseRoot);
|
||||
|
||||
return promise;
|
||||
return promiseRoot;
|
||||
}
|
||||
|
||||
// ES2016, 25.4.3.1.
|
||||
|
@ -1588,7 +1591,7 @@ PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!GetPrototypeFromBuiltinConstructor(cx, args, &proto))
|
||||
return false;
|
||||
}
|
||||
Rooted<PromiseObject*> promise(cx, PromiseObject::create(cx, executor, proto, needsWrapping));
|
||||
PromiseObject* promise = PromiseObject::create(cx, executor, proto, needsWrapping);
|
||||
if (!promise)
|
||||
return false;
|
||||
|
||||
|
@ -1639,14 +1642,16 @@ PromiseObject::create(JSContext* cx, HandleObject executor, HandleObject proto /
|
|||
return nullptr;
|
||||
|
||||
// Need to wrap the resolution functions before storing them on the Promise.
|
||||
MOZ_ASSERT(promise->getFixedSlot(PromiseSlot_RejectFunction).isUndefined(),
|
||||
"Slot must be undefined so initFixedSlot can be used");
|
||||
if (needsWrapping) {
|
||||
AutoCompartment ac(cx, promise);
|
||||
RootedObject wrappedRejectFn(cx, rejectFn);
|
||||
if (!cx->compartment()->wrap(cx, &wrappedRejectFn))
|
||||
return nullptr;
|
||||
promise->setFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*wrappedRejectFn));
|
||||
promise->initFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*wrappedRejectFn));
|
||||
} else {
|
||||
promise->setFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*rejectFn));
|
||||
promise->initFixedSlot(PromiseSlot_RejectFunction, ObjectValue(*rejectFn));
|
||||
}
|
||||
|
||||
// Step 9.
|
||||
|
@ -2401,6 +2406,15 @@ NewReactionRecord(JSContext* cx, HandleObject resultPromise, HandleValue onFulfi
|
|||
HandleValue onRejected, HandleObject resolve, HandleObject reject,
|
||||
HandleObject incumbentGlobalObject)
|
||||
{
|
||||
// Either of the following conditions must be met:
|
||||
// * resultPromise is a PromiseObject
|
||||
// * resolve and reject are callable
|
||||
// except for Async Generator, there resultPromise can be nullptr.
|
||||
MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), resolve);
|
||||
MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), IsCallable(resolve));
|
||||
MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), reject);
|
||||
MOZ_ASSERT_IF(resultPromise && !resultPromise->is<PromiseObject>(), IsCallable(reject));
|
||||
|
||||
Rooted<PromiseReactionRecord*> reaction(cx, NewObjectWithClassProto<PromiseReactionRecord>(cx));
|
||||
if (!reaction)
|
||||
return nullptr;
|
||||
|
@ -3108,7 +3122,7 @@ BlockOnPromise(JSContext* cx, HandleValue promiseVal, HandleObject blockedPromis
|
|||
// rejected promises list.
|
||||
bool addToDependent = true;
|
||||
|
||||
if (C == PromiseCtor) {
|
||||
if (C == PromiseCtor && resultPromise->is<PromiseObject>()) {
|
||||
addToDependent = false;
|
||||
} else {
|
||||
// 25.4.5.3., step 4.
|
||||
|
@ -3167,12 +3181,14 @@ BlockOnPromise(JSContext* cx, HandleValue promiseVal, HandleObject blockedPromis
|
|||
return false;
|
||||
}
|
||||
|
||||
// If the object to depend on isn't a, maybe-wrapped, Promise instance,
|
||||
// we ignore it. All this does is lose some small amount of debug
|
||||
// information in scenarios that are highly unlikely to occur in useful
|
||||
// code.
|
||||
// If either the object to depend on or the object that gets blocked isn't
|
||||
// a, maybe-wrapped, Promise instance, we ignore it. All this does is lose
|
||||
// some small amount of debug information in scenarios that are highly
|
||||
// unlikely to occur in useful code.
|
||||
if (!unwrappedPromiseObj->is<PromiseObject>())
|
||||
return true;
|
||||
if (!blockedPromise_->is<PromiseObject>())
|
||||
return true;
|
||||
|
||||
Rooted<PromiseObject*> promise(cx, &unwrappedPromiseObj->as<PromiseObject>());
|
||||
return AddPromiseReaction(cx, promise, UndefinedHandleValue, UndefinedHandleValue,
|
||||
|
|
|
@ -283,7 +283,7 @@ struct InternalBarrierMethods<Value>
|
|||
DispatchTyped(PreBarrierFunctor<Value>(), v);
|
||||
}
|
||||
|
||||
static void postBarrier(Value* vp, const Value& prev, const Value& next) {
|
||||
static MOZ_ALWAYS_INLINE void postBarrier(Value* vp, const Value& prev, const Value& next) {
|
||||
MOZ_ASSERT(!CurrentThreadIsIonCompiling());
|
||||
MOZ_ASSERT(vp);
|
||||
|
||||
|
@ -318,8 +318,11 @@ struct InternalBarrierMethods<jsid>
|
|||
};
|
||||
|
||||
// Base class of all barrier types.
|
||||
//
|
||||
// This is marked non-memmovable since post barriers added by derived classes
|
||||
// can add pointers to class instances to the store buffer.
|
||||
template <typename T>
|
||||
class BarrieredBase
|
||||
class MOZ_NON_MEMMOVABLE BarrieredBase
|
||||
{
|
||||
protected:
|
||||
// BarrieredBase is not directly instantiable.
|
||||
|
@ -369,7 +372,7 @@ class WriteBarrieredBase : public BarrieredBase<T>,
|
|||
|
||||
protected:
|
||||
void pre() { InternalBarrierMethods<T>::preBarrier(this->value); }
|
||||
void post(const T& prev, const T& next) {
|
||||
MOZ_ALWAYS_INLINE void post(const T& prev, const T& next) {
|
||||
InternalBarrierMethods<T>::postBarrier(&this->value, prev, next);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2716,6 +2716,7 @@ void
|
|||
js::gc::StoreBuffer::SlotsEdge::trace(TenuringTracer& mover) const
|
||||
{
|
||||
NativeObject* obj = object();
|
||||
MOZ_ASSERT(IsCellPointerValid(obj));
|
||||
|
||||
// Beware JSObject::swap exchanging a native object for a non-native one.
|
||||
if (!obj->isNative())
|
||||
|
@ -2788,6 +2789,7 @@ js::gc::StoreBuffer::traceWholeCells(TenuringTracer& mover)
|
|||
{
|
||||
for (ArenaCellSet* cells = bufferWholeCell; cells; cells = cells->next) {
|
||||
Arena* arena = cells->arena;
|
||||
MOZ_ASSERT(IsCellPointerValid(arena));
|
||||
|
||||
MOZ_ASSERT(arena->bufferedCells() == cells);
|
||||
arena->bufferedCells() = &ArenaCellSet::Empty;
|
||||
|
@ -2817,6 +2819,7 @@ js::gc::StoreBuffer::CellPtrEdge::trace(TenuringTracer& mover) const
|
|||
if (!*edge)
|
||||
return;
|
||||
|
||||
MOZ_ASSERT(IsCellPointerValid(*edge));
|
||||
MOZ_ASSERT((*edge)->getTraceKind() == JS::TraceKind::Object);
|
||||
mover.traverse(reinterpret_cast<JSObject**>(edge));
|
||||
}
|
||||
|
|
|
@ -82,9 +82,12 @@ Zone::~Zone()
|
|||
js_delete(jitZone_.ref());
|
||||
|
||||
#ifdef DEBUG
|
||||
// Avoid assertion destroying the weak map list if the embedding leaked GC things.
|
||||
if (!rt->gc.shutdownCollectedEverything())
|
||||
// Avoid assertions failures warning that not everything has been destroyed
|
||||
// if the embedding leaked GC things.
|
||||
if (!rt->gc.shutdownCollectedEverything()) {
|
||||
gcWeakMapList().clear();
|
||||
regExps.clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -619,26 +619,71 @@ assertEq(e.call(), 1090);
|
|||
let valueToConvert = 0;
|
||||
function ffi(n) { if (n == 1337) { return valueToConvert }; return 42; }
|
||||
|
||||
// Baseline compile ffi.
|
||||
for (let i = baselineTrigger + 1; i --> 0;)
|
||||
ffi(i);
|
||||
function sum(a, b, c) {
|
||||
if (a === 1337)
|
||||
return valueToConvert;
|
||||
return (a|0) + (b|0) + (c|0) | 0;
|
||||
}
|
||||
|
||||
let imports = { a: { ffi }};
|
||||
// Baseline compile ffis.
|
||||
for (let i = baselineTrigger + 1; i --> 0;) {
|
||||
ffi(i);
|
||||
sum((i%2)?i:undefined,
|
||||
(i%3)?i:undefined,
|
||||
(i%4)?i:undefined);
|
||||
}
|
||||
|
||||
let imports = {
|
||||
a: {
|
||||
ffi,
|
||||
sum
|
||||
}
|
||||
};
|
||||
|
||||
i = wasmEvalText(`(module
|
||||
(import $ffi "a" "ffi" (param i32) (result i32))
|
||||
(func $foo (export "foo") (param i32) (result i32)
|
||||
|
||||
(import $missingOneArg "a" "sum" (param i32) (param i32) (result i32))
|
||||
(import $missingTwoArgs "a" "sum" (param i32) (result i32))
|
||||
(import $missingThreeArgs "a" "sum" (result i32))
|
||||
|
||||
(func (export "foo") (param i32) (result i32)
|
||||
get_local 0
|
||||
call $ffi)
|
||||
call $ffi
|
||||
)
|
||||
|
||||
(func (export "missThree") (result i32)
|
||||
call $missingThreeArgs
|
||||
)
|
||||
|
||||
(func (export "missTwo") (param i32) (result i32)
|
||||
get_local 0
|
||||
call $missingTwoArgs
|
||||
)
|
||||
|
||||
(func (export "missOne") (param i32) (param i32) (result i32)
|
||||
get_local 0
|
||||
get_local 1
|
||||
call $missingOneArg
|
||||
)
|
||||
)`, imports).exports;
|
||||
|
||||
// Enable the jit exit.
|
||||
// Enable the jit exit for each JS callee.
|
||||
assertEq(i.foo(0), 42);
|
||||
|
||||
// Test the jit exit.
|
||||
assertEq(i.missThree(), 0);
|
||||
assertEq(i.missTwo(42), 42);
|
||||
assertEq(i.missOne(13, 37), 50);
|
||||
|
||||
// Test the jit exit under normal conditions.
|
||||
assertEq(i.foo(0), 42);
|
||||
assertEq(i.foo(1337), 0);
|
||||
|
||||
// Test the arguments rectifier.
|
||||
assertEq(i.missThree(), 0);
|
||||
assertEq(i.missTwo(-1), -1);
|
||||
assertEq(i.missOne(23, 10), 33);
|
||||
|
||||
// Test OOL coercion.
|
||||
valueToConvert = 2**31;
|
||||
assertEq(i.foo(1337), -(2**31));
|
||||
|
@ -649,5 +694,7 @@ assertEq(e.call(), 1090);
|
|||
|
||||
valueToConvert = { toString() { throw new Error('a FFI to believe in'); } }
|
||||
assertErrorMessage(() => i.foo(1337), Error, "a FFI to believe in");
|
||||
})();
|
||||
|
||||
// Test the error path in the arguments rectifier.
|
||||
assertErrorMessage(() => i.missTwo(1337), Error, "a FFI to believe in");
|
||||
})();
|
||||
|
|
|
@ -331,9 +331,17 @@ for (let type of ['f32', 'f64']) {
|
|||
|
||||
var m = new Module(wasmTextToBinary(`(module
|
||||
(import $ffi "a" "ffi" (param i32) (result i32))
|
||||
(func $foo (export "foo") (param i32) (result i32)
|
||||
|
||||
(import $missingOneArg "a" "sumTwo" (param i32) (result i32))
|
||||
|
||||
(func (export "foo") (param i32) (result i32)
|
||||
get_local 0
|
||||
call $ffi)
|
||||
|
||||
(func (export "id") (param i32) (result i32)
|
||||
get_local 0
|
||||
call $missingOneArg
|
||||
)
|
||||
)`));
|
||||
|
||||
var valueToConvert = 0;
|
||||
|
@ -343,45 +351,71 @@ for (let type of ['f32', 'f64']) {
|
|||
return 42;
|
||||
}
|
||||
|
||||
// Baseline compile ffi.
|
||||
for (var i = 20; i --> 0;)
|
||||
ffi(i);
|
||||
function sumTwo(a, b) {
|
||||
return (a|0)+(b|0)|0;
|
||||
}
|
||||
|
||||
var imports = { a: { ffi }};
|
||||
// Baseline compile ffi.
|
||||
for (var i = 20; i --> 0;) {
|
||||
ffi(i);
|
||||
sumTwo(i-1, i+1);
|
||||
}
|
||||
|
||||
var imports = {
|
||||
a: {
|
||||
ffi,
|
||||
sumTwo
|
||||
}
|
||||
};
|
||||
|
||||
var i = new Instance(m, imports).exports;
|
||||
|
||||
// Enable the jit exit.
|
||||
assertEq(i.foo(0), 42);
|
||||
assertEq(i.id(13), 13);
|
||||
|
||||
// Test normal conditions.
|
||||
enableSingleStepProfiling();
|
||||
assertEq(i.foo(0), 42);
|
||||
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "<,1,>",
|
||||
assertEqStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>",
|
||||
// Losing stack information while the JIT func prologue sets profiler
|
||||
// virtual FP.
|
||||
"",
|
||||
// Callee time.
|
||||
"<,1,>",
|
||||
"<,2,>",
|
||||
// Losing stack information while we're exiting JIT func epilogue and
|
||||
// recovering wasm FP.
|
||||
"",
|
||||
// Back into the jit exit (frame info has been recovered).
|
||||
"<,1,>",
|
||||
"<,2,>",
|
||||
// Normal unwinding.
|
||||
"1,>", ">", ""]);
|
||||
"2,>", ">", ""]);
|
||||
|
||||
// Test rectifier frame.
|
||||
enableSingleStepProfiling();
|
||||
assertEq(i.id(100), 100);
|
||||
assertEqStacks(disableSingleStepProfiling(), ["", ">", "3,>", "<,3,>",
|
||||
// Rectifier frame time is spent here (lastProfilingFrame has not been
|
||||
// set).
|
||||
"",
|
||||
"<,3,>",
|
||||
// Rectifier frame unwinding time is spent here.
|
||||
"",
|
||||
"<,3,>",
|
||||
"3,>", ">", ""]);
|
||||
|
||||
// Test OOL coercion path.
|
||||
valueToConvert = 2**31;
|
||||
|
||||
enableSingleStepProfiling();
|
||||
assertEq(i.foo(1337), -(2**31));
|
||||
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "<,1,>", "", "<,1,>", "",
|
||||
assertEqStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>", "", "<,2,>", "",
|
||||
// Back into the jit exit (frame info has been recovered).
|
||||
// Inline conversion fails, we skip to the OOL path, call from there
|
||||
// and get back to the jit exit.
|
||||
"<,1,>",
|
||||
"<,2,>",
|
||||
// Normal unwinding.
|
||||
"1,>", ">", ""]);
|
||||
"2,>", ">", ""]);
|
||||
|
||||
disableGeckoProfiling();
|
||||
setJitCompilerOption("baseline.warmup.trigger", prevOptions["baseline.warmup.trigger"]);
|
||||
|
|
|
@ -394,11 +394,13 @@ struct BaselineStackBuilder
|
|||
BufferPointer<RectifierFrameLayout> priorFrame =
|
||||
pointerAtStackOffset<RectifierFrameLayout>(priorOffset);
|
||||
FrameType priorType = priorFrame->prevType();
|
||||
MOZ_ASSERT(priorType == JitFrame_IonJS || priorType == JitFrame_BaselineStub);
|
||||
MOZ_ASSERT(priorType == JitFrame_WasmToJSJit ||
|
||||
priorType == JitFrame_IonJS ||
|
||||
priorType == JitFrame_BaselineStub);
|
||||
|
||||
// If the frame preceding the rectifier is an IonJS frame, then once again
|
||||
// the frame pointer does not matter.
|
||||
if (priorType == JitFrame_IonJS)
|
||||
// If the frame preceding the rectifier is an IonJS or WasmToJSJit
|
||||
// entry frame, then once again the frame pointer does not matter.
|
||||
if (priorType == JitFrame_IonJS || priorType == JitFrame_WasmToJSJit)
|
||||
return nullptr;
|
||||
|
||||
// Otherwise, the frame preceding the rectifier is a BaselineStub frame.
|
||||
|
|
|
@ -280,6 +280,15 @@ JitRuntime::initialize(JSContext* cx, AutoLockForExclusiveAccess& lock)
|
|||
return false;
|
||||
}
|
||||
|
||||
// The arguments rectifier has to use the same frame layout as the function
|
||||
// frames it rectifies.
|
||||
static_assert(mozilla::IsBaseOf<JitFrameLayout, RectifierFrameLayout>::value,
|
||||
"a rectifier frame can be used with jit frame");
|
||||
static_assert(mozilla::IsBaseOf<JitFrameLayout, WasmToJSJitFrameLayout>::value,
|
||||
"wasm frames simply are jit frames");
|
||||
static_assert(sizeof(JitFrameLayout) == sizeof(WasmToJSJitFrameLayout),
|
||||
"thus a rectifier frame can be used with a wasm frame");
|
||||
|
||||
JitSpew(JitSpew_Codegen, "# Emitting sequential arguments rectifier");
|
||||
argumentsRectifier_ = generateArgumentsRectifier(cx, &argumentsRectifierReturnAddr_.writeRef());
|
||||
if (!argumentsRectifier_)
|
||||
|
|
|
@ -643,6 +643,17 @@ JSJitProfilingFrameIterator::operator++()
|
|||
moveToNextFrame(frame);
|
||||
}
|
||||
|
||||
void
|
||||
JSJitProfilingFrameIterator::moveToWasmFrame(CommonFrameLayout* frame)
|
||||
{
|
||||
// No previous js jit frame, this is a transition frame, used to
|
||||
// pass a wasm iterator the correct value of FP.
|
||||
returnAddressToFp_ = nullptr;
|
||||
fp_ = GetPreviousRawFrame<uint8_t*>(frame);
|
||||
type_ = JitFrame_WasmToJSJit;
|
||||
MOZ_ASSERT(!done());
|
||||
}
|
||||
|
||||
void
|
||||
JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
|
||||
{
|
||||
|
@ -666,6 +677,8 @@ JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
|
|||
* | ^--- Ion
|
||||
* | |
|
||||
* | ^--- Baseline Stub <---- Baseline
|
||||
* | |
|
||||
* | ^--- WasmToJSJit <--- (other wasm frames)
|
||||
* |
|
||||
* ^--- Entry Frame (From C++)
|
||||
* Exit Frame (From previous JitActivation)
|
||||
|
@ -726,6 +739,11 @@ JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
|
|||
return;
|
||||
}
|
||||
|
||||
if (rectPrevType == JitFrame_WasmToJSJit) {
|
||||
moveToWasmFrame(rectFrame);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_CRASH("Bad frame type prior to rectifier frame.");
|
||||
}
|
||||
|
||||
|
@ -742,11 +760,7 @@ JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
|
|||
}
|
||||
|
||||
if (prevType == JitFrame_WasmToJSJit) {
|
||||
// No previous js jit frame, this is a transition frame, used to pass
|
||||
// a wasm iterator the correct value of FP.
|
||||
returnAddressToFp_ = nullptr;
|
||||
fp_ = GetPreviousRawFrame<uint8_t*>(frame);
|
||||
type_ = JitFrame_WasmToJSJit;
|
||||
moveToWasmFrame(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -297,6 +297,7 @@ class JSJitProfilingFrameIterator
|
|||
bool forLastCallSite);
|
||||
void fixBaselineReturnAddress();
|
||||
|
||||
void moveToWasmFrame(CommonFrameLayout* frame);
|
||||
void moveToNextFrame(CommonFrameLayout* frame);
|
||||
|
||||
public:
|
||||
|
|
|
@ -445,11 +445,11 @@ class RectifierFrameLayout : public JitFrameLayout
|
|||
}
|
||||
};
|
||||
|
||||
class WasmFrameLayout : public JitFrameLayout
|
||||
class WasmToJSJitFrameLayout : public JitFrameLayout
|
||||
{
|
||||
public:
|
||||
static inline size_t Size() {
|
||||
return sizeof(WasmFrameLayout);
|
||||
return sizeof(WasmToJSJitFrameLayout);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1654,6 +1654,22 @@ MacroAssembler::generateBailoutTail(Register scratch, Register bailoutInfo)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::assertRectifierFrameParentType(Register frameType)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// Check the possible previous frame types here.
|
||||
Label checkOk;
|
||||
branch32(Assembler::Equal, frameType, Imm32(JitFrame_IonJS), &checkOk);
|
||||
branch32(Assembler::Equal, frameType, Imm32(JitFrame_BaselineStub), &checkOk);
|
||||
branch32(Assembler::Equal, frameType, Imm32(JitFrame_WasmToJSJit), &checkOk);
|
||||
assumeUnreachable("Unrecognized frame type preceding RectifierFrame.");
|
||||
bind(&checkOk);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::loadBaselineOrIonRaw(Register script, Register dest, Label* failure)
|
||||
{
|
||||
|
|
|
@ -1837,6 +1837,8 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
// Generates code used to complete a bailout.
|
||||
void generateBailoutTail(Register scratch, Register bailoutInfo);
|
||||
|
||||
void assertRectifierFrameParentType(Register frameType);
|
||||
|
||||
public:
|
||||
#ifndef JS_CODEGEN_ARM64
|
||||
// StackPointer manipulation functions.
|
||||
|
|
|
@ -1287,10 +1287,10 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
//
|
||||
// JitFrame_Rectifier
|
||||
//
|
||||
// The rectifier frame can be preceded by either an IonJS or a
|
||||
// BaselineStub frame.
|
||||
// The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
|
||||
// a BaselineStub frame.
|
||||
//
|
||||
// Stack layout if caller of rectifier was Ion:
|
||||
// Stack layout if caller of rectifier was Ion or WasmToJSJit:
|
||||
//
|
||||
// Ion-Descriptor
|
||||
// Ion-ReturnAddr
|
||||
|
@ -1335,10 +1335,11 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
// and |scratch2| points to Rectifier frame
|
||||
// and |scratch3| contains Rect-Descriptor.Type
|
||||
|
||||
masm.assertRectifierFrameParentType(scratch3);
|
||||
|
||||
// Check for either Ion or BaselineStub frame.
|
||||
Label handle_Rectifier_BaselineStub;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
|
||||
&handle_Rectifier_BaselineStub);
|
||||
Label notIonFrame;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), ¬IonFrame);
|
||||
|
||||
// Handle Rectifier <- IonJS
|
||||
// scratch3 := RectFrame[ReturnAddr]
|
||||
|
@ -1351,16 +1352,13 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
masm.storePtr(scratch3, lastProfilingFrame);
|
||||
masm.ret();
|
||||
|
||||
masm.bind(¬IonFrame);
|
||||
|
||||
// Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
|
||||
// just an entry, jump there if we see it.
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
|
||||
|
||||
// Handle Rectifier <- BaselineStub <- BaselineJS
|
||||
masm.bind(&handle_Rectifier_BaselineStub);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
Label checkOk;
|
||||
masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
|
||||
masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
|
||||
masm.bind(&checkOk);
|
||||
}
|
||||
#endif
|
||||
masm.ma_add(scratch2, scratch1, scratch3);
|
||||
Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
|
||||
BaselineStubFrameLayout::offsetOfReturnAddress());
|
||||
|
@ -1424,7 +1422,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
}
|
||||
|
||||
//
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmJSToJit
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmToJSJit
|
||||
//
|
||||
// If at an entry frame, store null into both fields.
|
||||
// A fast-path wasm->jit transition frame is an entry frame from the point
|
||||
|
|
|
@ -1128,10 +1128,11 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
// and |scratch2| points to Rectifier frame
|
||||
// and |scratch3| contains Rect-Descriptor.Type
|
||||
|
||||
masm.assertRectifierFrameParentType(scratch3);
|
||||
|
||||
// Check for either Ion or BaselineStub frame.
|
||||
Label handle_Rectifier_BaselineStub;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
|
||||
&handle_Rectifier_BaselineStub);
|
||||
Label notIonFrame;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), ¬IonFrame);
|
||||
|
||||
// Handle Rectifier <- IonJS
|
||||
// scratch3 := RectFrame[ReturnAddr]
|
||||
|
@ -1144,16 +1145,13 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
masm.storePtr(scratch3, lastProfilingFrame);
|
||||
masm.ret();
|
||||
|
||||
masm.bind(¬IonFrame);
|
||||
|
||||
// Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
|
||||
// just an entry, jump there if we see it.
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
|
||||
|
||||
// Handle Rectifier <- BaselineStub <- BaselineJS
|
||||
masm.bind(&handle_Rectifier_BaselineStub);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
Label checkOk;
|
||||
masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
|
||||
masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
|
||||
masm.bind(&checkOk);
|
||||
}
|
||||
#endif
|
||||
masm.addPtr(scratch2, scratch1, scratch3);
|
||||
Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
|
||||
BaselineStubFrameLayout::offsetOfReturnAddress());
|
||||
|
@ -1218,7 +1216,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
}
|
||||
|
||||
//
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmJSToJit
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmToJSJit
|
||||
//
|
||||
// If at an entry frame, store null into both fields.
|
||||
// A fast-path wasm->jit transition frame is an entry frame from the point
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#define HWCAP_MIPS (1 << 28)
|
||||
#define HWCAP_LOONGSON (1 << 27)
|
||||
#define HWCAP_R2 (1 << 26)
|
||||
#define HWCAP_FPU (1 << 0)
|
||||
|
||||
namespace js {
|
||||
|
@ -25,6 +26,7 @@ get_mips_flags()
|
|||
|
||||
#if defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
|
||||
flags |= HWCAP_FPU;
|
||||
flags |= HWCAP_R2;
|
||||
#else
|
||||
# ifdef __linux__
|
||||
FILE* fp = fopen("/proc/cpuinfo", "r");
|
||||
|
@ -39,6 +41,8 @@ get_mips_flags()
|
|||
flags |= HWCAP_FPU;
|
||||
if (strstr(buf, "Loongson"))
|
||||
flags |= HWCAP_LOONGSON;
|
||||
if (strstr(buf, "mips32r2") || strstr(buf, "mips64r2"))
|
||||
flags |= HWCAP_R2;
|
||||
# endif
|
||||
#endif // JS_SIMULATOR_MIPS32 || JS_SIMULATOR_MIPS64
|
||||
return flags;
|
||||
|
@ -54,11 +58,17 @@ static bool check_loongson()
|
|||
return mips_private::Flags & HWCAP_LOONGSON;
|
||||
}
|
||||
|
||||
static bool check_r2()
|
||||
{
|
||||
return mips_private::Flags & HWCAP_R2;
|
||||
}
|
||||
|
||||
namespace mips_private {
|
||||
// Cache a local copy so we only have to read /proc/cpuinfo once.
|
||||
uint32_t Flags = get_mips_flags();
|
||||
bool hasFPU = check_fpu();;
|
||||
bool isLoongson = check_loongson();
|
||||
bool hasR2 = check_r2();
|
||||
}
|
||||
|
||||
Registers::Code
|
||||
|
|
|
@ -314,11 +314,13 @@ namespace mips_private {
|
|||
extern uint32_t Flags;
|
||||
extern bool hasFPU;
|
||||
extern bool isLoongson;
|
||||
extern bool hasR2;
|
||||
}
|
||||
|
||||
inline uint32_t GetMIPSFlags() { return mips_private::Flags; }
|
||||
inline bool hasFPU() { return mips_private::hasFPU; }
|
||||
inline bool isLoongson() { return mips_private::isLoongson; }
|
||||
inline bool hasR2() { return mips_private::hasR2; }
|
||||
|
||||
// MIPS doesn't have double registers that can NOT be treated as float32.
|
||||
inline bool
|
||||
|
|
|
@ -714,6 +714,7 @@ AssemblerMIPSShared::as_rotr(Register rd, Register rt, uint16_t sa)
|
|||
{
|
||||
MOZ_ASSERT(sa < 32);
|
||||
spew("rotr %3s,%3s, 0x%x", rd.name(), rt.name(), sa);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_srl).encode());
|
||||
}
|
||||
|
||||
|
@ -722,6 +723,7 @@ AssemblerMIPSShared::as_drotr(Register rd, Register rt, uint16_t sa)
|
|||
{
|
||||
MOZ_ASSERT(sa < 32);
|
||||
spew("drotr %3s,%3s, 0x%x", rd.name(), rt.name(), sa);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_dsrl).encode());
|
||||
}
|
||||
|
||||
|
@ -730,6 +732,7 @@ AssemblerMIPSShared::as_drotr32(Register rd, Register rt, uint16_t sa)
|
|||
{
|
||||
MOZ_ASSERT(31 < sa && sa < 64);
|
||||
spew("drotr32%3s,%3s, 0x%x", rd.name(), rt.name(), sa - 32);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special, rs_one, rt, rd, sa - 32, ff_dsrl32).encode());
|
||||
}
|
||||
|
||||
|
@ -737,6 +740,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_rotrv(Register rd, Register rt, Register rs)
|
||||
{
|
||||
spew("rotrv %3s,%3s,%3s", rd.name(), rt.name(), rs.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_srlv).encode());
|
||||
}
|
||||
|
||||
|
@ -744,6 +748,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_drotrv(Register rd, Register rt, Register rs)
|
||||
{
|
||||
spew("drotrv %3s,%3s,%3s", rd.name(), rt.name(), rs.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_dsrlv).encode());
|
||||
}
|
||||
|
||||
|
@ -1076,6 +1081,7 @@ AssemblerMIPSShared::as_ins(Register rt, Register rs, uint16_t pos, uint16_t siz
|
|||
Register rd;
|
||||
rd = Register::FromCode(pos + size - 1);
|
||||
spew("ins %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ins).encode());
|
||||
}
|
||||
|
||||
|
@ -1086,6 +1092,7 @@ AssemblerMIPSShared::as_dins(Register rt, Register rs, uint16_t pos, uint16_t si
|
|||
Register rd;
|
||||
rd = Register::FromCode(pos + size - 1);
|
||||
spew("dins %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dins).encode());
|
||||
}
|
||||
|
||||
|
@ -1096,6 +1103,7 @@ AssemblerMIPSShared::as_dinsm(Register rt, Register rs, uint16_t pos, uint16_t s
|
|||
Register rd;
|
||||
rd = Register::FromCode(pos + size - 1 - 32);
|
||||
spew("dinsm %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dinsm).encode());
|
||||
}
|
||||
|
||||
|
@ -1106,6 +1114,7 @@ AssemblerMIPSShared::as_dinsu(Register rt, Register rs, uint16_t pos, uint16_t s
|
|||
Register rd;
|
||||
rd = Register::FromCode(pos + size - 1 - 32);
|
||||
spew("dinsu %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dinsu).encode());
|
||||
}
|
||||
|
||||
|
@ -1116,6 +1125,7 @@ AssemblerMIPSShared::as_ext(Register rt, Register rs, uint16_t pos, uint16_t siz
|
|||
Register rd;
|
||||
rd = Register::FromCode(size - 1);
|
||||
spew("ext %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ext).encode());
|
||||
}
|
||||
|
||||
|
@ -1124,6 +1134,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_seb(Register rd, Register rt)
|
||||
{
|
||||
spew("seb %3s,%3s", rd.name(), rt.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, zero, rt, rd, 16, ff_bshfl).encode());
|
||||
}
|
||||
|
||||
|
@ -1131,6 +1142,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_seh(Register rd, Register rt)
|
||||
{
|
||||
spew("seh %3s,%3s", rd.name(), rt.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, zero, rt, rd, 24, ff_bshfl).encode());
|
||||
}
|
||||
|
||||
|
@ -1141,6 +1153,7 @@ AssemblerMIPSShared::as_dext(Register rt, Register rs, uint16_t pos, uint16_t si
|
|||
Register rd;
|
||||
rd = Register::FromCode(size - 1);
|
||||
spew("dext %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dext).encode());
|
||||
}
|
||||
|
||||
|
@ -1151,7 +1164,8 @@ AssemblerMIPSShared::as_dextm(Register rt, Register rs, uint16_t pos, uint16_t s
|
|||
Register rd;
|
||||
rd = Register::FromCode(size - 1 - 32);
|
||||
spew("dextm %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dextm).encode());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dextm).encode());
|
||||
}
|
||||
|
||||
BufferOffset
|
||||
|
@ -1161,6 +1175,7 @@ AssemblerMIPSShared::as_dextu(Register rt, Register rs, uint16_t pos, uint16_t s
|
|||
Register rd;
|
||||
rd = Register::FromCode(size - 1);
|
||||
spew("dextu %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dextu).encode());
|
||||
}
|
||||
|
||||
|
@ -1412,6 +1427,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_truncls(FloatRegister fd, FloatRegister fs)
|
||||
{
|
||||
spew("trunc.l.s%3s,%3s", fd.name(), fs.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_cop1, rs_s, zero, fs, fd, ff_trunc_l_fmt).encode());
|
||||
}
|
||||
|
||||
|
@ -1447,6 +1463,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_truncld(FloatRegister fd, FloatRegister fs)
|
||||
{
|
||||
spew("trunc.l.d%3s,%3s", fd.name(), fs.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_cop1, rs_d, zero, fs, fd, ff_trunc_l_fmt).encode());
|
||||
}
|
||||
|
||||
|
@ -1454,6 +1471,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_cvtdl(FloatRegister fd, FloatRegister fs)
|
||||
{
|
||||
spew("cvt.d.l%3s,%3s", fd.name(), fs.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_cop1, rs_l, zero, fs, fd, ff_cvt_d_fmt).encode());
|
||||
}
|
||||
|
||||
|
@ -1482,6 +1500,7 @@ BufferOffset
|
|||
AssemblerMIPSShared::as_cvtsl(FloatRegister fd, FloatRegister fs)
|
||||
{
|
||||
spew("cvt.s.l%3s,%3s", fd.name(), fs.name());
|
||||
MOZ_ASSERT(hasR2());
|
||||
return writeInst(InstReg(op_cop1, rs_l, zero, fs, fd, ff_cvt_s_fmt).encode());
|
||||
}
|
||||
|
||||
|
|
|
@ -1580,7 +1580,7 @@ CodeGeneratorMIPSShared::visitCopySignF(LCopySignF* ins)
|
|||
masm.moveFromFloat32(rhs, rhsi);
|
||||
|
||||
// Combine.
|
||||
masm.as_ins(rhsi, lhsi, 0, 31);
|
||||
masm.ma_ins(rhsi, lhsi, 0, 31);
|
||||
|
||||
masm.moveToFloat32(rhsi, output);
|
||||
}
|
||||
|
@ -1600,7 +1600,7 @@ CodeGeneratorMIPSShared::visitCopySignD(LCopySignD* ins)
|
|||
masm.moveFromDoubleHi(rhs, rhsi);
|
||||
|
||||
// Combine.
|
||||
masm.as_ins(rhsi, lhsi, 0, 31);
|
||||
masm.ma_ins(rhsi, lhsi, 0, 31);
|
||||
|
||||
masm.moveToDoubleHi(rhsi, output);
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest)
|
|||
void
|
||||
MacroAssembler::move8SignExtend(Register src, Register dest)
|
||||
{
|
||||
as_seb(dest, src);
|
||||
ma_seb(dest, src);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::move16SignExtend(Register src, Register dest)
|
||||
{
|
||||
as_seh(dest, src);
|
||||
ma_seh(dest, src);
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
|
|
|
@ -71,13 +71,27 @@ MacroAssemblerMIPSShared::ma_sra(Register rd, Register rt, Imm32 shift)
|
|||
void
|
||||
MacroAssemblerMIPSShared::ma_ror(Register rd, Register rt, Imm32 shift)
|
||||
{
|
||||
as_rotr(rd, rt, shift.value % 32);
|
||||
if (hasR2()) {
|
||||
as_rotr(rd, rt, shift.value % 32);
|
||||
} else {
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
as_srl(scratch, rt, shift.value % 32);
|
||||
as_sll(rd, rt, (32 - (shift.value % 32)) % 32);
|
||||
as_or(rd, rd, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSShared::ma_rol(Register rd, Register rt, Imm32 shift)
|
||||
{
|
||||
as_rotr(rd, rt, 32 - (shift.value % 32));
|
||||
if (hasR2()) {
|
||||
as_rotr(rd, rt, (32 - (shift.value % 32)) % 32);
|
||||
} else {
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
as_srl(scratch, rt, (32 - (shift.value % 32)) % 32);
|
||||
as_sll(rd, rt, shift.value % 32);
|
||||
as_or(rd, rd, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -101,14 +115,29 @@ MacroAssemblerMIPSShared::ma_sra(Register rd, Register rt, Register shift)
|
|||
void
|
||||
MacroAssemblerMIPSShared::ma_ror(Register rd, Register rt, Register shift)
|
||||
{
|
||||
as_rotrv(rd, rt, shift);
|
||||
if (hasR2()) {
|
||||
as_rotrv(rd, rt, shift);
|
||||
} else {
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
ma_negu(scratch, shift);
|
||||
as_sllv(scratch, rt, scratch);
|
||||
as_srlv(rd, rt, shift);
|
||||
as_or(rd, rd, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSShared::ma_rol(Register rd, Register rt, Register shift)
|
||||
{
|
||||
ma_negu(ScratchRegister, shift);
|
||||
as_rotrv(rd, rt, ScratchRegister);
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
ma_negu(scratch, shift);
|
||||
if (hasR2()) {
|
||||
as_rotrv(rd, rt, scratch);
|
||||
} else {
|
||||
as_srlv(rd, rt, scratch);
|
||||
as_sllv(scratch, rt, shift);
|
||||
as_or(rd, rd, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -123,6 +152,69 @@ MacroAssemblerMIPSShared::ma_not(Register rd, Register rs)
|
|||
as_nor(rd, rs, zero);
|
||||
}
|
||||
|
||||
// Bit extract/insert
|
||||
void
|
||||
MacroAssemblerMIPSShared::ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size) {
|
||||
MOZ_ASSERT(pos < 32);
|
||||
MOZ_ASSERT(pos + size < 33);
|
||||
|
||||
if (hasR2()) {
|
||||
as_ext(rt, rs, pos, size);
|
||||
} else {
|
||||
int shift_left = 32 - (pos + size);
|
||||
as_sll(rt, rs, shift_left);
|
||||
int shift_right = 32 - size;
|
||||
if (shift_right > 0) {
|
||||
as_srl(rt, rt, shift_right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSShared::ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size) {
|
||||
MOZ_ASSERT(pos < 32);
|
||||
MOZ_ASSERT(pos + size <= 32);
|
||||
MOZ_ASSERT(size != 0);
|
||||
|
||||
if (hasR2()) {
|
||||
as_ins(rt, rs, pos, size);
|
||||
} else {
|
||||
ScratchRegisterScope scratch(asMasm());
|
||||
SecondScratchRegisterScope scratch2(asMasm());
|
||||
ma_subu(scratch, zero, Imm32(1));
|
||||
as_srl(scratch, scratch, 32 - size);
|
||||
as_and(scratch2, rs, scratch);
|
||||
as_sll(scratch2, scratch2, pos);
|
||||
as_sll(scratch, scratch, pos);
|
||||
as_nor(scratch, scratch, zero);
|
||||
as_and(scratch, rt, scratch);
|
||||
as_or(rt, scratch2, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
// Sign extend
|
||||
void
|
||||
MacroAssemblerMIPSShared::ma_seb(Register rd, Register rt)
|
||||
{
|
||||
if (hasR2()) {
|
||||
as_seb(rd, rt);
|
||||
} else {
|
||||
as_sll(rd, rt, 24);
|
||||
as_sra(rd, rd, 24);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSShared::ma_seh(Register rd, Register rt)
|
||||
{
|
||||
if (hasR2()) {
|
||||
as_seh(rd, rt);
|
||||
} else {
|
||||
as_sll(rd, rt, 16);
|
||||
as_sra(rd, rd, 16);
|
||||
}
|
||||
}
|
||||
|
||||
// And.
|
||||
void
|
||||
MacroAssemblerMIPSShared::ma_and(Register rd, Register rs)
|
||||
|
@ -484,7 +576,7 @@ MacroAssemblerMIPSShared::ma_load_unaligned(Register dest, const BaseIndex& src,
|
|||
as_lbu(temp, base, hiOffset);
|
||||
else
|
||||
as_lb(temp, base, hiOffset);
|
||||
as_ins(dest, temp, 8, 24);
|
||||
ma_ins(dest, temp, 8, 24);
|
||||
break;
|
||||
case SizeWord:
|
||||
as_lwl(dest, base, hiOffset);
|
||||
|
@ -627,7 +719,7 @@ MacroAssemblerMIPSShared::ma_store_unaligned(Register data, const BaseIndex& des
|
|||
switch (size) {
|
||||
case SizeHalfWord:
|
||||
as_sb(data, base, lowOffset);
|
||||
as_ext(temp, data, 8, 8);
|
||||
ma_ext(temp, data, 8, 8);
|
||||
as_sb(temp, base, hiOffset);
|
||||
break;
|
||||
case SizeWord:
|
||||
|
@ -1243,10 +1335,10 @@ MacroAssemblerMIPSShared::atomicFetchOpMIPSr2(int nbytes, bool signExtend, Atomi
|
|||
if (signExtend) {
|
||||
switch (nbytes) {
|
||||
case 1:
|
||||
as_seb(output, output);
|
||||
ma_seb(output, output);
|
||||
break;
|
||||
case 2:
|
||||
as_seh(output, output);
|
||||
ma_seh(output, output);
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
|
@ -1418,10 +1510,10 @@ MacroAssemblerMIPSShared::compareExchangeMIPSr2(int nbytes, bool signExtend, con
|
|||
if (signExtend) {
|
||||
switch (nbytes) {
|
||||
case 1:
|
||||
as_seb(output, output);
|
||||
ma_seb(output, output);
|
||||
break;
|
||||
case 2:
|
||||
as_seh(output, output);
|
||||
ma_seh(output, output);
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
|
@ -1769,7 +1861,7 @@ MacroAssembler::wasmTruncateDoubleToInt32(FloatRegister input, Register output,
|
|||
as_truncwd(ScratchFloat32Reg, input);
|
||||
as_cfc1(ScratchRegister, Assembler::FCSR);
|
||||
moveFromFloat32(ScratchFloat32Reg, output);
|
||||
as_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
|
||||
}
|
||||
|
||||
|
@ -1780,7 +1872,7 @@ MacroAssembler::wasmTruncateFloat32ToInt32(FloatRegister input, Register output,
|
|||
as_truncws(ScratchFloat32Reg, input);
|
||||
as_cfc1(ScratchRegister, Assembler::FCSR);
|
||||
moveFromFloat32(ScratchFloat32Reg, output);
|
||||
as_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,14 @@ class MacroAssemblerMIPSShared : public Assembler
|
|||
|
||||
void ma_not(Register rd, Register rs);
|
||||
|
||||
// Bit extract/insert
|
||||
void ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size);
|
||||
void ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size);
|
||||
|
||||
// Sign extend
|
||||
void ma_seb(Register rd, Register rt);
|
||||
void ma_seh(Register rd, Register rt);
|
||||
|
||||
// and
|
||||
void ma_and(Register rd, Register rs);
|
||||
void ma_and(Register rd, Imm32 imm);
|
||||
|
|
|
@ -427,21 +427,21 @@ JitRuntime::generateArgumentsRectifier(JSContext* cx, void** returnAddrOut)
|
|||
MacroAssembler masm(cx);
|
||||
masm.pushReturnAddress();
|
||||
|
||||
// ArgumentsRectifierReg contains the |nargs| pushed onto the current
|
||||
// frame. Including |this|, there are (|nargs| + 1) arguments to copy.
|
||||
MOZ_ASSERT(ArgumentsRectifierReg == s3);
|
||||
|
||||
Register numActArgsReg = t6;
|
||||
Register calleeTokenReg = t7;
|
||||
Register numArgsReg = t5;
|
||||
|
||||
// Copy number of actual arguments into numActArgsReg
|
||||
// Load the number of actual arguments into numActArgsReg
|
||||
masm.loadPtr(Address(StackPointer, RectifierFrameLayout::offsetOfNumActualArgs()),
|
||||
numActArgsReg);
|
||||
|
||||
// Load the number of |undefined|s to push into t1.
|
||||
masm.loadPtr(Address(StackPointer, RectifierFrameLayout::offsetOfCalleeToken()),
|
||||
calleeTokenReg);
|
||||
|
||||
// Copy the number of actual arguments into s3.
|
||||
masm.mov(numActArgsReg, s3);
|
||||
|
||||
masm.mov(calleeTokenReg, numArgsReg);
|
||||
masm.andPtr(Imm32(CalleeTokenMask), numArgsReg);
|
||||
masm.load16ZeroExtend(Address(numArgsReg, JSFunction::offsetOfNargs()), numArgsReg);
|
||||
|
@ -1266,10 +1266,10 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
//
|
||||
// JitFrame_Rectifier
|
||||
//
|
||||
// The rectifier frame can be preceded by either an IonJS or a
|
||||
// BaselineStub frame.
|
||||
// The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
|
||||
// a BaselineStub frame.
|
||||
//
|
||||
// Stack layout if caller of rectifier was Ion:
|
||||
// Stack layout if caller of rectifier was Ion or WasmToJSJit:
|
||||
//
|
||||
// Ion-Descriptor
|
||||
// Ion-ReturnAddr
|
||||
|
@ -1314,10 +1314,11 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
// and |scratch2| points to Rectifier frame
|
||||
// and |scratch3| contains Rect-Descriptor.Type
|
||||
|
||||
masm.assertRectifierFrameParentType(scratch3);
|
||||
|
||||
// Check for either Ion or BaselineStub frame.
|
||||
Label handle_Rectifier_BaselineStub;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
|
||||
&handle_Rectifier_BaselineStub);
|
||||
Label notIonFrame;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), ¬IonFrame);
|
||||
|
||||
// Handle Rectifier <- IonJS
|
||||
// scratch3 := RectFrame[ReturnAddr]
|
||||
|
@ -1330,16 +1331,13 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
masm.storePtr(scratch3, lastProfilingFrame);
|
||||
masm.ret();
|
||||
|
||||
masm.bind(¬IonFrame);
|
||||
|
||||
// Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
|
||||
// just an entry, jump there if we see it.
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
|
||||
|
||||
// Handle Rectifier <- BaselineStub <- BaselineJS
|
||||
masm.bind(&handle_Rectifier_BaselineStub);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
Label checkOk;
|
||||
masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
|
||||
masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
|
||||
masm.bind(&checkOk);
|
||||
}
|
||||
#endif
|
||||
masm.as_addu(scratch3, scratch2, scratch1);
|
||||
Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
|
||||
BaselineStubFrameLayout::offsetOfReturnAddress());
|
||||
|
@ -1403,7 +1401,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
}
|
||||
|
||||
//
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmJSToJit
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmToJSJit
|
||||
//
|
||||
// If at an entry frame, store null into both fields.
|
||||
// A fast-path wasm->jit transition frame is an entry frame from the point
|
||||
|
|
|
@ -683,7 +683,7 @@ CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
|
|||
masm.moveFromDouble(ScratchDoubleReg, output);
|
||||
masm.as_cfc1(ScratchRegister, Assembler::FCSR);
|
||||
// extract invalid operation flag (bit 6) from FCSR
|
||||
masm.as_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
|
||||
masm.ma_or(SecondScratchReg, ScratchRegister);
|
||||
masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
|
||||
|
@ -703,7 +703,7 @@ CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
|
|||
// Check that the result is in the uint64_t range.
|
||||
masm.moveFromDouble(ScratchDoubleReg, output);
|
||||
masm.as_cfc1(ScratchRegister, Assembler::FCSR);
|
||||
masm.as_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
|
||||
masm.ma_or(SecondScratchReg, ScratchRegister);
|
||||
masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
|
||||
|
@ -724,7 +724,7 @@ CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
|
|||
|
||||
// Check that the result is in the int64_t range.
|
||||
masm.as_cfc1(output, Assembler::FCSR);
|
||||
masm.as_ext(output, output, 6, 1);
|
||||
masm.ma_ext(output, output, 6, 1);
|
||||
masm.ma_b(output, Imm32(0), ool->entry(), Assembler::NotEqual);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
|
|
|
@ -2578,7 +2578,7 @@ MacroAssembler::wasmTruncateDoubleToUInt32(FloatRegister input, Register output,
|
|||
as_truncld(ScratchDoubleReg, input);
|
||||
moveFromDoubleHi(ScratchDoubleReg, output);
|
||||
as_cfc1(ScratchRegister, Assembler::FCSR);
|
||||
as_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_or(ScratchRegister, output);
|
||||
moveFromFloat32(ScratchDoubleReg, output);
|
||||
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
|
||||
|
@ -2592,7 +2592,7 @@ MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input, Register output
|
|||
as_truncls(ScratchDoubleReg, input);
|
||||
moveFromDoubleHi(ScratchDoubleReg, output);
|
||||
as_cfc1(ScratchRegister, Assembler::FCSR);
|
||||
as_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
|
||||
ma_or(ScratchRegister, output);
|
||||
moveFromFloat32(ScratchDoubleReg, output);
|
||||
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
|
||||
|
|
|
@ -428,14 +428,10 @@ JitRuntime::generateArgumentsRectifier(JSContext* cx, void** returnAddrOut)
|
|||
masm.pushReturnAddress();
|
||||
// Caller:
|
||||
// [arg2] [arg1] [this] [[argc] [callee] [descr] [raddr]] <- sp
|
||||
// '--- s3 ---'
|
||||
|
||||
// ArgumentsRectifierReg contains the |nargs| pushed onto the current
|
||||
// frame. Including |this|, there are (|nargs| + 1) arguments to copy.
|
||||
MOZ_ASSERT(ArgumentsRectifierReg == s3);
|
||||
|
||||
// Add |this|, in the counter of known arguments.
|
||||
masm.addPtr(Imm32(1), ArgumentsRectifierReg);
|
||||
masm.loadPtr(Address(StackPointer, RectifierFrameLayout::offsetOfNumActualArgs()), s3);
|
||||
masm.addPtr(Imm32(1), s3);
|
||||
|
||||
Register numActArgsReg = a6;
|
||||
Register calleeTokenReg = a7;
|
||||
|
@ -1211,10 +1207,10 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
//
|
||||
// JitFrame_Rectifier
|
||||
//
|
||||
// The rectifier frame can be preceded by either an IonJS or a
|
||||
// BaselineStub frame.
|
||||
// The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
|
||||
// a BaselineStub frame.
|
||||
//
|
||||
// Stack layout if caller of rectifier was Ion:
|
||||
// Stack layout if caller of rectifier was Ion or WasmToJSJit:
|
||||
//
|
||||
// Ion-Descriptor
|
||||
// Ion-ReturnAddr
|
||||
|
@ -1259,10 +1255,11 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
// and |scratch2| points to Rectifier frame
|
||||
// and |scratch3| contains Rect-Descriptor.Type
|
||||
|
||||
masm.assertRectifierFrameParentType(scratch3);
|
||||
|
||||
// Check for either Ion or BaselineStub frame.
|
||||
Label handle_Rectifier_BaselineStub;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
|
||||
&handle_Rectifier_BaselineStub);
|
||||
Label notIonFrame;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), ¬IonFrame);
|
||||
|
||||
// Handle Rectifier <- IonJS
|
||||
// scratch3 := RectFrame[ReturnAddr]
|
||||
|
@ -1275,16 +1272,13 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
masm.storePtr(scratch3, lastProfilingFrame);
|
||||
masm.ret();
|
||||
|
||||
masm.bind(¬IonFrame);
|
||||
|
||||
// Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
|
||||
// just an entry, jump there if we see it.
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
|
||||
|
||||
// Handle Rectifier <- BaselineStub <- BaselineJS
|
||||
masm.bind(&handle_Rectifier_BaselineStub);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
Label checkOk;
|
||||
masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
|
||||
masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
|
||||
masm.bind(&checkOk);
|
||||
}
|
||||
#endif
|
||||
masm.as_daddu(scratch3, scratch2, scratch1);
|
||||
Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
|
||||
BaselineStubFrameLayout::offsetOfReturnAddress());
|
||||
|
@ -1348,7 +1342,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
}
|
||||
|
||||
//
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmJSToJit
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmToJSJit
|
||||
//
|
||||
// If at an entry frame, store null into both fields.
|
||||
// A fast-path wasm->jit transition frame is an entry frame from the point
|
||||
|
|
|
@ -1180,10 +1180,10 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
//
|
||||
// JitFrame_Rectifier
|
||||
//
|
||||
// The rectifier frame can be preceded by either an IonJS or a
|
||||
// BaselineStub frame.
|
||||
// The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
|
||||
// a BaselineStub frame.
|
||||
//
|
||||
// Stack layout if caller of rectifier was Ion:
|
||||
// Stack layout if caller of rectifier was Ion or WasmToJSJit:
|
||||
//
|
||||
// Ion-Descriptor
|
||||
// Ion-ReturnAddr
|
||||
|
@ -1228,10 +1228,11 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
// and |scratch2| points to Rectifier frame
|
||||
// and |scratch3| contains Rect-Descriptor.Type
|
||||
|
||||
// Check for either Ion or BaselineStub frame.
|
||||
Label handle_Rectifier_BaselineStub;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
|
||||
&handle_Rectifier_BaselineStub);
|
||||
masm.assertRectifierFrameParentType(scratch3);
|
||||
|
||||
// Check for either Ion or something else frame.
|
||||
Label notIonFrame;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), ¬IonFrame);
|
||||
|
||||
// Handle Rectifier <- IonJS
|
||||
// scratch3 := RectFrame[ReturnAddr]
|
||||
|
@ -1243,16 +1244,13 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
masm.storePtr(scratch3, lastProfilingFrame);
|
||||
masm.ret();
|
||||
|
||||
masm.bind(¬IonFrame);
|
||||
|
||||
// Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
|
||||
// just an entry, jump there if we see it.
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
|
||||
|
||||
// Handle Rectifier <- BaselineStub <- BaselineJS
|
||||
masm.bind(&handle_Rectifier_BaselineStub);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
Label checkOk;
|
||||
masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
|
||||
masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
|
||||
masm.bind(&checkOk);
|
||||
}
|
||||
#endif
|
||||
BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
|
||||
RectifierFrameLayout::Size() +
|
||||
BaselineStubFrameLayout::offsetOfReturnAddress());
|
||||
|
@ -1314,7 +1312,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
}
|
||||
|
||||
//
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmJSToJit
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmToJSJit
|
||||
//
|
||||
// If at an entry frame, store null into both fields.
|
||||
// A fast-path wasm->jit transition frame is an entry frame from the point
|
||||
|
|
|
@ -1214,10 +1214,10 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
//
|
||||
// JitFrame_Rectifier
|
||||
//
|
||||
// The rectifier frame can be preceded by either an IonJS or a
|
||||
// BaselineStub frame.
|
||||
// The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
|
||||
// a BaselineStub frame.
|
||||
//
|
||||
// Stack layout if caller of rectifier was Ion:
|
||||
// Stack layout if caller of rectifier was Ion or WasmToJSJit:
|
||||
//
|
||||
// Ion-Descriptor
|
||||
// Ion-ReturnAddr
|
||||
|
@ -1262,10 +1262,11 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
// and |scratch2| points to Rectifier frame
|
||||
// and |scratch3| contains Rect-Descriptor.Type
|
||||
|
||||
masm.assertRectifierFrameParentType(scratch3);
|
||||
|
||||
// Check for either Ion or BaselineStub frame.
|
||||
Label handle_Rectifier_BaselineStub;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS),
|
||||
&handle_Rectifier_BaselineStub);
|
||||
Label notIonFrame;
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_IonJS), ¬IonFrame);
|
||||
|
||||
// Handle Rectifier <- IonJS
|
||||
// scratch3 := RectFrame[ReturnAddr]
|
||||
|
@ -1277,16 +1278,13 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
masm.storePtr(scratch3, lastProfilingFrame);
|
||||
masm.ret();
|
||||
|
||||
masm.bind(¬IonFrame);
|
||||
|
||||
// Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
|
||||
// just an entry, jump there if we see it.
|
||||
masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
|
||||
|
||||
// Handle Rectifier <- BaselineStub <- BaselineJS
|
||||
masm.bind(&handle_Rectifier_BaselineStub);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
Label checkOk;
|
||||
masm.branch32(Assembler::Equal, scratch3, Imm32(JitFrame_BaselineStub), &checkOk);
|
||||
masm.assumeUnreachable("Unrecognized frame preceding baselineStub.");
|
||||
masm.bind(&checkOk);
|
||||
}
|
||||
#endif
|
||||
BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
|
||||
RectifierFrameLayout::Size() +
|
||||
BaselineStubFrameLayout::offsetOfReturnAddress());
|
||||
|
@ -1348,7 +1346,7 @@ JitRuntime::generateProfilerExitFrameTailStub(JSContext* cx)
|
|||
}
|
||||
|
||||
//
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmJSToJit
|
||||
// JitFrame_CppToJSJit / JitFrame_WasmToJSJit
|
||||
//
|
||||
// If at an entry frame, store null into both fields.
|
||||
// A fast-path wasm->jit transition frame is an entry frame from the point
|
||||
|
|
|
@ -7525,19 +7525,6 @@ UnhideScriptedCaller(JSContext* cx)
|
|||
|
||||
} /* namespace JS */
|
||||
|
||||
AutoGCRooter::AutoGCRooter(JSContext* cx, ptrdiff_t tag)
|
||||
: AutoGCRooter(JS::RootingContext::get(cx), tag)
|
||||
{}
|
||||
|
||||
AutoGCRooter::AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag)
|
||||
: down(cx->autoGCRooters_),
|
||||
tag_(tag),
|
||||
stackTop(&cx->autoGCRooters_)
|
||||
{
|
||||
MOZ_ASSERT(this != *stackTop);
|
||||
*stackTop = this;
|
||||
}
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
JS_PUBLIC_API(void)
|
||||
JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value)
|
||||
|
|
|
@ -2036,28 +2036,6 @@ JSFunction::needsNamedLambdaEnvironment() const
|
|||
return scope->hasEnvironment();
|
||||
}
|
||||
|
||||
JSFunction*
|
||||
js::NewNativeFunction(JSContext* cx, Native native, unsigned nargs, HandleAtom atom,
|
||||
gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
|
||||
NewObjectKind newKind /* = SingletonObject */)
|
||||
{
|
||||
MOZ_ASSERT(native);
|
||||
return NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_FUN,
|
||||
nullptr, atom, nullptr, allocKind, newKind);
|
||||
}
|
||||
|
||||
JSFunction*
|
||||
js::NewNativeConstructor(JSContext* cx, Native native, unsigned nargs, HandleAtom atom,
|
||||
gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
|
||||
NewObjectKind newKind /* = SingletonObject */,
|
||||
JSFunction::Flags flags /* = JSFunction::NATIVE_CTOR */)
|
||||
{
|
||||
MOZ_ASSERT(native);
|
||||
MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
|
||||
return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom,
|
||||
nullptr, allocKind, newKind);
|
||||
}
|
||||
|
||||
JSFunction*
|
||||
js::NewScriptedFunction(JSContext* cx, unsigned nargs,
|
||||
JSFunction::Flags flags, HandleAtom atom,
|
||||
|
@ -2092,26 +2070,16 @@ js::NewFunctionWithProto(JSContext* cx, Native native,
|
|||
unsigned nargs, JSFunction::Flags flags, HandleObject enclosingEnv,
|
||||
HandleAtom atom, HandleObject proto,
|
||||
gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
|
||||
NewObjectKind newKind /* = GenericObject */,
|
||||
NewFunctionProtoHandling protoHandling /* = NewFunctionClassProto */)
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
{
|
||||
MOZ_ASSERT(allocKind == AllocKind::FUNCTION || allocKind == AllocKind::FUNCTION_EXTENDED);
|
||||
MOZ_ASSERT_IF(native, !enclosingEnv);
|
||||
MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
|
||||
|
||||
RootedObject funobj(cx);
|
||||
if (protoHandling == NewFunctionClassProto) {
|
||||
funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto, allocKind,
|
||||
newKind);
|
||||
} else {
|
||||
funobj = NewObjectWithGivenTaggedProto(cx, &JSFunction::class_, AsTaggedProto(proto),
|
||||
allocKind, newKind);
|
||||
}
|
||||
if (!funobj)
|
||||
JSFunction* fun = NewObjectWithClassProto<JSFunction>(cx, proto, allocKind, newKind);
|
||||
if (!fun)
|
||||
return nullptr;
|
||||
|
||||
RootedFunction fun(cx, &funobj->as<JSFunction>());
|
||||
|
||||
if (allocKind == AllocKind::FUNCTION_EXTENDED)
|
||||
flags = JSFunction::Flags(flags | JSFunction::EXTENDED);
|
||||
|
||||
|
|
|
@ -687,20 +687,41 @@ AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp);
|
|||
extern bool
|
||||
AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// If enclosingEnv is null, the function will have a null environment()
|
||||
// (yes, null, not the global). In all cases, the global will be used as the
|
||||
// parent.
|
||||
|
||||
extern JSFunction*
|
||||
NewFunctionWithProto(JSContext* cx, JSNative native, unsigned nargs,
|
||||
JSFunction::Flags flags, HandleObject enclosingEnv, HandleAtom atom,
|
||||
HandleObject proto, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
|
||||
// Allocate a new function backed by a JSNative. Note that by default this
|
||||
// creates a singleton object.
|
||||
extern JSFunction*
|
||||
inline JSFunction*
|
||||
NewNativeFunction(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = SingletonObject);
|
||||
NewObjectKind newKind = SingletonObject)
|
||||
{
|
||||
MOZ_ASSERT(native);
|
||||
return NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_FUN,
|
||||
nullptr, atom, nullptr, allocKind, newKind);
|
||||
}
|
||||
|
||||
// Allocate a new constructor backed by a JSNative. Note that by default this
|
||||
// creates a singleton object.
|
||||
extern JSFunction*
|
||||
inline JSFunction*
|
||||
NewNativeConstructor(JSContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = SingletonObject,
|
||||
JSFunction::Flags flags = JSFunction::NATIVE_CTOR);
|
||||
JSFunction::Flags flags = JSFunction::NATIVE_CTOR)
|
||||
{
|
||||
MOZ_ASSERT(native);
|
||||
MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
|
||||
return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom,
|
||||
nullptr, allocKind, newKind);
|
||||
}
|
||||
|
||||
// Allocate a new scripted function. If enclosingEnv is null, the
|
||||
// global will be used. In all cases the parent of the resulting object will be
|
||||
|
@ -711,25 +732,6 @@ NewScriptedFunction(JSContext* cx, unsigned nargs, JSFunction::Flags flags,
|
|||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = GenericObject,
|
||||
HandleObject enclosingEnv = nullptr);
|
||||
|
||||
// By default, if proto is nullptr, Function.prototype is used instead.i
|
||||
// If protoHandling is NewFunctionExactProto, and proto is nullptr, the created
|
||||
// function will use nullptr as its [[Prototype]] instead. If
|
||||
// enclosingEnv is null, the function will have a null environment()
|
||||
// (yes, null, not the global). In all cases, the global will be used as the
|
||||
// parent.
|
||||
|
||||
enum NewFunctionProtoHandling {
|
||||
NewFunctionClassProto,
|
||||
NewFunctionGivenProto
|
||||
};
|
||||
extern JSFunction*
|
||||
NewFunctionWithProto(JSContext* cx, JSNative native, unsigned nargs,
|
||||
JSFunction::Flags flags, HandleObject enclosingEnv, HandleAtom atom,
|
||||
HandleObject proto, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = GenericObject,
|
||||
NewFunctionProtoHandling protoHandling = NewFunctionClassProto);
|
||||
|
||||
extern JSAtom*
|
||||
IdToFunctionName(JSContext* cx, HandleId id,
|
||||
FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
|
||||
|
|
151
js/src/jspubtd.h
151
js/src/jspubtd.h
|
@ -210,11 +210,90 @@ class MOZ_STACK_CLASS JS_PUBLIC_API(AutoEnterCycleCollection)
|
|||
|
||||
class RootingContext;
|
||||
|
||||
// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
|
||||
// instantiation of MapTypeToRootKind.
|
||||
template <>
|
||||
struct MapTypeToRootKind<void*> {
|
||||
static const RootKind kind = RootKind::Traceable;
|
||||
};
|
||||
|
||||
using RootedListHeads = mozilla::EnumeratedArray<RootKind, RootKind::Limit,
|
||||
Rooted<void*>*>;
|
||||
|
||||
/*
|
||||
* This list enumerates the different types of conceptual stacks we have in
|
||||
* SpiderMonkey. In reality, they all share the C stack, but we allow different
|
||||
* stack limits depending on the type of code running.
|
||||
*/
|
||||
enum StackKind
|
||||
{
|
||||
StackForSystemCode, // C++, such as the GC, running on behalf of the VM.
|
||||
StackForTrustedScript, // Script running with trusted principals.
|
||||
StackForUntrustedScript, // Script running with untrusted principals.
|
||||
StackKindCount
|
||||
};
|
||||
|
||||
class JS_PUBLIC_API(AutoGCRooter);
|
||||
|
||||
// Superclass of JSContext which can be used for rooting data in use by the
|
||||
// current thread but that does not provide all the functions of a JSContext.
|
||||
class RootingContext
|
||||
{
|
||||
// Stack GC roots for Rooted GC heap pointers.
|
||||
RootedListHeads stackRoots_;
|
||||
template <typename T> friend class JS::Rooted;
|
||||
|
||||
// Stack GC roots for AutoFooRooter classes.
|
||||
JS::AutoGCRooter* autoGCRooters_;
|
||||
friend class JS::AutoGCRooter;
|
||||
|
||||
public:
|
||||
RootingContext();
|
||||
|
||||
void traceStackRoots(JSTracer* trc);
|
||||
void checkNoGCRooters();
|
||||
|
||||
protected:
|
||||
// The remaining members in this class should only be accessed through
|
||||
// JSContext pointers. They are unrelated to rooting and are in place so
|
||||
// that inlined API functions can directly access the data.
|
||||
|
||||
/* The current compartment. */
|
||||
JSCompartment* compartment_;
|
||||
|
||||
/* The current zone. */
|
||||
JS::Zone* zone_;
|
||||
|
||||
public:
|
||||
/* Limit pointer for checking native stack consumption. */
|
||||
uintptr_t nativeStackLimit[StackKindCount];
|
||||
|
||||
static const RootingContext* get(const JSContext* cx) {
|
||||
return reinterpret_cast<const RootingContext*>(cx);
|
||||
}
|
||||
|
||||
static RootingContext* get(JSContext* cx) {
|
||||
return reinterpret_cast<RootingContext*>(cx);
|
||||
}
|
||||
|
||||
friend JSCompartment* js::GetContextCompartment(const JSContext* cx);
|
||||
friend JS::Zone* js::GetContextZone(const JSContext* cx);
|
||||
};
|
||||
|
||||
class JS_PUBLIC_API(AutoGCRooter)
|
||||
{
|
||||
public:
|
||||
AutoGCRooter(JSContext* cx, ptrdiff_t tag);
|
||||
AutoGCRooter(RootingContext* cx, ptrdiff_t tag);
|
||||
AutoGCRooter(JSContext* cx, ptrdiff_t tag)
|
||||
: AutoGCRooter(JS::RootingContext::get(cx), tag)
|
||||
{}
|
||||
AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag)
|
||||
: down(cx->autoGCRooters_),
|
||||
tag_(tag),
|
||||
stackTop(&cx->autoGCRooters_)
|
||||
{
|
||||
MOZ_ASSERT(this != *stackTop);
|
||||
*stackTop = this;
|
||||
}
|
||||
|
||||
~AutoGCRooter() {
|
||||
MOZ_ASSERT(this == *stackTop);
|
||||
|
@ -262,74 +341,6 @@ class JS_PUBLIC_API(AutoGCRooter)
|
|||
void operator=(AutoGCRooter& ida) = delete;
|
||||
};
|
||||
|
||||
// Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
|
||||
// instantiation of MapTypeToRootKind.
|
||||
template <>
|
||||
struct MapTypeToRootKind<void*> {
|
||||
static const RootKind kind = RootKind::Traceable;
|
||||
};
|
||||
|
||||
using RootedListHeads = mozilla::EnumeratedArray<RootKind, RootKind::Limit,
|
||||
Rooted<void*>*>;
|
||||
|
||||
/*
|
||||
* This list enumerates the different types of conceptual stacks we have in
|
||||
* SpiderMonkey. In reality, they all share the C stack, but we allow different
|
||||
* stack limits depending on the type of code running.
|
||||
*/
|
||||
enum StackKind
|
||||
{
|
||||
StackForSystemCode, // C++, such as the GC, running on behalf of the VM.
|
||||
StackForTrustedScript, // Script running with trusted principals.
|
||||
StackForUntrustedScript, // Script running with untrusted principals.
|
||||
StackKindCount
|
||||
};
|
||||
|
||||
// Superclass of JSContext which can be used for rooting data in use by the
|
||||
// current thread but that does not provide all the functions of a JSContext.
|
||||
class RootingContext
|
||||
{
|
||||
// Stack GC roots for Rooted GC heap pointers.
|
||||
RootedListHeads stackRoots_;
|
||||
template <typename T> friend class JS::Rooted;
|
||||
|
||||
// Stack GC roots for AutoFooRooter classes.
|
||||
JS::AutoGCRooter* autoGCRooters_;
|
||||
friend class JS::AutoGCRooter;
|
||||
|
||||
public:
|
||||
RootingContext();
|
||||
|
||||
void traceStackRoots(JSTracer* trc);
|
||||
void checkNoGCRooters();
|
||||
|
||||
protected:
|
||||
// The remaining members in this class should only be accessed through
|
||||
// JSContext pointers. They are unrelated to rooting and are in place so
|
||||
// that inlined API functions can directly access the data.
|
||||
|
||||
/* The current compartment. */
|
||||
JSCompartment* compartment_;
|
||||
|
||||
/* The current zone. */
|
||||
JS::Zone* zone_;
|
||||
|
||||
public:
|
||||
/* Limit pointer for checking native stack consumption. */
|
||||
uintptr_t nativeStackLimit[StackKindCount];
|
||||
|
||||
static const RootingContext* get(const JSContext* cx) {
|
||||
return reinterpret_cast<const RootingContext*>(cx);
|
||||
}
|
||||
|
||||
static RootingContext* get(JSContext* cx) {
|
||||
return reinterpret_cast<RootingContext*>(cx);
|
||||
}
|
||||
|
||||
friend JSCompartment* js::GetContextCompartment(const JSContext* cx);
|
||||
friend JS::Zone* js::GetContextZone(const JSContext* cx);
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
namespace js {
|
||||
|
|
|
@ -279,6 +279,10 @@ class RegExpZone
|
|||
/* Like 'get', but compile 'maybeOpt' (if non-null). */
|
||||
RegExpShared* get(JSContext* cx, HandleAtom source, JSString* maybeOpt);
|
||||
|
||||
#ifdef DEBUG
|
||||
void clear() { set_.clear(); }
|
||||
#endif
|
||||
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
};
|
||||
|
||||
|
|
|
@ -538,6 +538,7 @@ JitFrameIter::skipNonScriptedJSFrames()
|
|||
jit::JSJitFrameIter& frames = asJSJit();
|
||||
while (!frames.isScripted() && !frames.done())
|
||||
++frames;
|
||||
settle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -215,10 +215,6 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
|
|||
if (script->baselineScript()->hasPendingIonBuilder())
|
||||
return true;
|
||||
|
||||
// Currently we can't rectify arguments. Therefore disable if argc is too low.
|
||||
if (importFun->nargs() > fi.sig().args().length())
|
||||
return true;
|
||||
|
||||
// Ensure the argument types are included in the argument TypeSets stored in
|
||||
// the TypeScript. This is necessary for Ion, because the import will use
|
||||
// the skip-arg-checks entry point.
|
||||
|
@ -229,9 +225,13 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
|
|||
// patched back.
|
||||
if (!TypeScript::ThisTypes(script)->hasType(TypeSet::UndefinedType()))
|
||||
return true;
|
||||
for (uint32_t i = 0; i < importFun->nargs(); i++) {
|
||||
|
||||
const ValTypeVector& importArgs = fi.sig().args();
|
||||
|
||||
size_t numKnownArgs = Min(importArgs.length(), importFun->nargs());
|
||||
for (uint32_t i = 0; i < numKnownArgs; i++) {
|
||||
TypeSet::Type type = TypeSet::UnknownType();
|
||||
switch (fi.sig().args()[i]) {
|
||||
switch (importArgs[i]) {
|
||||
case ValType::I32: type = TypeSet::Int32Type(); break;
|
||||
case ValType::I64: MOZ_CRASH("can't happen because of above guard");
|
||||
case ValType::F32: type = TypeSet::DoubleType(); break;
|
||||
|
@ -248,6 +248,14 @@ Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, con
|
|||
return true;
|
||||
}
|
||||
|
||||
// These arguments will be filled with undefined at runtime by the
|
||||
// arguments rectifier: check that the imported function can handle
|
||||
// undefined there.
|
||||
for (uint32_t i = importArgs.length(); i < importFun->nargs(); i++) {
|
||||
if (!TypeScript::ArgTypes(script, i)->hasType(TypeSet::UndefinedType()))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Let's optimize it!
|
||||
if (!script->baselineScript()->addDependentWasmImport(cx, *this, funcImportIndex))
|
||||
return false;
|
||||
|
@ -451,6 +459,13 @@ Instance::init(JSContext* cx)
|
|||
}
|
||||
}
|
||||
|
||||
if (!metadata(code_->bestTier()).funcImports.empty()) {
|
||||
JitRuntime* jitRuntime = cx->runtime()->getJitRuntime(cx);
|
||||
if (!jitRuntime)
|
||||
return false;
|
||||
jsJitArgsRectifier_ = jitRuntime->getArgumentsRectifier();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -508,6 +523,8 @@ Instance::tracePrivate(JSTracer* trc)
|
|||
MOZ_ASSERT(!gc::IsAboutToBeFinalized(&object_));
|
||||
TraceEdge(trc, &object_, "wasm instance object");
|
||||
|
||||
TraceNullableEdge(trc, &jsJitArgsRectifier_, "wasm jit args rectifier");
|
||||
|
||||
// OK to just do one tier here; though the tiers have different funcImports
|
||||
// tables, they share the tls object.
|
||||
for (const FuncImport& fi : metadata(code().stableTier()).funcImports)
|
||||
|
|
|
@ -71,6 +71,7 @@ class Instance
|
|||
{
|
||||
JSCompartment* const compartment_;
|
||||
ReadBarrieredWasmInstanceObject object_;
|
||||
GCPtrJitCode jsJitArgsRectifier_;
|
||||
const SharedCode code_;
|
||||
const UniqueDebugState debug_;
|
||||
const UniqueGlobalSegment globals_;
|
||||
|
@ -122,6 +123,8 @@ class Instance
|
|||
bool memoryAccessInGuardRegion(uint8_t* addr, unsigned numBytes) const;
|
||||
TlsData* tlsData() const { return globals_->tlsData(); }
|
||||
|
||||
static size_t offsetOfJSJitArgsRectifier() { return offsetof(Instance, jsJitArgsRectifier_); }
|
||||
|
||||
// This method returns a pointer to the GC object that owns this Instance.
|
||||
// Instances may be reached via weak edges (e.g., Compartment::instances_)
|
||||
// so this perform a read-barrier on the returned object unless the barrier
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "wasm/WasmCode.h"
|
||||
#include "wasm/WasmGenerator.h"
|
||||
#include "wasm/WasmInstance.h"
|
||||
|
||||
#include "jit/MacroAssembler-inl.h"
|
||||
|
||||
|
@ -710,7 +711,7 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
|
|||
// the return address.
|
||||
static_assert(WasmStackAlignment >= JitStackAlignment, "subsumes");
|
||||
unsigned sizeOfRetAddr = sizeof(void*);
|
||||
unsigned sizeOfPreFrame = WasmFrameLayout::Size() - sizeOfRetAddr;
|
||||
unsigned sizeOfPreFrame = WasmToJSJitFrameLayout::Size() - sizeOfRetAddr;
|
||||
unsigned sizeOfThisAndArgs = (1 + fi.sig().args().length()) * sizeof(Value);
|
||||
unsigned totalJitFrameBytes = sizeOfRetAddr + sizeOfPreFrame + sizeOfThisAndArgs;
|
||||
unsigned jitFramePushed = StackDecrementForCall(masm, JitStackAlignment, totalJitFrameBytes) -
|
||||
|
@ -722,7 +723,7 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
|
|||
// 1. Descriptor
|
||||
size_t argOffset = 0;
|
||||
uint32_t descriptor = MakeFrameDescriptor(sizeOfThisAndArgsAndPadding, JitFrame_WasmToJSJit,
|
||||
WasmFrameLayout::Size());
|
||||
WasmToJSJitFrameLayout::Size());
|
||||
masm.storePtr(ImmWord(uintptr_t(descriptor)), Address(masm.getStackPointer(), argOffset));
|
||||
argOffset += sizeof(size_t);
|
||||
|
||||
|
@ -730,17 +731,13 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
|
|||
Register callee = ABINonArgReturnReg0; // live until call
|
||||
Register scratch = ABINonArgReturnReg1; // repeatedly clobbered
|
||||
|
||||
// 2.1. Get callee
|
||||
// 2.1. Get JSFunction callee
|
||||
masm.loadWasmGlobalPtr(fi.tlsDataOffset() + offsetof(FuncImportTls, obj), callee);
|
||||
|
||||
// 2.2. Save callee
|
||||
masm.storePtr(callee, Address(masm.getStackPointer(), argOffset));
|
||||
argOffset += sizeof(size_t);
|
||||
|
||||
// 2.3. Load callee executable entry point
|
||||
masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), callee);
|
||||
masm.loadBaselineOrIonNoArgCheck(callee, callee, nullptr);
|
||||
|
||||
// 3. Argc
|
||||
unsigned argc = fi.sig().args().length();
|
||||
masm.storePtr(ImmWord(uintptr_t(argc)), Address(masm.getStackPointer(), argOffset));
|
||||
|
@ -757,6 +754,19 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
|
|||
argOffset += fi.sig().args().length() * sizeof(Value);
|
||||
MOZ_ASSERT(argOffset == sizeOfThisAndArgs + sizeOfPreFrame);
|
||||
|
||||
// 6. Check if we need to rectify arguments
|
||||
masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch);
|
||||
|
||||
Label rectify;
|
||||
masm.branch32(Assembler::Above, scratch, Imm32(fi.sig().args().length()), &rectify);
|
||||
|
||||
// 7. If we haven't rectified arguments, load callee executable entry point
|
||||
masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), callee);
|
||||
masm.loadBaselineOrIonNoArgCheck(callee, callee, nullptr);
|
||||
|
||||
Label rejoinBeforeCall;
|
||||
masm.bind(&rejoinBeforeCall);
|
||||
|
||||
AssertStackAlignment(masm, JitStackAlignment, sizeOfRetAddr);
|
||||
masm.callJitNoProfiler(callee);
|
||||
|
||||
|
@ -818,6 +828,15 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
|
|||
|
||||
GenerateJitExitEpilogue(masm, masm.framePushed(), offsets);
|
||||
|
||||
{
|
||||
// Call the arguments rectifier.
|
||||
masm.bind(&rectify);
|
||||
masm.loadPtr(Address(WasmTlsReg, offsetof(TlsData, instance)), callee);
|
||||
masm.loadPtr(Address(callee, Instance::offsetOfJSJitArgsRectifier()), callee);
|
||||
masm.loadPtr(Address(callee, JitCode::offsetOfCode()), callee);
|
||||
masm.jump(&rejoinBeforeCall);
|
||||
}
|
||||
|
||||
if (oolConvert.used()) {
|
||||
masm.bind(&oolConvert);
|
||||
masm.setFramePushed(nativeFramePushed);
|
||||
|
|
|
@ -6279,17 +6279,8 @@ nsDisplayOpacity::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuil
|
|||
}
|
||||
|
||||
nsTArray<mozilla::wr::WrFilterOp> filters;
|
||||
StackingContextHelper sc(aSc,
|
||||
aBuilder,
|
||||
aDisplayListBuilder,
|
||||
this,
|
||||
&mList,
|
||||
nullptr,
|
||||
animationsId,
|
||||
opacityForSC,
|
||||
nullptr,
|
||||
nullptr,
|
||||
filters);
|
||||
StackingContextHelper sc(aSc, aBuilder, filters, nullptr, animationsId,
|
||||
opacityForSC);
|
||||
|
||||
aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(&mList,
|
||||
aDisplayListBuilder,
|
||||
|
@ -6341,9 +6332,8 @@ nsDisplayBlendMode::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu
|
|||
nsDisplayListBuilder* aDisplayListBuilder)
|
||||
{
|
||||
nsTArray<mozilla::wr::WrFilterOp> filters;
|
||||
StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
|
||||
&mList, nullptr, 0, nullptr, nullptr, nullptr,
|
||||
filters, nsCSSRendering::GetGFXBlendMode(mBlendMode));
|
||||
StackingContextHelper sc(aSc, aBuilder, filters, nullptr, 0, nullptr, nullptr,
|
||||
nullptr, nsCSSRendering::GetGFXBlendMode(mBlendMode));
|
||||
|
||||
return nsDisplayWrapList::CreateWebRenderCommands(aBuilder,aResources, sc,
|
||||
aManager, aDisplayListBuilder);
|
||||
|
@ -6471,8 +6461,7 @@ nsDisplayBlendContainer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder
|
|||
mozilla::layers::WebRenderLayerManager* aManager,
|
||||
nsDisplayListBuilder* aDisplayListBuilder)
|
||||
{
|
||||
StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
|
||||
&mList, nullptr, 0, nullptr, nullptr);
|
||||
StackingContextHelper sc(aSc, aBuilder);
|
||||
|
||||
return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
|
||||
aManager, aDisplayListBuilder);
|
||||
|
@ -6578,8 +6567,8 @@ nsDisplayOwnLayer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBui
|
|||
animationInfo.EnsureAnimationsId();
|
||||
mWrAnimationId = animationInfo.GetCompositorAnimationsId();
|
||||
|
||||
StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
|
||||
&mList, nullptr, mWrAnimationId, nullptr, nullptr);
|
||||
StackingContextHelper sc(aSc, aBuilder, nsTArray<wr::WrFilterOp>(), nullptr,
|
||||
mWrAnimationId);
|
||||
|
||||
nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
|
||||
aManager, aDisplayListBuilder);
|
||||
|
@ -7131,8 +7120,7 @@ nsDisplayStickyPosition::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder
|
|||
// adjusted origin and use that for the nested items. This way all the
|
||||
// ToRelativeLayoutRect calls on this StackingContextHelper object will
|
||||
// include the necessary adjustment.
|
||||
StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
|
||||
&mList, nullptr, 0, nullptr, nullptr);
|
||||
StackingContextHelper sc(aSc, aBuilder);
|
||||
sc.AdjustOrigin(scTranslation);
|
||||
|
||||
// TODO: if, inside this nested command builder, we try to turn a gecko clip
|
||||
|
@ -8056,15 +8044,12 @@ nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBu
|
|||
nsTArray<mozilla::wr::WrFilterOp> filters;
|
||||
StackingContextHelper sc(aSc,
|
||||
aBuilder,
|
||||
aDisplayListBuilder,
|
||||
this,
|
||||
mStoredList.GetChildren(),
|
||||
filters,
|
||||
&newTransformMatrix,
|
||||
animationsId,
|
||||
nullptr,
|
||||
transformForSC,
|
||||
nullptr,
|
||||
filters,
|
||||
gfx::CompositionOp::OP_OVER,
|
||||
!BackfaceIsHidden());
|
||||
|
||||
|
@ -8670,15 +8655,12 @@ nsDisplayPerspective::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& a
|
|||
nsTArray<mozilla::wr::WrFilterOp> filters;
|
||||
StackingContextHelper sc(aSc,
|
||||
aBuilder,
|
||||
aDisplayListBuilder,
|
||||
this,
|
||||
mList.GetChildren(),
|
||||
filters,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
&transformForSC,
|
||||
&perspectiveMatrix,
|
||||
filters,
|
||||
gfx::CompositionOp::OP_OVER,
|
||||
!BackfaceIsHidden());
|
||||
|
||||
|
@ -9409,17 +9391,7 @@ nsDisplayFilter::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuild
|
|||
wrFilters.AppendElement(wr::ToWrFilterOp(ToCSSFilter(filter)));
|
||||
}
|
||||
|
||||
StackingContextHelper sc(aSc,
|
||||
aBuilder,
|
||||
aDisplayListBuilder,
|
||||
this,
|
||||
&mList,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
wrFilters);
|
||||
StackingContextHelper sc(aSc, aBuilder, wrFilters);
|
||||
|
||||
nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, sc, aManager, aDisplayListBuilder);
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<select>
|
||||
<script>document.documentElement.offsetHeight</script>
|
||||
<option>Hello there</option>
|
||||
<script>document.documentElement.offsetHeight</script>
|
||||
</select>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<select>
|
||||
<script>document.documentElement.offsetHeight</script>
|
||||
<option>Hello there</option>
|
||||
</select>
|
||||
</html>
|
|
@ -2042,5 +2042,6 @@ needs-focus != 1377447-1.html 1377447-2.html
|
|||
== 1398500-1.html 1398500-1-ref.html
|
||||
== 1401317.html 1401317-ref.html
|
||||
== 1401992.html 1401992-ref.html
|
||||
== 1405878-1.xml 1405878-1-ref.xml
|
||||
== 1404057.html 1404057-ref.html
|
||||
!= 1404057.html 1404057-noref.html
|
||||
|
|
|
@ -2,9 +2,9 @@ pref(layout.css.mix-blend-mode.enabled,true) == blend-canvas.html blend-canvas-r
|
|||
pref(layout.css.mix-blend-mode.enabled,true) == blend-constant-background-color.html blend-constant-background-color-ref.html
|
||||
pref(layout.css.mix-blend-mode.enabled,true) fuzzy-if(webrender,1-1,7875-7875) == blend-gradient-background-color.html blend-gradient-background-color-ref.html
|
||||
pref(layout.css.mix-blend-mode.enabled,true) == blend-image.html blend-image-ref.html
|
||||
pref(layout.css.mix-blend-mode.enabled,true) fails-if(webrender) == blend-difference-stacking.html blend-difference-stacking-ref.html
|
||||
pref(layout.css.mix-blend-mode.enabled,true) == blend-difference-stacking.html blend-difference-stacking-ref.html
|
||||
|
||||
fuzzy-if(skiaContent,1,30000) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-alpha.html background-blending-alpha-ref.html
|
||||
fuzzy-if(skiaContent,1,30000) pref(layout.css.background-blend-mode.enabled,true) == background-blending-alpha.html background-blending-alpha-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) fuzzy-if(webrender,1-1,7875-7875) == background-blending-gradient-color.html background-blending-gradient-color-ref.html
|
||||
fuzzy-if(azureSkiaGL,3,7597) fuzzy-if(cocoaWidget,3,7597) fuzzy-if(d2d,1,3800) fuzzy-if(d3d11,1,4200) fuzzy-if(skiaContent,2,9450) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-gradient-gradient.html background-blending-gradient-gradient-ref.html
|
||||
fuzzy-if(azureSkiaGL,2,7174) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-gradient-image.html background-blending-gradient-color-ref.html
|
||||
|
@ -12,21 +12,21 @@ fuzzy-if(azureSkia||d2d||gtkWidget,1,10000) pref(layout.css.background-blend-mod
|
|||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-png.html background-blending-image-color-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-color-svg.html background-blending-image-color-ref.html
|
||||
fuzzy-if(azureSkiaGL,2,7174) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-image-gradient.html background-blending-gradient-color-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-image-image.html background-blending-image-color-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-isolation.html background-blending-isolation-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-image-image.html background-blending-image-color-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-isolation.html background-blending-isolation-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-list-repeat.html background-blending-list-repeat-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-multiple-images.html background-blending-multiple-images-ref.html
|
||||
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-color-burn.html background-blending-color-burn-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-color-dodge.html background-blending-color-dodge-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-color-burn.html background-blending-color-burn-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-color-dodge.html background-blending-color-dodge-ref.svg
|
||||
# need to investigate why these tests are fuzzy - first suspect is a possible color space conversion on some platforms; same for mix-blend-mode tests
|
||||
fuzzy-if(azureSkia||gtkWidget,2,9600) fuzzy-if(d2d,1,8000) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-color.html background-blending-color-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-darken.html background-blending-darken-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-difference.html background-blending-difference-ref.svg
|
||||
fuzzy-if(skiaContent,1,1600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-exclusion.html background-blending-exclusion-ref.svg
|
||||
fuzzy-if(cocoaWidget||d2d,1,1600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-hard-light.html background-blending-hard-light-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-difference.html background-blending-difference-ref.svg
|
||||
fuzzy-if(skiaContent,1,1600) pref(layout.css.background-blend-mode.enabled,true) == background-blending-exclusion.html background-blending-exclusion-ref.svg
|
||||
fuzzy-if(cocoaWidget||d2d,1,1600) pref(layout.css.background-blend-mode.enabled,true) == background-blending-hard-light.html background-blending-hard-light-ref.svg
|
||||
fuzzy-if(d2d,1,9600) fuzzy-if(azureSkia||gtkWidget,2,9600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-hue.html background-blending-hue-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-lighten.html background-blending-lighten-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-lighten.html background-blending-lighten-ref.svg
|
||||
fuzzy-if(d2d,1,8000) fuzzy-if(azureSkia||gtkWidget,2,9600) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-luminosity.html background-blending-luminosity-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-multiply.html background-blending-multiply-ref.svg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-normal.html background-blending-normal-ref.svg
|
||||
|
@ -60,7 +60,7 @@ pref(layout.css.background-blend-mode.enabled,true) == background-blending-image
|
|||
|
||||
# Test plan 5.3.2 Background layers do not blend with content outside the background (or behind the element) - tests 2 and 3
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-isolation-parent-child-color.html background-blending-isolation-parent-child-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-isolation-parent-child-image.html background-blending-isolation-parent-child-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-isolation-parent-child-image.html background-blending-isolation-parent-child-ref.html
|
||||
|
||||
# Test plan 5.3.6 background-blend-mode for an element with background-position
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-position-percentage.html background-blending-background-position-percentage-ref.html
|
||||
|
@ -85,16 +85,16 @@ pref(layout.css.background-blend-mode.enabled,true) == background-blending-backg
|
|||
|
||||
# Test plan 5.3.11 background-blend-mode for an element with background-attachement
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-attachement-fixed.html background-blending-background-attachement-fixed-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-background-attachement-fixed-scroll.html background-blending-background-attachement-fixed-scroll-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-background-attachement-fixed-scroll.html background-blending-background-attachement-fixed-scroll-ref.html
|
||||
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blend-mode-body-image.html background-blend-mode-body-image-ref.html
|
||||
fuzzy-if(Android,4,768) fuzzy-if(gtkWidget,1,132) fuzzy-if(skiaContent,1,800) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blend-mode-body-transparent-image.html background-blend-mode-body-transparent-image-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blend-mode-body-image.html background-blend-mode-body-image-ref.html
|
||||
fuzzy-if(Android,4,768) fuzzy-if(gtkWidget,1,132) fuzzy-if(skiaContent,1,800) pref(layout.css.background-blend-mode.enabled,true) == background-blend-mode-body-transparent-image.html background-blend-mode-body-transparent-image-ref.html
|
||||
|
||||
pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == background-blending-moz-element.html background-blending-moz-element-ref.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-moz-element.html background-blending-moz-element-ref.html
|
||||
|
||||
fuzzy(1,40000) pref(layout.css.background-blend-mode.enabled,true) fails-if(webrender) == mix-blend-mode-soft-light.html mix-blend-mode-soft-light-ref.html
|
||||
|
||||
# Test plan 4.4.2 element with isolation:isolate creates an isolated group for blended children
|
||||
pref(layout.css.isolation.enabled,true) fails-if(webrender) == blend-isolation.html blend-isolation-ref.html
|
||||
pref(layout.css.isolation.enabled,true) == blend-isolation.html blend-isolation-ref.html
|
||||
|
||||
pref(layout.css.background-blend-mode.enabled,true) == bug1281593.html bug1281593-ref.html
|
||||
|
|
|
@ -178,7 +178,7 @@ HTTP(..) == reflow-sanity-1.html reflow-sanity-1-data.html
|
|||
HTTP(..) == reflow-sanity-delay-1a.html reflow-sanity-1-ref.html
|
||||
HTTP(..) == reflow-sanity-delay-1b.html reflow-sanity-1-ref.html
|
||||
HTTP(..) == reflow-sanity-delay-1c.html reflow-sanity-1-ref.html
|
||||
HTTP(..) == reflow-sanity-delay-1-metrics.html reflow-sanity-1-ref.html
|
||||
skip-if(winWidget&&!isDebugBuild) HTTP(..) == reflow-sanity-delay-1-metrics.html reflow-sanity-1-ref.html
|
||||
|
||||
# font-display
|
||||
skip-if(/^Linux\x20i686/.test(http.oscpu)) HTTP(..) == font-display-1.html font-display-1-ref.html # normal font load (~500ms)
|
||||
|
|
|
@ -194,14 +194,25 @@ public:
|
|||
mozilla::LogicalSide aOwner,
|
||||
bool aBevel);
|
||||
|
||||
bool IsIStartStart() const;
|
||||
inline bool IsIStartStart() const
|
||||
{
|
||||
return (bool)mIStartStart;
|
||||
}
|
||||
|
||||
void SetIStartStart(bool aValue);
|
||||
inline void SetIStartStart(bool aValue)
|
||||
{
|
||||
mIStartStart = aValue;
|
||||
}
|
||||
|
||||
bool IsBStartStart() const;
|
||||
|
||||
void SetBStartStart(bool aValue);
|
||||
inline bool IsBStartStart() const
|
||||
{
|
||||
return (bool)mBStartStart;
|
||||
}
|
||||
|
||||
inline void SetBStartStart(bool aValue)
|
||||
{
|
||||
mBStartStart = aValue;
|
||||
}
|
||||
|
||||
protected:
|
||||
BCPixelSize mIStartSize; // size in pixels of iStart border
|
||||
|
@ -371,7 +382,8 @@ inline void CellData::SetOverlap(bool aOverlap)
|
|||
inline BCData::BCData()
|
||||
{
|
||||
mIStartOwner = mBStartOwner = eCellOwner;
|
||||
mIStartStart = mBStartStart = 1;
|
||||
SetBStartStart(true);
|
||||
SetIStartStart(true);
|
||||
mIStartSize = mCornerSubSize = mBStartSize = 0;
|
||||
mCornerSide = mozilla::eLogicalSideBStart;
|
||||
mCornerBevel = false;
|
||||
|
@ -385,7 +397,7 @@ inline nscoord BCData::GetIStartEdge(BCBorderOwner& aOwner,
|
|||
bool& aStart) const
|
||||
{
|
||||
aOwner = (BCBorderOwner)mIStartOwner;
|
||||
aStart = (bool)mIStartStart;
|
||||
aStart = IsIStartStart();
|
||||
|
||||
return (nscoord)mIStartSize;
|
||||
}
|
||||
|
@ -396,14 +408,14 @@ inline void BCData::SetIStartEdge(BCBorderOwner aOwner,
|
|||
{
|
||||
mIStartOwner = aOwner;
|
||||
mIStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
|
||||
mIStartStart = aStart;
|
||||
SetIStartStart(aStart);
|
||||
}
|
||||
|
||||
inline nscoord BCData::GetBStartEdge(BCBorderOwner& aOwner,
|
||||
bool& aStart) const
|
||||
{
|
||||
aOwner = (BCBorderOwner)mBStartOwner;
|
||||
aStart = (bool)mBStartStart;
|
||||
aStart = IsBStartStart();
|
||||
|
||||
return (nscoord)mBStartSize;
|
||||
}
|
||||
|
@ -414,7 +426,7 @@ inline void BCData::SetBStartEdge(BCBorderOwner aOwner,
|
|||
{
|
||||
mBStartOwner = aOwner;
|
||||
mBStartSize = (aSize > MAX_BORDER_WIDTH) ? MAX_BORDER_WIDTH : aSize;
|
||||
mBStartStart = aStart;
|
||||
SetBStartStart(aStart);
|
||||
}
|
||||
|
||||
inline BCPixelSize BCData::GetCorner(mozilla::LogicalSide& aOwnerSide,
|
||||
|
@ -434,24 +446,4 @@ inline void BCData::SetCorner(BCPixelSize aSubSize,
|
|||
mCornerBevel = aBevel;
|
||||
}
|
||||
|
||||
inline bool BCData::IsIStartStart() const
|
||||
{
|
||||
return (bool)mIStartStart;
|
||||
}
|
||||
|
||||
inline void BCData::SetIStartStart(bool aValue)
|
||||
{
|
||||
mIStartStart = aValue;
|
||||
}
|
||||
|
||||
inline bool BCData::IsBStartStart() const
|
||||
{
|
||||
return (bool)mBStartStart;
|
||||
}
|
||||
|
||||
inline void BCData::SetBStartStart(bool aValue)
|
||||
{
|
||||
mBStartStart = aValue;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1312,8 +1312,8 @@ pref("dom.timeout.foreground_budget_regeneration_rate", 1);
|
|||
pref("dom.timeout.foreground_throttling_max_budget", -1);
|
||||
// The maximum amount a timeout can be delayed by budget throttling
|
||||
pref("dom.timeout.budget_throttling_max_delay", 15000);
|
||||
// Turn off budget throttling by default
|
||||
pref("dom.timeout.enable_budget_timer_throttling", false);
|
||||
// Turn on budget throttling by default
|
||||
pref("dom.timeout.enable_budget_timer_throttling", true);
|
||||
|
||||
// Don't use new input types
|
||||
pref("dom.experimental_forms", false);
|
||||
|
|
|
@ -106,6 +106,28 @@ nsBaseChannel::Redirect(nsIChannel *newChannel, uint32_t redirectFlags,
|
|||
new nsRedirectHistoryEntry(uriPrincipal, nullptr, EmptyCString());
|
||||
|
||||
newLoadInfo->AppendRedirectHistoryEntry(entry, isInternalRedirect);
|
||||
|
||||
// Ensure the channel's loadInfo's result principal URI so that it's
|
||||
// either non-null or updated to the redirect target URI.
|
||||
// We must do this because in case the loadInfo's result principal URI
|
||||
// is null, it would be taken from OriginalURI of the channel. But we
|
||||
// overwrite it with the whole redirect chain first URI before opening
|
||||
// the target channel, hence the information would be lost.
|
||||
// If the protocol handler that created the channel wants to use
|
||||
// the originalURI of the channel as the principal URI, it has left
|
||||
// the result principal URI on the load info null.
|
||||
nsCOMPtr<nsIURI> resultPrincipalURI;
|
||||
|
||||
nsCOMPtr<nsILoadInfo> existingLoadInfo = newChannel->GetLoadInfo();
|
||||
if (existingLoadInfo) {
|
||||
existingLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
|
||||
}
|
||||
if (!resultPrincipalURI) {
|
||||
newChannel->GetOriginalURI(getter_AddRefs(resultPrincipalURI));
|
||||
}
|
||||
|
||||
newLoadInfo->SetResultPrincipalURI(resultPrincipalURI);
|
||||
|
||||
newChannel->SetLoadInfo(newLoadInfo);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -68,7 +68,7 @@ interface nsIInterceptedChannel : nsISupports
|
|||
* @return NS_ERROR_FAILURE if the response has already been synthesized or
|
||||
* the original request has been instructed to continue.
|
||||
*/
|
||||
void cancel(in nsresult status);
|
||||
void cancelInterception(in nsresult status);
|
||||
|
||||
/**
|
||||
* The synthesized response body to be produced.
|
||||
|
|
|
@ -780,7 +780,6 @@ bool nsIDNService::isLabelSafe(const nsAString &label)
|
|||
if (illegalScriptCombo(script, savedScript)) {
|
||||
return false;
|
||||
}
|
||||
lastScript = script;
|
||||
}
|
||||
|
||||
// Check for mixed numbering systems
|
||||
|
@ -833,6 +832,10 @@ bool nsIDNService::isLabelSafe(const nsAString &label)
|
|||
}
|
||||
}
|
||||
|
||||
if (script != Script::COMMON && script != Script::INHERITED) {
|
||||
lastScript = script;
|
||||
}
|
||||
|
||||
// Simplified/Traditional Chinese check temporarily disabled -- bug 857481
|
||||
#if 0
|
||||
|
||||
|
|
|
@ -371,6 +371,36 @@ public: /* Necko internal use only... */
|
|||
return mChannelId;
|
||||
}
|
||||
|
||||
void InternalSetUploadStream(nsIInputStream *uploadStream)
|
||||
{
|
||||
mUploadStream = uploadStream;
|
||||
}
|
||||
|
||||
void SetUploadStreamHasHeaders(bool hasHeaders)
|
||||
{
|
||||
mUploadStreamHasHeaders = hasHeaders;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE nsresult
|
||||
SetReferrerWithPolicyInternal(nsIURI *referrer, uint32_t referrerPolicy)
|
||||
{
|
||||
nsAutoCString spec;
|
||||
nsresult rv = referrer->GetAsciiSpec(spec);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
mReferrer = referrer;
|
||||
mReferrerPolicy = referrerPolicy;
|
||||
rv = mRequestHead.SetHeader(nsHttp::Referer, spec);
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE nsresult SetTopWindowURI(nsIURI* aTopWindowURI)
|
||||
{
|
||||
mTopWindowURI = aTopWindowURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Handle notifying listener, removing from loadgroup if request failed.
|
||||
void DoNotifyListener();
|
||||
|
|
|
@ -3570,12 +3570,6 @@ HttpChannelChild::ForceIntercepted(bool aPostRedirectChannelShouldIntercept,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelChild::ForceIntercepted(uint64_t aInterceptionID)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::ForceIntercepted(nsIInputStream* aSynthesizedInput)
|
||||
{
|
||||
|
|
|
@ -98,7 +98,6 @@ public:
|
|||
NS_IMETHOD GetProtocolVersion(nsACString& aProtocolVersion) override;
|
||||
// nsIHttpChannelInternal
|
||||
NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey) override;
|
||||
NS_IMETHOD ForceIntercepted(uint64_t aInterceptionID) override;
|
||||
// nsISupportsPriority
|
||||
NS_IMETHOD SetPriority(int32_t value) override;
|
||||
// nsIClassOfService
|
||||
|
|
|
@ -113,7 +113,7 @@ HttpChannelParent::ActorDestroy(ActorDestroyReason why)
|
|||
// If this is an intercepted channel, we need to make sure that any resources are
|
||||
// cleaned up to avoid leaks.
|
||||
if (mParentListener) {
|
||||
mParentListener->ClearInterceptedChannel();
|
||||
mParentListener->ClearInterceptedChannel(this);
|
||||
}
|
||||
|
||||
CleanupBackgroundChannel();
|
||||
|
@ -235,8 +235,9 @@ HttpChannelParent::CleanupBackgroundChannel()
|
|||
|
||||
// The nsHttpChannel may have a reference to this parent, release it
|
||||
// to avoid circular references.
|
||||
if (mChannel) {
|
||||
mChannel->SetWarningReporter(nullptr);
|
||||
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
|
||||
if (httpChannelImpl) {
|
||||
httpChannelImpl->SetWarningReporter(nullptr);
|
||||
}
|
||||
|
||||
if (!mPromise.IsEmpty()) {
|
||||
|
@ -521,7 +522,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
||||
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(channel, &rv);
|
||||
RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(channel, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
@ -531,7 +532,10 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
httpChannel->SetTopLevelContentWindowId(aContentWindowId);
|
||||
httpChannel->SetTopLevelOuterContentWindowId(aTopLevelOuterContentWindowId);
|
||||
|
||||
httpChannel->SetWarningReporter(this);
|
||||
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(httpChannel);
|
||||
if (httpChannelImpl) {
|
||||
httpChannelImpl->SetWarningReporter(this);
|
||||
}
|
||||
httpChannel->SetTimingEnabled(true);
|
||||
if (mPBOverride != kPBOverride_Unset) {
|
||||
httpChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
|
||||
|
@ -566,8 +570,8 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
httpChannel->SetEmptyRequestHeader(requestHeaders[i].mHeader);
|
||||
} else {
|
||||
httpChannel->SetRequestHeader(requestHeaders[i].mHeader,
|
||||
requestHeaders[i].mValue,
|
||||
requestHeaders[i].mMerge);
|
||||
requestHeaders[i].mValue,
|
||||
requestHeaders[i].mMerge);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,7 +649,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
if (aSynthesizedResponseHead.type() == OptionalHttpResponseHead::TnsHttpResponseHead) {
|
||||
parentListener->SetupInterception(aSynthesizedResponseHead.get_nsHttpResponseHead());
|
||||
mWillSynthesizeResponse = true;
|
||||
httpChannel->SetCouldBeSynthesized();
|
||||
httpChannelImpl->SetCouldBeSynthesized();
|
||||
|
||||
if (!aSecurityInfoSerialization.IsEmpty()) {
|
||||
nsCOMPtr<nsISupports> secInfo;
|
||||
|
@ -671,10 +675,14 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
|||
return SendFailedAsyncOpen(rv);
|
||||
}
|
||||
|
||||
httpChannel->SetCacheKey(cacheKey);
|
||||
httpChannel->PreferAlternativeDataType(aPreferredAlternativeType);
|
||||
nsCOMPtr<nsICacheInfoChannel> cacheChannel =
|
||||
do_QueryInterface(static_cast<nsIChannel*>(httpChannel.get()));
|
||||
if (cacheChannel) {
|
||||
cacheChannel->SetCacheKey(cacheKey);
|
||||
cacheChannel->PreferAlternativeDataType(aPreferredAlternativeType);
|
||||
|
||||
httpChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
|
||||
cacheChannel->SetAllowStaleCacheContent(aAllowStaleCacheContent);
|
||||
}
|
||||
|
||||
httpChannel->SetContentType(aContentTypeHint);
|
||||
|
||||
|
@ -814,14 +822,17 @@ HttpChannelParent::ConnectChannel(const uint32_t& registrarId, const bool& shoul
|
|||
LOG((" found channel %p, rv=%08" PRIx32, channel.get(), static_cast<uint32_t>(rv)));
|
||||
mChannel = do_QueryObject(channel);
|
||||
if (!mChannel) {
|
||||
LOG((" but it's not nsHttpChannel"));
|
||||
LOG((" but it's not HttpBaseChannel"));
|
||||
Delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG((" and it is nsHttpChannel %p", mChannel.get()));
|
||||
LOG((" and it is HttpBaseChannel %p", mChannel.get()));
|
||||
|
||||
mChannel->SetWarningReporter(this);
|
||||
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
|
||||
if (httpChannelImpl) {
|
||||
httpChannelImpl->SetWarningReporter(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINetworkInterceptController> controller;
|
||||
NS_QueryNotificationCallbacks(channel, controller);
|
||||
|
@ -1409,15 +1420,15 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
MOZ_RELEASE_ASSERT(!mDivertingFromChild,
|
||||
"Cannot call OnStartRequest if diverting is set!");
|
||||
|
||||
RefPtr<nsHttpChannel> chan = do_QueryObject(aRequest);
|
||||
RefPtr<HttpBaseChannel> chan = do_QueryObject(aRequest);
|
||||
if (!chan) {
|
||||
LOG((" aRequest is not nsHttpChannel"));
|
||||
NS_ERROR("Expecting only nsHttpChannel as aRequest in HttpChannelParent::OnStartRequest");
|
||||
LOG((" aRequest is not HttpBaseChannel"));
|
||||
NS_ERROR("Expecting only HttpBaseChannel as aRequest in HttpChannelParent::OnStartRequest");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mChannel == chan,
|
||||
"HttpChannelParent getting OnStartRequest from a different nsHttpChannel instance");
|
||||
"HttpChannelParent getting OnStartRequest from a different HttpBaseChannel instance");
|
||||
|
||||
// Send down any permissions which are relevant to this URL if we are
|
||||
// performing a document load. We can't do that is mIPCClosed is set.
|
||||
|
@ -1432,28 +1443,36 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
nsHttpResponseHead *responseHead = chan->GetResponseHead();
|
||||
nsHttpRequestHead *requestHead = chan->GetRequestHead();
|
||||
bool isFromCache = false;
|
||||
chan->IsFromCache(&isFromCache);
|
||||
int32_t fetchCount = 0;
|
||||
chan->GetCacheTokenFetchCount(&fetchCount);
|
||||
uint32_t expirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
|
||||
chan->GetCacheTokenExpirationTime(&expirationTime);
|
||||
nsCString cachedCharset;
|
||||
chan->GetCacheTokenCachedCharset(cachedCharset);
|
||||
|
||||
bool loadedFromApplicationCache;
|
||||
chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
|
||||
if (loadedFromApplicationCache) {
|
||||
mOfflineForeignMarker = chan->GetOfflineCacheEntryAsForeignMarker();
|
||||
nsCOMPtr<nsIApplicationCache> appCache;
|
||||
chan->GetApplicationCache(getter_AddRefs(appCache));
|
||||
nsCString appCacheGroupId;
|
||||
nsCString appCacheClientId;
|
||||
appCache->GetGroupID(appCacheGroupId);
|
||||
appCache->GetClientID(appCacheClientId);
|
||||
if (mIPCClosed ||
|
||||
!SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
|
||||
{
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(chan);
|
||||
|
||||
if (httpChannelImpl) {
|
||||
httpChannelImpl->IsFromCache(&isFromCache);
|
||||
httpChannelImpl->GetCacheTokenFetchCount(&fetchCount);
|
||||
httpChannelImpl->GetCacheTokenExpirationTime(&expirationTime);
|
||||
httpChannelImpl->GetCacheTokenCachedCharset(cachedCharset);
|
||||
}
|
||||
|
||||
bool loadedFromApplicationCache = false;
|
||||
|
||||
if (httpChannelImpl) {
|
||||
httpChannelImpl->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
|
||||
if (loadedFromApplicationCache) {
|
||||
mOfflineForeignMarker = httpChannelImpl->GetOfflineCacheEntryAsForeignMarker();
|
||||
nsCOMPtr<nsIApplicationCache> appCache;
|
||||
httpChannelImpl->GetApplicationCache(getter_AddRefs(appCache));
|
||||
nsCString appCacheGroupId;
|
||||
nsCString appCacheClientId;
|
||||
appCache->GetGroupID(appCacheGroupId);
|
||||
appCache->GetClientID(appCacheClientId);
|
||||
if (mIPCClosed ||
|
||||
!SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
|
||||
{
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1464,11 +1483,32 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
// Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
|
||||
// It could be already released by nsHttpChannel at that time.
|
||||
nsCOMPtr<nsISupports> cacheEntry;
|
||||
chan->GetCacheToken(getter_AddRefs(cacheEntry));
|
||||
mCacheEntry = do_QueryInterface(cacheEntry);
|
||||
|
||||
nsresult channelStatus = NS_OK;
|
||||
chan->GetStatus(&channelStatus);
|
||||
uint32_t cacheKeyValue = 0;
|
||||
nsAutoCString altDataType;
|
||||
|
||||
if (httpChannelImpl) {
|
||||
httpChannelImpl->GetCacheToken(getter_AddRefs(cacheEntry));
|
||||
mCacheEntry = do_QueryInterface(cacheEntry);
|
||||
|
||||
httpChannelImpl->GetStatus(&channelStatus);
|
||||
|
||||
nsCOMPtr<nsISupports> cacheKey;
|
||||
httpChannelImpl->GetCacheKey(getter_AddRefs(cacheKey));
|
||||
if (cacheKey) {
|
||||
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(cacheKey);
|
||||
if (!container) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
nsresult rv = container->GetData(&cacheKeyValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
httpChannelImpl->GetAlternativeDataType(altDataType);
|
||||
}
|
||||
|
||||
nsCString secInfoSerialization;
|
||||
UpdateAndSerializeSecurityInfo(secInfoSerialization);
|
||||
|
@ -1476,23 +1516,6 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
|||
uint8_t redirectCount = 0;
|
||||
chan->GetRedirectCount(&redirectCount);
|
||||
|
||||
nsCOMPtr<nsISupports> cacheKey;
|
||||
chan->GetCacheKey(getter_AddRefs(cacheKey));
|
||||
uint32_t cacheKeyValue = 0;
|
||||
if (cacheKey) {
|
||||
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(cacheKey);
|
||||
if (!container) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
nsresult rv = container->GetData(&cacheKeyValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString altDataType;
|
||||
chan->GetAlternativeDataType(altDataType);
|
||||
int64_t altDataLen = chan->GetAltDataLength();
|
||||
|
||||
// !!! We need to lock headers and please don't forget to unlock them !!!
|
||||
|
@ -1562,7 +1585,10 @@ HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
|
|||
mChannel->GetCacheReadStart(&timing.cacheReadStart);
|
||||
mChannel->GetCacheReadEnd(&timing.cacheReadEnd);
|
||||
|
||||
mChannel->SetWarningReporter(nullptr);
|
||||
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
|
||||
if (httpChannelImpl) {
|
||||
httpChannelImpl->SetWarningReporter(nullptr);
|
||||
}
|
||||
|
||||
// Either IPC channel is closed or background channel
|
||||
// is ready to send OnStopRequest.
|
||||
|
@ -1597,9 +1623,11 @@ HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
|
|||
nsresult channelStatus = NS_OK;
|
||||
mChannel->GetStatus(&channelStatus);
|
||||
|
||||
nsresult transportStatus =
|
||||
(mChannel->IsReadingFromCache()) ? NS_NET_STATUS_READING
|
||||
: NS_NET_STATUS_RECEIVING_FROM;
|
||||
nsresult transportStatus = NS_NET_STATUS_RECEIVING_FROM;
|
||||
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
|
||||
if (httpChannelImpl && httpChannelImpl->IsReadingFromCache()) {
|
||||
transportStatus = NS_NET_STATUS_READING;
|
||||
}
|
||||
|
||||
static uint32_t const kCopyChunkSize = 128 * 1024;
|
||||
uint32_t toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
|
||||
|
@ -1778,8 +1806,40 @@ HttpChannelParent::StartRedirect(uint32_t registrarId,
|
|||
"newChannel=%p callback=%p]\n", this, registrarId, newChannel,
|
||||
callback));
|
||||
|
||||
if (mIPCClosed)
|
||||
if (mIPCClosed) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
// If this is an internal redirect for service worker interception, then
|
||||
// hide it from the child process. The original e10s interception code
|
||||
// was not designed with this in mind and its not necessary to replace
|
||||
// the HttpChannelChild/Parent objects in this case.
|
||||
if (redirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
|
||||
nsCOMPtr<nsIInterceptedChannel> newIntercepted = do_QueryInterface(newChannel);
|
||||
if (newIntercepted) {
|
||||
#ifdef DEBUG
|
||||
// Note, InterceptedHttpChannel can also do an internal redirect
|
||||
// for opaque response interception. This should not actually
|
||||
// happen here in e10s mode.
|
||||
nsCOMPtr<nsIInterceptedChannel> oldIntercepted =
|
||||
do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
|
||||
MOZ_ASSERT(!oldIntercepted);
|
||||
#endif
|
||||
|
||||
// Re-link the HttpChannelParent to the new InterceptedHttpChannel.
|
||||
nsCOMPtr<nsIChannel> linkedChannel;
|
||||
rv = NS_LinkRedirectChannels(registrarId, this, getter_AddRefs(linkedChannel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
MOZ_ASSERT(linkedChannel == newChannel);
|
||||
|
||||
// We immediately store the InterceptedHttpChannel as our nested
|
||||
// mChannel. None of the redirect IPC messaging takes place.
|
||||
mChannel = do_QueryObject(newChannel);
|
||||
|
||||
callback->OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Sending down the original URI, because that is the URI we have
|
||||
// to construct the channel from - this is the URI we've been actually
|
||||
|
@ -1798,7 +1858,7 @@ HttpChannelParent::StartRedirect(uint32_t registrarId,
|
|||
// If the channel is a HTTP channel, we also want to inform the child
|
||||
// about the parent's channelId attribute, so that both parent and child
|
||||
// share the same ID. Useful for monitoring channel activity in devtools.
|
||||
uint64_t channelId;
|
||||
uint64_t channelId = 0;
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
|
||||
if (httpChannel) {
|
||||
rv = httpChannel->GetChannelId(&channelId);
|
||||
|
@ -1839,6 +1899,13 @@ HttpChannelParent::CompleteRedirect(bool succeeded)
|
|||
LOG(("HttpChannelParent::CompleteRedirect [this=%p succeeded=%d]\n",
|
||||
this, succeeded));
|
||||
|
||||
// If this was an internal redirect for a service worker interception then
|
||||
// we will not have a redirecting channel here. Hide this redirect from
|
||||
// the child.
|
||||
if (!mRedirectChannel) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (succeeded && !mIPCClosed) {
|
||||
// TODO: check return value: assume child dead if failed
|
||||
Unused << SendRedirect3Complete();
|
||||
|
@ -1873,7 +1940,9 @@ HttpChannelParent::SuspendForDiversion()
|
|||
|
||||
// MessageDiversionStarted call will suspend mEventQ as many times as the
|
||||
// channel has been suspended, so that channel and this queue are in sync.
|
||||
mChannel->MessageDiversionStarted(this);
|
||||
nsCOMPtr<nsIChannelWithDivertableParentListener> divertChannel =
|
||||
do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
|
||||
divertChannel->MessageDiversionStarted(this);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -1889,7 +1958,7 @@ HttpChannelParent::SuspendForDiversion()
|
|||
// OnDataAvailable until diversion is over. At the same time we should
|
||||
// send the diverted OnDataAvailable-s to the listeners and not queue them
|
||||
// in mEventQ.
|
||||
rv = mChannel->SuspendInternal();
|
||||
rv = divertChannel->SuspendInternal();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) || rv == NS_ERROR_NOT_AVAILABLE);
|
||||
mSuspendedForDiversion = NS_SUCCEEDED(rv);
|
||||
} else {
|
||||
|
@ -1944,11 +2013,13 @@ HttpChannelParent::ResumeForDiversion()
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mChannel->MessageDiversionStop();
|
||||
nsCOMPtr<nsIChannelWithDivertableParentListener> divertChannel =
|
||||
do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
|
||||
divertChannel->MessageDiversionStop();
|
||||
|
||||
if (mSuspendedForDiversion) {
|
||||
// The nsHttpChannel will deliver remaining OnData/OnStop for the transfer.
|
||||
nsresult rv = mChannel->ResumeInternal();
|
||||
nsresult rv = divertChannel->ResumeInternal();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2104,7 +2175,9 @@ HttpChannelParent::NotifyDiversionFailed(nsresult aErrorCode)
|
|||
|
||||
// Resume only if we suspended earlier.
|
||||
if (mSuspendedForDiversion) {
|
||||
mChannel->ResumeInternal();
|
||||
nsCOMPtr<nsIChannelWithDivertableParentListener> divertChannel =
|
||||
do_QueryInterface(static_cast<nsIChannel*>(mChannel.get()));
|
||||
divertChannel->ResumeInternal();
|
||||
}
|
||||
// Channel has already sent OnStartRequest to the child, so ensure that we
|
||||
// call it here if it hasn't already been called.
|
||||
|
|
|
@ -260,7 +260,7 @@ private:
|
|||
friend class DivertStopRequestEvent;
|
||||
friend class DivertCompleteEvent;
|
||||
|
||||
RefPtr<nsHttpChannel> mChannel;
|
||||
RefPtr<HttpBaseChannel> mChannel;
|
||||
nsCOMPtr<nsICacheEntry> mCacheEntry;
|
||||
nsCOMPtr<nsIAssociatedContentSecurity> mAssociatedContentSecurity;
|
||||
bool mIPCClosed; // PHttpChannel actor has been Closed()
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче