зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
805cb19c1d
|
@ -347,8 +347,8 @@ var DownloadsCommon = {
|
|||
}
|
||||
|
||||
if (summary.totalSize != 0) {
|
||||
summary.percentComplete = (summary.totalTransferred /
|
||||
summary.totalSize) * 100;
|
||||
summary.percentComplete =
|
||||
Math.floor((summary.totalTransferred / summary.totalSize) * 100);
|
||||
}
|
||||
|
||||
if (summary.slowestSpeed == Infinity) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 38.0
|
||||
Version 39.0
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-37...release-38
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-38...release-39
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
||||
|
|
|
@ -2837,17 +2837,50 @@ debug-expression-error {
|
|||
padding: 0.5em 1em 0.5em 0.5em;
|
||||
}
|
||||
|
||||
.breakpoints-list .breakpoint {
|
||||
.breakpoints-list .breakpoint-heading,
|
||||
.breakpoints-list .breakpoint,
|
||||
.breakpoints-exceptions {
|
||||
padding: 0.5em 1em 0.5em 0.5em;
|
||||
}
|
||||
|
||||
.breakpoints-exceptions-caught {
|
||||
padding: 0 1em 0.5em 2em;
|
||||
}
|
||||
|
||||
.breakpoints-exceptions-options:not(.empty) {
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
.breakpoints-exceptions input,
|
||||
.breakpoints-exceptions-caught input {
|
||||
padding-inline-start: 2px;
|
||||
margin-inline-start: 0;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.breakpoint-exceptions-label {
|
||||
padding-top: 2px;
|
||||
display: inline-block;
|
||||
padding-inline-start: 2px;
|
||||
padding-inline-end: 8px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.breakpoints-list .breakpoint,
|
||||
.breakpoints-exceptions,
|
||||
.breakpoints-exceptions-caught {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .breakpoints-list .breakpoint,
|
||||
html[dir="rtl"] .breakpoints-list .breakpoint-heading {
|
||||
html[dir="rtl"] .breakpoints-list .breakpoint-heading,
|
||||
html[dir="rtl"] .breakpoints-exceptions {
|
||||
border-right: 4px solid transparent;
|
||||
}
|
||||
|
||||
html:not([dir="rtl"]) .breakpoints-list .breakpoint,
|
||||
html:not([dir="rtl"]) .breakpoints-list .breakpoint-heading {
|
||||
html:not([dir="rtl"]) .breakpoints-list .breakpoint-heading,
|
||||
html:not([dir="rtl"]) .breakpoints-exceptions {
|
||||
border-left: 4px solid transparent;
|
||||
}
|
||||
|
||||
|
@ -2967,7 +3000,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
|||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-line span[role=presentation] {
|
||||
.CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-line span[role="presentation"] {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -3512,23 +3545,6 @@ img.shortcuts {
|
|||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.command-bar > .pause-exceptions.uncaught.enabled > img.pause-exceptions {
|
||||
background-color: var(--theme-highlight-purple);
|
||||
}
|
||||
|
||||
.command-bar > .pause-exceptions.all.enabled > img.pause-exceptions {
|
||||
background-color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.command-bar > .pause-exceptions.enabled > img.pause-exceptions {
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.command-bar img.pause-exceptions {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
|
||||
margin-inline-start: 0.2em;
|
||||
}
|
||||
|
||||
.command-bar .filler {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
@ -3596,149 +3612,6 @@ img.shortcuts {
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.dropdown {
|
||||
--width: 150px;
|
||||
background: var(--theme-body-background);
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
box-shadow: 0 4px 4px 0 var(--search-overlays-semitransparent);
|
||||
max-height: 300px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 23px;
|
||||
width: var(--width);
|
||||
z-index: 1000;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .dropdown {
|
||||
right: calc((var(--width) - 11px) * (-1));
|
||||
}
|
||||
|
||||
.dropdown-block {
|
||||
padding: 0px 2px;
|
||||
position: relative;
|
||||
align-self: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dropdown-button {
|
||||
color: var(--theme-comment);
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-weight: 100;
|
||||
font-size: 14px;
|
||||
height: 100%;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.dropdown li {
|
||||
transition: all 0.25s ease;
|
||||
padding: 2px 10px 10px 5px;
|
||||
overflow: hidden;
|
||||
height: 30px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dropdown li:hover {
|
||||
background-color: var(--search-overlays-semitransparent);
|
||||
}
|
||||
|
||||
.dropdown-icon {
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dropdown-icon.prettyPrint {
|
||||
mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown-icon.blackBox {
|
||||
mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown-icon.file {
|
||||
mask: url("chrome://devtools/skin/images/debugger/file.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
}
|
||||
|
||||
.dropdown ul {
|
||||
list-style: none;
|
||||
line-height: 2em;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dropdown-mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.dropdown span.icon-spacer {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.dropdown li.first {
|
||||
border-bottom: 1px solid var(--theme-toolbar-background-hover);
|
||||
}
|
||||
|
||||
img.pause-next,
|
||||
img.pause-on-exceptions,
|
||||
img.pause-uncaught-exceptions,
|
||||
img.ignore-exceptions {
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dropdown div > img.pause-next {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause.svg") no-repeat;
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.dropdown div > img.ignore-exceptions {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.dropdown div > img.pause-uncaught-exceptions {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
|
||||
background-color: var(--theme-highlight-purple);
|
||||
}
|
||||
|
||||
.dropdown div > img.pause-on-exceptions {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
|
||||
background-color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown div.pause-next.active,
|
||||
.dropdown div.pause-on-exceptions.active,
|
||||
.dropdown div.pause-uncaught-exceptions.active,
|
||||
.dropdown div.ignore-exceptions.active > span.icon-spacer {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.object-node.default-property {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
@ -4070,6 +3943,101 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.dropdown {
|
||||
--width: 150px;
|
||||
background: var(--theme-body-background);
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
box-shadow: 0 4px 4px 0 var(--search-overlays-semitransparent);
|
||||
max-height: 300px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 23px;
|
||||
width: var(--width);
|
||||
z-index: 1000;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .dropdown {
|
||||
right: calc((var(--width) - 11px) * (-1));
|
||||
}
|
||||
|
||||
.dropdown-block {
|
||||
padding: 0px 2px;
|
||||
position: relative;
|
||||
align-self: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dropdown-button {
|
||||
color: var(--theme-comment);
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-weight: 100;
|
||||
font-size: 14px;
|
||||
height: 100%;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.dropdown li {
|
||||
transition: all 0.25s ease;
|
||||
padding: 2px 10px 10px 5px;
|
||||
overflow: hidden;
|
||||
height: 30px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dropdown li:hover {
|
||||
background-color: var(--search-overlays-semitransparent);
|
||||
}
|
||||
|
||||
.dropdown-icon {
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dropdown-icon.prettyPrint {
|
||||
mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown-icon.blackBox {
|
||||
mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown-icon.file {
|
||||
mask: url("chrome://devtools/skin/images/debugger/file.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
}
|
||||
|
||||
.dropdown ul {
|
||||
list-style: none;
|
||||
line-height: 2em;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dropdown-mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.result-list {
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -778,7 +778,7 @@ const {
|
|||
isOriginalId
|
||||
} = __webpack_require__(1389);
|
||||
|
||||
const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1363);
|
||||
const { workerUtils: { WorkerDispatcher } } = __webpack_require__(1390);
|
||||
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
|
||||
|
@ -880,53 +880,81 @@ WorkerDispatcher.prototype = {
|
|||
this.worker = null;
|
||||
},
|
||||
|
||||
task(method) {
|
||||
return (...args) => {
|
||||
task(method, { queue = false } = {}) {
|
||||
const calls = [];
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, args });
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
calls.push([args, resolve, reject]);
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
if (result.error) {
|
||||
reject(result.error);
|
||||
} else {
|
||||
resolve(result.response);
|
||||
}
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, calls: items.map(item => item[0]) });
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const [, resolve, reject] = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
reject(resultData.error);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
}
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const { id, method, args } = msg.data;
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
response.then(val => self.postMessage({ id, response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => self.postMessage({ id, error: err.toString() }));
|
||||
} else {
|
||||
self.postMessage({ id, response });
|
||||
const { id, method, calls } = msg.data;
|
||||
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({ response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => ({ error: err.toString() }));
|
||||
} else {
|
||||
return { response };
|
||||
}
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return { error: error.toString() };
|
||||
}
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
self.postMessage({ id, error: error.toString() });
|
||||
}
|
||||
})).then(results => {
|
||||
self.postMessage({ id, results });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1201,6 +1229,184 @@ module.exports = {
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1390:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const networkRequest = __webpack_require__(1391);
|
||||
const workerUtils = __webpack_require__(1392);
|
||||
|
||||
module.exports = {
|
||||
networkRequest,
|
||||
workerUtils
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1391:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
function networkRequest(url, opts) {
|
||||
return fetch(url, {
|
||||
cache: opts.loadFromCache ? "default" : "no-cache"
|
||||
}).then(res => {
|
||||
if (res.status >= 200 && res.status < 300) {
|
||||
return res.text().then(text => ({ content: text }));
|
||||
}
|
||||
return Promise.reject(`request failed with status ${res.status}`);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = networkRequest;
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1392:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
||||
|
||||
function WorkerDispatcher() {
|
||||
this.msgId = 1;
|
||||
this.worker = null;
|
||||
} /* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
WorkerDispatcher.prototype = {
|
||||
start(url) {
|
||||
this.worker = new Worker(url);
|
||||
this.worker.onerror = () => {
|
||||
console.error(`Error in worker ${url}`);
|
||||
};
|
||||
},
|
||||
|
||||
stop() {
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
},
|
||||
|
||||
task(method) {
|
||||
return (...args) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, args });
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
if (result.error) {
|
||||
reject(result.error);
|
||||
} else {
|
||||
resolve(result.response);
|
||||
}
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const { id, method, args } = msg.data;
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
response.then(val => self.postMessage({ id, response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => self.postMessage({ id, error: err.toString() }));
|
||||
} else {
|
||||
self.postMessage({ id, response });
|
||||
}
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
self.postMessage({ id, error: error.toString() });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function streamingWorkerHandler(publicInterface, { timeout = 100 } = {}, worker = self) {
|
||||
let streamingWorker = (() => {
|
||||
var _ref = _asyncToGenerator(function* (id, tasks) {
|
||||
let isWorking = true;
|
||||
|
||||
const intervalId = setTimeout(function () {
|
||||
isWorking = false;
|
||||
}, timeout);
|
||||
|
||||
const results = [];
|
||||
while (tasks.length !== 0 && isWorking) {
|
||||
const { callback, context, args } = tasks.shift();
|
||||
const result = yield callback.call(context, args);
|
||||
results.push(result);
|
||||
}
|
||||
worker.postMessage({ id, status: "pending", data: results });
|
||||
clearInterval(intervalId);
|
||||
|
||||
if (tasks.length !== 0) {
|
||||
yield streamingWorker(id, tasks);
|
||||
}
|
||||
});
|
||||
|
||||
return function streamingWorker(_x, _x2) {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
return (() => {
|
||||
var _ref2 = _asyncToGenerator(function* (msg) {
|
||||
const { id, method, args } = msg.data;
|
||||
const workerMethod = publicInterface[method];
|
||||
if (!workerMethod) {
|
||||
console.error(`Could not find ${method} defined in worker.`);
|
||||
}
|
||||
worker.postMessage({ id, status: "start" });
|
||||
|
||||
try {
|
||||
const tasks = workerMethod(args);
|
||||
yield streamingWorker(id, tasks);
|
||||
worker.postMessage({ id, status: "done" });
|
||||
} catch (error) {
|
||||
worker.postMessage({ id, status: "error", error });
|
||||
}
|
||||
});
|
||||
|
||||
return function (_x3) {
|
||||
return _ref2.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WorkerDispatcher,
|
||||
workerHandler,
|
||||
streamingWorkerHandler
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 14:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
|
@ -19228,7 +19434,8 @@ function parseSourceScopes(sourceId) {
|
|||
freeVariables: new Map(),
|
||||
freeVariableStack: [],
|
||||
scope: lexical,
|
||||
scopeStack: []
|
||||
scopeStack: [],
|
||||
declarationBindingIds: new Set()
|
||||
};
|
||||
t.traverse(ast, scopeCollectionVisitor, state);
|
||||
|
||||
|
@ -19255,7 +19462,7 @@ function parseSourceScopes(sourceId) {
|
|||
return toParsedScopes([global], sourceId) || [];
|
||||
} /* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
function toParsedScopes(children, sourceId) {
|
||||
if (!children || children.length === 0) {
|
||||
|
@ -19322,7 +19529,7 @@ function fromBabelLocation(location, sourceId) {
|
|||
};
|
||||
}
|
||||
|
||||
function parseDeclarator(declaratorId, targetScope, type, declaration, sourceId) {
|
||||
function parseDeclarator(declaratorId, targetScope, type, declaration, state) {
|
||||
if (isNode(declaratorId, "Identifier")) {
|
||||
let existing = targetScope.bindings[declaratorId.name];
|
||||
if (!existing) {
|
||||
|
@ -19332,27 +19539,28 @@ function parseDeclarator(declaratorId, targetScope, type, declaration, sourceId)
|
|||
};
|
||||
targetScope.bindings[declaratorId.name] = existing;
|
||||
}
|
||||
state.declarationBindingIds.add(declaratorId);
|
||||
existing.refs.push({
|
||||
type: "decl",
|
||||
start: fromBabelLocation(declaratorId.loc.start, sourceId),
|
||||
end: fromBabelLocation(declaratorId.loc.end, sourceId),
|
||||
start: fromBabelLocation(declaratorId.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(declaratorId.loc.end, state.sourceId),
|
||||
declaration: {
|
||||
start: fromBabelLocation(declaration.loc.start, sourceId),
|
||||
end: fromBabelLocation(declaration.loc.end, sourceId)
|
||||
start: fromBabelLocation(declaration.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(declaration.loc.end, state.sourceId)
|
||||
}
|
||||
});
|
||||
} else if (isNode(declaratorId, "ObjectPattern")) {
|
||||
declaratorId.properties.forEach(prop => {
|
||||
parseDeclarator(prop.value, targetScope, type, declaration, sourceId);
|
||||
parseDeclarator(prop.value, targetScope, type, declaration, state);
|
||||
});
|
||||
} else if (isNode(declaratorId, "ArrayPattern")) {
|
||||
declaratorId.elements.forEach(item => {
|
||||
parseDeclarator(item, targetScope, type, declaration, sourceId);
|
||||
parseDeclarator(item, targetScope, type, declaration, state);
|
||||
});
|
||||
} else if (isNode(declaratorId, "AssignmentPattern")) {
|
||||
parseDeclarator(declaratorId.left, targetScope, type, declaration, sourceId);
|
||||
parseDeclarator(declaratorId.left, targetScope, type, declaration, state);
|
||||
} else if (isNode(declaratorId, "RestElement")) {
|
||||
parseDeclarator(declaratorId.argument, targetScope, type, declaration, sourceId);
|
||||
parseDeclarator(declaratorId.argument, targetScope, type, declaration, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19409,6 +19617,7 @@ const scopeCollectionVisitor = {
|
|||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
});
|
||||
state.declarationBindingIds.add(node.id);
|
||||
scope.bindings[node.id.name] = {
|
||||
type: "const",
|
||||
refs: [{
|
||||
|
@ -19426,6 +19635,7 @@ const scopeCollectionVisitor = {
|
|||
if (t.isFunctionDeclaration(node) && isNode(node.id, "Identifier")) {
|
||||
// This ignores Annex B function declaration hoisting, which
|
||||
// is probably a fine assumption.
|
||||
state.declarationBindingIds.add(node.id);
|
||||
const fnScope = getVarScope(scope);
|
||||
scope.bindings[node.id.name] = {
|
||||
type: fnScope === scope ? "var" : "let",
|
||||
|
@ -19448,7 +19658,7 @@ const scopeCollectionVisitor = {
|
|||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
});
|
||||
|
||||
node.params.forEach(param => parseDeclarator(param, scope, "var", node, state.sourceId));
|
||||
node.params.forEach(param => parseDeclarator(param, scope, "var", node, state));
|
||||
|
||||
if (!t.isArrowFunctionExpression(node)) {
|
||||
scope.bindings.this = {
|
||||
|
@ -19462,6 +19672,7 @@ const scopeCollectionVisitor = {
|
|||
}
|
||||
} else if (t.isClass(node)) {
|
||||
if (t.isClassDeclaration(node) && t.isIdentifier(node.id)) {
|
||||
state.declarationBindingIds.add(node.id);
|
||||
state.scope.bindings[node.id.name] = {
|
||||
type: "let",
|
||||
refs: [{
|
||||
|
@ -19482,6 +19693,7 @@ const scopeCollectionVisitor = {
|
|||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
});
|
||||
|
||||
state.declarationBindingIds.add(node.id);
|
||||
scope.bindings[node.id.name] = {
|
||||
type: "const",
|
||||
refs: [{
|
||||
|
@ -19511,7 +19723,7 @@ const scopeCollectionVisitor = {
|
|||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
});
|
||||
parseDeclarator(node.param, scope, "var", node, state.sourceId);
|
||||
parseDeclarator(node.param, scope, "var", node, state);
|
||||
} else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) {
|
||||
// Debugger will create new lexical environment for the block.
|
||||
pushTempScope(state, "block", "Block", {
|
||||
|
@ -19524,11 +19736,13 @@ const scopeCollectionVisitor = {
|
|||
// Finds right lexical environment
|
||||
const hoistAt = !isLetOrConst(node) ? getVarScope(state.scope) : state.scope;
|
||||
node.declarations.forEach(declarator => {
|
||||
parseDeclarator(declarator.id, hoistAt, node.kind, node, state.sourceId);
|
||||
parseDeclarator(declarator.id, hoistAt, node.kind, node, state);
|
||||
});
|
||||
} else if (t.isImportDeclaration(node) && (!node.importKind || node.importKind === "value")) {
|
||||
node.specifiers.forEach(spec => {
|
||||
if (t.isImportNamespaceSpecifier(spec)) {
|
||||
state.declarationBindingIds.add(spec.local);
|
||||
|
||||
state.scope.bindings[spec.local.name] = {
|
||||
// Imported namespaces aren't live import bindings, they are
|
||||
// just normal const bindings.
|
||||
|
@ -19536,10 +19750,16 @@ const scopeCollectionVisitor = {
|
|||
refs: [{
|
||||
type: "decl",
|
||||
start: fromBabelLocation(spec.local.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(spec.local.loc.end, state.sourceId)
|
||||
end: fromBabelLocation(spec.local.loc.end, state.sourceId),
|
||||
declaration: {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
}
|
||||
}]
|
||||
};
|
||||
} else {
|
||||
state.declarationBindingIds.add(spec.local);
|
||||
|
||||
state.scope.bindings[spec.local.name] = {
|
||||
type: "import",
|
||||
refs: [{
|
||||
|
@ -19556,6 +19776,7 @@ const scopeCollectionVisitor = {
|
|||
}
|
||||
});
|
||||
} else if (t.isTSEnumDeclaration(node)) {
|
||||
state.declarationBindingIds.add(node.id);
|
||||
state.scope.bindings[node.id.name] = {
|
||||
type: "const",
|
||||
refs: [{
|
||||
|
@ -19571,7 +19792,11 @@ const scopeCollectionVisitor = {
|
|||
} else if (t.isIdentifier(node) && t.isReferenced(node, parentNode) &&
|
||||
// Babel doesn't cover this in 'isReferenced' yet, but it should
|
||||
// eventually.
|
||||
!t.isTSEnumMember(parentNode, { id: node })) {
|
||||
!t.isTSEnumMember(parentNode, { id: node }) &&
|
||||
// isReferenced above fails to see `var { foo } = ...` as a non-reference
|
||||
// because the direct parent is not enough to know that the pattern is
|
||||
// used within a variable declaration.
|
||||
!state.declarationBindingIds.has(node)) {
|
||||
let freeVariables = state.freeVariables.get(node.name);
|
||||
if (!freeVariables) {
|
||||
freeVariables = [];
|
||||
|
|
|
@ -151,53 +151,81 @@ WorkerDispatcher.prototype = {
|
|||
this.worker = null;
|
||||
},
|
||||
|
||||
task(method) {
|
||||
return (...args) => {
|
||||
task(method, { queue = false } = {}) {
|
||||
const calls = [];
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, args });
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
calls.push([args, resolve, reject]);
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
if (result.error) {
|
||||
reject(result.error);
|
||||
} else {
|
||||
resolve(result.response);
|
||||
}
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, calls: items.map(item => item[0]) });
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const [, resolve, reject] = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
reject(resultData.error);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
}
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const { id, method, args } = msg.data;
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
response.then(val => self.postMessage({ id, response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => self.postMessage({ id, error: err.toString() }));
|
||||
} else {
|
||||
self.postMessage({ id, response });
|
||||
const { id, method, calls } = msg.data;
|
||||
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({ response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => ({ error: err.toString() }));
|
||||
} else {
|
||||
return { response };
|
||||
}
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return { error: error.toString() };
|
||||
}
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
self.postMessage({ id, error: error.toString() });
|
||||
}
|
||||
})).then(results => {
|
||||
self.postMessage({ id, results });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -340,53 +340,81 @@ WorkerDispatcher.prototype = {
|
|||
this.worker = null;
|
||||
},
|
||||
|
||||
task(method) {
|
||||
return (...args) => {
|
||||
task(method, { queue = false } = {}) {
|
||||
const calls = [];
|
||||
const push = args => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, args });
|
||||
if (queue && calls.length === 0) {
|
||||
Promise.resolve().then(flush);
|
||||
}
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
calls.push([args, resolve, reject]);
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
if (result.error) {
|
||||
reject(result.error);
|
||||
} else {
|
||||
resolve(result.response);
|
||||
}
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
if (!queue) {
|
||||
flush();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
const items = calls.slice();
|
||||
calls.length = 0;
|
||||
|
||||
const id = this.msgId++;
|
||||
this.worker.postMessage({ id, method, calls: items.map(item => item[0]) });
|
||||
|
||||
const listener = ({ data: result }) => {
|
||||
if (result.id !== id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.worker) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.worker.removeEventListener("message", listener);
|
||||
|
||||
result.results.forEach((resultData, i) => {
|
||||
const [, resolve, reject] = items[i];
|
||||
|
||||
if (resultData.error) {
|
||||
reject(resultData.error);
|
||||
} else {
|
||||
resolve(resultData.response);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.worker.addEventListener("message", listener);
|
||||
};
|
||||
|
||||
return (...args) => push(args);
|
||||
}
|
||||
};
|
||||
|
||||
function workerHandler(publicInterface) {
|
||||
return function (msg) {
|
||||
const { id, method, args } = msg.data;
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
response.then(val => self.postMessage({ id, response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => self.postMessage({ id, error: err.toString() }));
|
||||
} else {
|
||||
self.postMessage({ id, response });
|
||||
const { id, method, calls } = msg.data;
|
||||
|
||||
Promise.all(calls.map(args => {
|
||||
try {
|
||||
const response = publicInterface[method].apply(undefined, args);
|
||||
if (response instanceof Promise) {
|
||||
return response.then(val => ({ response: val }),
|
||||
// Error can't be sent via postMessage, so be sure to
|
||||
// convert to string.
|
||||
err => ({ error: err.toString() }));
|
||||
} else {
|
||||
return { response };
|
||||
}
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
return { error: error.toString() };
|
||||
}
|
||||
} catch (error) {
|
||||
// Error can't be sent via postMessage, so be sure to convert to
|
||||
// string.
|
||||
self.postMessage({ id, error: error.toString() });
|
||||
}
|
||||
})).then(results => {
|
||||
self.postMessage({ id, results });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ support-files =
|
|||
examples/babel/fixtures/eval-source-maps/output.js.map
|
||||
examples/babel/fixtures/for-of/output.js
|
||||
examples/babel/fixtures/for-of/output.js.map
|
||||
examples/babel/fixtures/line-start-bindings-es6/output.js
|
||||
examples/babel/fixtures/line-start-bindings-es6/output.js.map
|
||||
examples/babel/fixtures/shadowed-vars/output.js
|
||||
examples/babel/fixtures/shadowed-vars/output.js.map
|
||||
examples/babel/fixtures/this-arguments-bindings/output.js
|
||||
|
|
|
@ -61,6 +61,22 @@ add_task(async function() {
|
|||
["aVar", '"var3"']
|
||||
]);
|
||||
|
||||
await breakpointScopes(
|
||||
dbg,
|
||||
"line-start-bindings-es6",
|
||||
{ line: 19, column: 4 },
|
||||
[
|
||||
"Block",
|
||||
["<this>", '{\u2026}'],
|
||||
["one", "1"],
|
||||
["two", "2"],
|
||||
"root",
|
||||
["aFunc", "(optimized away)"],
|
||||
"Module",
|
||||
"root()"
|
||||
]
|
||||
);
|
||||
|
||||
await breakpointScopes(
|
||||
dbg,
|
||||
"this-arguments-bindings",
|
||||
|
@ -87,7 +103,7 @@ add_task(async function() {
|
|||
{ line: 8, column: 6 },
|
||||
[
|
||||
"arrow",
|
||||
["argArrow", "(unmapped)"],
|
||||
["argArrow", "(optimized away)"],
|
||||
"Block",
|
||||
"arrow()",
|
||||
"fn",
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
export default function root() {
|
||||
function aFunc(){
|
||||
// Since these bindings are on their own linem, the mappings will
|
||||
// extend to the start of the line, rather than starting at the first
|
||||
// character of the binding.
|
||||
const {
|
||||
one,
|
||||
two
|
||||
} = {
|
||||
one: 1,
|
||||
two: 2,
|
||||
};
|
||||
|
||||
// The 'this' binding here is also its own line, so the comment above
|
||||
// applies here too.
|
||||
this.thing = 4;
|
||||
|
||||
console.log("pause here");
|
||||
}
|
||||
|
||||
aFunc.call({ });
|
||||
}
|
||||
|
||||
|
||||
// The build harness sets the wrong global, so just override it.
|
||||
Promise.resolve().then(() => {
|
||||
window.lineStartBindingsEs6 = root;
|
||||
});
|
|
@ -0,0 +1,105 @@
|
|||
var lineStartBindingsEs6 =
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
/* harmony export (immutable) */ __webpack_exports__["default"] = root;
|
||||
|
||||
function root() {
|
||||
function aFunc() {
|
||||
// Since these bindings are on their own linem, the mappings will
|
||||
// extend to the start of the line, rather than starting at the first
|
||||
// character of the binding.
|
||||
const {
|
||||
one,
|
||||
two
|
||||
} = {
|
||||
one: 1,
|
||||
two: 2
|
||||
};
|
||||
|
||||
// The 'this' binding here is also its own line, so the comment above
|
||||
// applies here too.
|
||||
this.thing = 4;
|
||||
|
||||
console.log("pause here");
|
||||
}
|
||||
|
||||
aFunc.call({});
|
||||
}
|
||||
|
||||
// The build harness sets the wrong global, so just override it.
|
||||
Promise.resolve().then(() => {
|
||||
window.lineStartBindingsEs6 = root;
|
||||
});
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
//# sourceMappingURL=output.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack:///webpack/bootstrap 3fee9e40469b3fb786b0","webpack:///./fixtures/line-start-bindings-es6/input.js"],"names":["root","aFunc","one","two","thing","console","log","call","Promise","resolve","then","window","lineStartBindingsEs6"],"mappings":";;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;;;;AC5De,SAASA,IAAT,GAAgB;AAC7B,WAASC,KAAT,GAAgB;AACd;AACA;AACA;AACA,UAAM;AACJC,SADI;AAEJC;AAFI,QAGF;AACFD,WAAK,CADH;AAEFC,WAAK;AAFH,KAHJ;;AAQA;AACA;AACA,SAAKC,KAAL,GAAa,CAAb;;AAEAC,YAAQC,GAAR,CAAY,YAAZ;AACD;;AAEDL,QAAMM,IAAN,CAAW,EAAX;AACD;;AAGD;AACAC,QAAQC,OAAR,GAAkBC,IAAlB,CAAuB,MAAM;AAC3BC,SAAOC,oBAAP,GAA8BZ,IAA9B;AACD,CAFD,E","file":"fixtures/line-start-bindings-es6/output.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 3fee9e40469b3fb786b0","\nexport default function root() {\n function aFunc(){\n // Since these bindings are on their own linem, the mappings will\n // extend to the start of the line, rather than starting at the first\n // character of the binding.\n const {\n one,\n two\n } = {\n one: 1,\n two: 2,\n };\n\n // The 'this' binding here is also its own line, so the comment above\n // applies here too.\n this.thing = 4;\n\n console.log(\"pause here\");\n }\n\n aFunc.call({ });\n}\n\n\n// The build harness sets the wrong global, so just override it.\nPromise.resolve().then(() => {\n window.lineStartBindingsEs6 = root;\n});\n\n\n\n// WEBPACK FOOTER //\n// ./fixtures/line-start-bindings-es6/input.js"],"sourceRoot":""}
|
|
@ -49,7 +49,7 @@ module.exports = [
|
|||
].concat(
|
||||
tests.map(({ name, dirname, input, output }) => {
|
||||
const babelEnabled = name !== "webpackStandalone";
|
||||
const babelEnv = name !== "webpackModulesEs6";
|
||||
const babelEnv = !name.match(/Es6/);
|
||||
const babelModules = name !== "webpackModules";
|
||||
const devtool =
|
||||
name === "evalSourceMaps" ? "eval-source-map" : "source-map";
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
<button onclick="functions()">Run functions</button>
|
||||
<script src="babel/fixtures/imported-bindings/output.js"></script>
|
||||
<button onclick="importedBindings()">Run importedBindings</button>
|
||||
<script src="babel/fixtures/line-start-bindings-es6/output.js"></script>
|
||||
<button onclick="lineStartBindingsEs6()">Run lineStartBindingsEs6</button>
|
||||
<script src="babel/fixtures/modules/output.js"></script>
|
||||
<button onclick="modules()">Run modules</button>
|
||||
<script src="babel/fixtures/non-modules/output.js"></script>
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
### Building
|
||||
|
||||
* `ember build`
|
|
@ -1,14 +0,0 @@
|
|||
import Application from '@ember/application';
|
||||
import Resolver from './resolver';
|
||||
import loadInitializers from 'ember-load-initializers';
|
||||
import config from './config/environment';
|
||||
|
||||
const App = Application.extend({
|
||||
modulePrefix: config.modulePrefix,
|
||||
podModulePrefix: config.podModulePrefix,
|
||||
Resolver
|
||||
});
|
||||
|
||||
loadInitializers(App, config.modulePrefix);
|
||||
|
||||
export default App;
|
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Quickstart</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link integrity="" rel="stylesheet" href="{{rootURL}}assets/quickstart.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/quickstart.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +0,0 @@
|
|||
import Resolver from 'ember-resolver';
|
||||
|
||||
export default Resolver;
|
|
@ -1,16 +0,0 @@
|
|||
import EmberRouter from '@ember/routing/router';
|
||||
import config from './config/environment';
|
||||
|
||||
const Router = EmberRouter.extend({
|
||||
location: config.locationType,
|
||||
rootURL: config.rootURL
|
||||
});
|
||||
|
||||
Router.map(function() {
|
||||
});
|
||||
|
||||
window.mapTestFunction = () => {
|
||||
window.console.log("pause here", config, Router);
|
||||
};
|
||||
|
||||
export default Router;
|
|
@ -1,5 +0,0 @@
|
|||
{{!-- The following component displays Ember's default welcome message. --}}
|
||||
{{welcome-page}}
|
||||
{{!-- Feel free to remove this! --}}
|
||||
|
||||
{{outlet}}
|
|
@ -1,58 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = function(environment) {
|
||||
let ENV = {
|
||||
modulePrefix: 'quickstart',
|
||||
environment,
|
||||
locationType: 'auto',
|
||||
EmberENV: {
|
||||
FEATURES: {
|
||||
// Here you can enable experimental features on an ember canary build
|
||||
// e.g. 'with-controller': true
|
||||
},
|
||||
EXTEND_PROTOTYPES: {
|
||||
// Prevent Ember Data from overriding Date.parse.
|
||||
Date: false
|
||||
}
|
||||
},
|
||||
|
||||
APP: {
|
||||
// Here you can pass flags/options to your application instance
|
||||
// when it is created
|
||||
},
|
||||
|
||||
// NOTE(logan): Hard-code the URL for the debugger example to allow it to
|
||||
// function properly. The default "/" root makes assets fail to load.
|
||||
rootURL: "/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/",
|
||||
|
||||
// If using "http://localhost:8000/integration/examples/ember/quickstart/dist/" to
|
||||
// access this test example, uncomment this line and re-run "yarn build".
|
||||
// rootURL: "/integration/examples/ember/quickstart/dist/",
|
||||
};
|
||||
|
||||
if (environment === 'development') {
|
||||
// ENV.APP.LOG_RESOLVER = true;
|
||||
// ENV.APP.LOG_ACTIVE_GENERATION = true;
|
||||
// ENV.APP.LOG_TRANSITIONS = true;
|
||||
// ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
|
||||
// ENV.APP.LOG_VIEW_LOOKUPS = true;
|
||||
}
|
||||
|
||||
if (environment === 'test') {
|
||||
// Testem prefers this...
|
||||
ENV.locationType = 'none';
|
||||
|
||||
// keep test console output quieter
|
||||
ENV.APP.LOG_ACTIVE_GENERATION = false;
|
||||
ENV.APP.LOG_VIEW_LOOKUPS = false;
|
||||
|
||||
ENV.APP.rootElement = '#ember-testing';
|
||||
ENV.APP.autoboot = false;
|
||||
}
|
||||
|
||||
if (environment === 'production') {
|
||||
// here you can enable a production-specific feature
|
||||
}
|
||||
|
||||
return ENV;
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const browsers = [
|
||||
'last 1 Chrome versions',
|
||||
'last 1 Firefox versions',
|
||||
'last 1 Safari versions'
|
||||
];
|
||||
|
||||
const isCI = !!process.env.CI;
|
||||
const isProduction = process.env.EMBER_ENV === 'production';
|
||||
|
||||
if (isCI || isProduction) {
|
||||
browsers.push('ie 11');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
browsers
|
||||
};
|
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 89 KiB |
|
@ -1,39 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Quickstart Tests</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
|
||||
<meta name="quickstart/config/environment" content="%7B%22modulePrefix%22%3A%22quickstart%22%2C%22environment%22%3A%22test%22%2C%22locationType%22%3A%22none%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%7D%7D%2C%22APP%22%3A%7B%22LOG_ACTIVE_GENERATION%22%3Afalse%2C%22LOG_VIEW_LOOKUPS%22%3Afalse%2C%22rootElement%22%3A%22%23ember-testing%22%2C%22autoboot%22%3Afalse%2C%22name%22%3A%22quickstart%22%2C%22version%22%3A%220.0.0+1dde1d7f%22%7D%2C%22rootURL%22%3A%22/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/%22%2C%22exportApplicationGlobal%22%3Atrue%7D" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/assets/vendor.css">
|
||||
<link rel="stylesheet" href="/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/assets/quickstart.css">
|
||||
<link rel="stylesheet" href="/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/assets/test-support.css">
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
|
||||
<div id="ember-testing-container">
|
||||
<div id="ember-testing"></div>
|
||||
</div>
|
||||
|
||||
<script src="/testem.js" integrity=""></script>
|
||||
<script src="/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/assets/vendor.js"></script>
|
||||
<script src="/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/assets/test-support.js"></script>
|
||||
<script src="/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/assets/quickstart.js"></script>
|
||||
<script src="/browser/devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/dist/assets/tests.js"></script>
|
||||
|
||||
|
||||
<script>Ember.assert('The tests file was not loaded. Make sure your tests index.html includes "assets/tests.js".', EmberENV.TESTS_FILE_LOADED);</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,32 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
|
||||
|
||||
module.exports = function(defaults) {
|
||||
// debugger;
|
||||
let app = new EmberApp(defaults, {
|
||||
// Add options here
|
||||
sourcemaps: { enabled: true },
|
||||
babel: {
|
||||
sourceMaps: "inline",
|
||||
},
|
||||
'ember-babel-cli': {
|
||||
sourceMaps: "inline",
|
||||
}
|
||||
});
|
||||
|
||||
// Use `app.import` to add additional libraries to the generated
|
||||
// output files.
|
||||
//
|
||||
// If you need to use different assets in different
|
||||
// environments, specify an object as the first parameter. That
|
||||
// object's keys should be the environment name and the values
|
||||
// should be the asset to use in that environment.
|
||||
//
|
||||
// If the library that you are including contains AMD or ES6
|
||||
// modules that you would like to import into your application
|
||||
// please specify an object with the list of modules as keys
|
||||
// along with the exports of each module as its value.
|
||||
|
||||
return app.toTree();
|
||||
};
|
10513
devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/package-lock.json
сгенерированный
10513
devtools/client/debugger/new/test/mochitest/examples/ember/quickstart/package-lock.json
сгенерированный
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,47 +0,0 @@
|
|||
{
|
||||
"name": "quickstart",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"description": "Small description for quickstart goes here",
|
||||
"license": "MIT",
|
||||
"author": "",
|
||||
"directories": {
|
||||
"doc": "doc",
|
||||
"test": "tests"
|
||||
},
|
||||
"repository": "",
|
||||
"scripts": {
|
||||
"build": "ember build",
|
||||
"lint:js": "eslint ./*.js app config lib server tests",
|
||||
"start": "ember serve",
|
||||
"test": "ember test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"broccoli-asset-rev": "^2.4.5",
|
||||
"ember-ajax": "^3.0.0",
|
||||
"ember-cli": "~3.0.2",
|
||||
"ember-cli-app-version": "^3.0.0",
|
||||
"ember-cli-babel": "^6.6.0",
|
||||
"ember-cli-dependency-checker": "^2.0.0",
|
||||
"ember-cli-eslint": "^4.2.1",
|
||||
"ember-cli-htmlbars": "^2.0.1",
|
||||
"ember-cli-htmlbars-inline-precompile": "^1.0.0",
|
||||
"ember-cli-inject-live-reload": "^1.4.1",
|
||||
"ember-cli-qunit": "^4.1.1",
|
||||
"ember-cli-shims": "^1.2.0",
|
||||
"ember-cli-sri": "^2.1.0",
|
||||
"ember-cli-uglify": "^2.0.0",
|
||||
"ember-data": "~3.0.0",
|
||||
"ember-export-application-global": "^2.0.0",
|
||||
"ember-load-initializers": "^1.0.0",
|
||||
"ember-maybe-import-regenerator": "^0.1.6",
|
||||
"ember-resolver": "^4.0.0",
|
||||
"ember-source": "~3.0.0",
|
||||
"ember-welcome-page": "^3.0.0",
|
||||
"eslint-plugin-ember": "^5.0.0",
|
||||
"loader.js": "^4.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^4.5 || 6.* || >= 7.*"
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
# http://www.robotstxt.org
|
||||
User-agent: *
|
||||
Disallow:
|
|
@ -1,24 +0,0 @@
|
|||
module.exports = {
|
||||
test_page: 'tests/index.html?hidepassed',
|
||||
disable_watching: true,
|
||||
launch_in_ci: [
|
||||
'Chrome'
|
||||
],
|
||||
launch_in_dev: [
|
||||
'Chrome'
|
||||
],
|
||||
browser_args: {
|
||||
Chrome: {
|
||||
mode: 'ci',
|
||||
args: [
|
||||
// --no-sandbox is needed when running Chrome inside a container
|
||||
process.env.TRAVIS ? '--no-sandbox' : null,
|
||||
|
||||
'--disable-gpu',
|
||||
'--headless',
|
||||
'--remote-debugging-port=0',
|
||||
'--window-size=1440,900'
|
||||
].filter(Boolean)
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,33 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Quickstart Tests</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{{content-for "head"}}
|
||||
{{content-for "test-head"}}
|
||||
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/vendor.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/quickstart.css">
|
||||
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css">
|
||||
|
||||
{{content-for "head-footer"}}
|
||||
{{content-for "test-head-footer"}}
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
{{content-for "test-body"}}
|
||||
|
||||
<script src="/testem.js" integrity=""></script>
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/test-support.js"></script>
|
||||
<script src="{{rootURL}}assets/quickstart.js"></script>
|
||||
<script src="{{rootURL}}assets/tests.js"></script>
|
||||
|
||||
{{content-for "body-footer"}}
|
||||
{{content-for "test-body-footer"}}
|
||||
</body>
|
||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||
import Application from '../app';
|
||||
import config from '../config/environment';
|
||||
import { setApplication } from '@ember/test-helpers';
|
||||
import { start } from 'ember-qunit';
|
||||
|
||||
setApplication(Application.create(config.APP));
|
||||
|
||||
start();
|
|
@ -277,7 +277,6 @@ devtools.jar:
|
|||
skin/images/debugger/folder.svg (themes/images/debugger/folder.svg)
|
||||
skin/images/debugger/forward.svg (themes/images/debugger/forward.svg)
|
||||
skin/images/debugger/javascript.svg (themes/images/debugger/javascript.svg)
|
||||
skin/images/debugger/pause-exceptions.svg (themes/images/debugger/pause-exceptions.svg)
|
||||
skin/images/debugger/pause.svg (themes/images/debugger/pause.svg)
|
||||
skin/images/debugger/prettyPrint.svg (themes/images/debugger/prettyPrint.svg)
|
||||
skin/images/debugger/react.svg (themes/images/debugger/react.svg)
|
||||
|
|
|
@ -93,9 +93,13 @@ ignoreExceptionsItem=Ignore exceptions
|
|||
# item shown when a user is adding a new breakpoint.
|
||||
pauseOnUncaughtExceptionsItem=Pause on uncaught exceptions
|
||||
|
||||
# LOCALIZATION NOTE (pauseOnExceptionsItem): The pause on exceptions button description
|
||||
# LOCALIZATION NOTE (pauseOnExceptionsItem2): The pause on exceptions checkbox description
|
||||
# when the debugger will pause on all exceptions.
|
||||
pauseOnExceptionsItem=Pause on all exceptions
|
||||
pauseOnExceptionsItem2=Pause on exceptions
|
||||
|
||||
# LOCALIZATION NOTE (ignoreCaughtExceptionsItem): The pause on exceptions checkbox description
|
||||
# when the debugger will not pause on any caught exception
|
||||
ignoreCaughtExceptionsItem=Ignore caught exceptions
|
||||
|
||||
# LOCALIZATION NOTE (workersHeader): The text to display in the events
|
||||
# header.
|
||||
|
|
|
@ -52,7 +52,6 @@ pref("devtools.debugger.features.root", true);
|
|||
pref("devtools.debugger.features.column-breakpoints", false);
|
||||
pref("devtools.debugger.features.chrome-scopes", false);
|
||||
pref("devtools.debugger.features.map-scopes", true);
|
||||
pref("devtools.debugger.features.breakpoints-dropdown", false);
|
||||
pref("devtools.debugger.features.remove-command-bar-options", false);
|
||||
pref("devtools.debugger.features.workers", true);
|
||||
pref("devtools.debugger.features.code-coverage", false);
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.483 13.995H5.517l-3.512-3.512V5.516l3.512-3.512h4.966l3.512 3.512v4.967l-3.512 3.512zm4.37-9.042l-3.807-3.805A.503.503 0 0 0 10.691 1H5.309a.503.503 0 0 0-.356.148L1.147 4.953A.502.502 0 0 0 1 5.308v5.383c0 .134.053.262.147.356l3.806 3.806a.503.503 0 0 0 .356.147h5.382a.503.503 0 0 0 .355-.147l3.806-3.806A.502.502 0 0 0 15 10.69V5.308a.502.502 0 0 0-.147-.355z"/>
|
||||
<path d="M10 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 1 0-1 0v5zM5 10.5a.5.5 0 1 0 1 0v-5a.5.5 0 0 0-1 0v5z"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 786 B |
|
@ -395,8 +395,6 @@ nsFrameLoader::FireWillChangeProcessEvent()
|
|||
return nullptr;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
GlobalObject global(cx, mOwnerContent->GetOwnerGlobal()->GetGlobalJSObject());
|
||||
MOZ_ASSERT(!global.Failed());
|
||||
|
||||
// Set our mBrowserChangingProcessBlockers property to refer to the blockers
|
||||
// list. We will synchronously dispatch a DOM event to collect this list of
|
||||
|
@ -418,7 +416,7 @@ nsFrameLoader::FireWillChangeProcessEvent()
|
|||
mBrowserChangingProcessBlockers = nullptr;
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> allPromise = Promise::All(global, blockers, rv);
|
||||
RefPtr<Promise> allPromise = Promise::All(cx, blockers, rv);
|
||||
return allPromise.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -1226,7 +1226,10 @@ nsGlobalWindowInner::FreeInnerObjects()
|
|||
mApplicationCache = nullptr;
|
||||
}
|
||||
|
||||
mIndexedDB = nullptr;
|
||||
if (mIndexedDB) {
|
||||
mIndexedDB->DisconnectFromWindow(this);
|
||||
mIndexedDB = nullptr;
|
||||
}
|
||||
|
||||
UnlinkHostObjectURIs();
|
||||
|
||||
|
@ -1520,7 +1523,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
|
|||
static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
|
||||
if (tmp->mIndexedDB) {
|
||||
tmp->mIndexedDB->DisconnectFromWindow(tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
|
||||
|
@ -2469,6 +2475,32 @@ nsGlobalWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& a
|
|||
mClientSource->NoteCalledRegisterForServiceWorkerScope(aScope);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::MigrateStateForDocumentOpen(nsGlobalWindowInner* aOldInner)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aOldInner);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aOldInner != this);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mDoc);
|
||||
|
||||
// Rebind DETH objects to the new global created by document.open().
|
||||
// XXX: Is this correct? We should consider if the spec and our
|
||||
// implementation should change to match other browsers by
|
||||
// just reusing the current window. (Bug 1449992)
|
||||
aOldInner->ForEachEventTargetObject(
|
||||
[&] (DOMEventTargetHelper* aDETH, bool* aDoneOut) {
|
||||
aDETH->BindToOwner(this->AsInner());
|
||||
});
|
||||
|
||||
// Move the old Performance object from the old window to the new window.
|
||||
// The Performance object was also rebound in the DETH loop above.
|
||||
mPerformance = aOldInner->mPerformance.forget();
|
||||
|
||||
if (aOldInner->mIndexedDB) {
|
||||
aOldInner->mIndexedDB->RebindToNewWindow(this);
|
||||
mIndexedDB = aOldInner->mIndexedDB.forget();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::UpdateTopInnerWindow()
|
||||
{
|
||||
|
|
|
@ -1151,6 +1151,8 @@ private:
|
|||
CallState ShouldReportForServiceWorkerScopeInternal(const nsACString& aScope,
|
||||
bool* aResultOut);
|
||||
|
||||
void
|
||||
MigrateStateForDocumentOpen(nsGlobalWindowInner* aOldInner);
|
||||
|
||||
public:
|
||||
// Timeout Functions
|
||||
|
|
|
@ -1721,7 +1721,7 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
|
|||
|
||||
mContext->WillInitializeContext();
|
||||
|
||||
nsGlobalWindowInner *currentInner = GetCurrentInnerWindowInternal();
|
||||
RefPtr<nsGlobalWindowInner> currentInner = GetCurrentInnerWindowInternal();
|
||||
|
||||
if (currentInner && currentInner->mNavigator) {
|
||||
currentInner->mNavigator->OnNavigation();
|
||||
|
@ -1735,6 +1735,9 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
|
|||
nsCOMPtr<WindowStateHolder> wsh = do_QueryInterface(aState);
|
||||
NS_ASSERTION(!aState || wsh, "What kind of weird state are you giving me here?");
|
||||
|
||||
bool handleDocumentOpen = false;
|
||||
bool doomCurrentInner = false;
|
||||
|
||||
JS::Rooted<JSObject*> newInnerGlobal(cx);
|
||||
if (reUseInnerWindow) {
|
||||
// We're reusing the current inner window.
|
||||
|
@ -1818,32 +1821,13 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
|
|||
|
||||
if (currentInner && currentInner->GetWrapperPreserveColor()) {
|
||||
if (oldDoc == aDocument) {
|
||||
// Make a copy of the old window's performance object on document.open.
|
||||
// Note that we have to force eager creation of it here, because we need
|
||||
// to grab the current document channel and whatnot before that changes.
|
||||
currentInner->AsInner()->CreatePerformanceObjectIfNeeded();
|
||||
if (currentInner->mPerformance) {
|
||||
newInnerWindow->mPerformance =
|
||||
Performance::CreateForMainThread(newInnerWindow->AsInner(),
|
||||
aDocument->NodePrincipal(),
|
||||
currentInner->mPerformance->GetDOMTiming(),
|
||||
currentInner->mPerformance->GetChannel());
|
||||
}
|
||||
|
||||
// Rebind DETH objects to the new global created by document.open().
|
||||
// XXX: Is this correct? We should consider if the spec and our
|
||||
// implementation should change to match other browsers by
|
||||
// just reusing the current window. (Bug 1449992)
|
||||
currentInner->ForEachEventTargetObject(
|
||||
[&] (DOMEventTargetHelper* aDETH, bool* aDoneOut) {
|
||||
aDETH->BindToOwner(newInnerWindow->AsGlobal());
|
||||
});
|
||||
handleDocumentOpen = true;
|
||||
}
|
||||
|
||||
// Don't free objects on our current inner window if it's going to be
|
||||
// held in the bfcache.
|
||||
if (!currentInner->IsFrozen()) {
|
||||
currentInner->FreeInnerObjects();
|
||||
doomCurrentInner = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1994,6 +1978,19 @@ nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
|
|||
newInnerWindow->mChromeEventHandler = mChromeEventHandler;
|
||||
}
|
||||
|
||||
// Handle any document.open() logic after we setup the new inner window
|
||||
// so that any bound DETH objects can see the top window, document, etc.
|
||||
if (handleDocumentOpen) {
|
||||
newInnerWindow->MigrateStateForDocumentOpen(currentInner);
|
||||
}
|
||||
|
||||
// We no longer need the old inner window. Start its destruction if
|
||||
// its not being reused and clear our reference.
|
||||
if (doomCurrentInner) {
|
||||
currentInner->FreeInnerObjects();
|
||||
}
|
||||
currentInner = nullptr;
|
||||
|
||||
// Ask the JS engine to assert that it's valid to access our DocGroup whenever
|
||||
// it runs JS code for this compartment. We skip the check if this window is
|
||||
// for chrome JS or an add-on.
|
||||
|
|
|
@ -630,7 +630,7 @@ Cache::AddAll(const GlobalObject& aGlobal,
|
|||
new FetchHandler(mActor->GetWorkerHolder(), this,
|
||||
Move(aRequestList), promise);
|
||||
|
||||
RefPtr<Promise> fetchPromise = Promise::All(aGlobal, fetchList, aRv);
|
||||
RefPtr<Promise> fetchPromise = Promise::All(aGlobal.Context(), fetchList, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -99,34 +99,25 @@ DOMEventTargetHelper::~DOMEventTargetHelper()
|
|||
void
|
||||
DOMEventTargetHelper::BindToOwner(nsPIDOMWindowInner* aOwner)
|
||||
{
|
||||
BindToOwner(aOwner ? aOwner->AsGlobal() : nullptr);
|
||||
// Make sure to bind via BindToOwner(nsIGlobalObject*) so
|
||||
// subclasses can override the method to perform additional
|
||||
// actions.
|
||||
nsIGlobalObject* global = aOwner ? aOwner->AsGlobal() : nullptr;
|
||||
BindToOwner(global);
|
||||
}
|
||||
|
||||
void
|
||||
DOMEventTargetHelper::BindToOwner(nsIGlobalObject* aOwner)
|
||||
{
|
||||
if (mParentObject) {
|
||||
mParentObject->RemoveEventTargetObject(this);
|
||||
if (mOwnerWindow) {
|
||||
mOwnerWindow = nullptr;
|
||||
}
|
||||
mParentObject = nullptr;
|
||||
mHasOrHasHadOwnerWindow = false;
|
||||
}
|
||||
if (aOwner) {
|
||||
mParentObject = aOwner;
|
||||
aOwner->AddEventTargetObject(this);
|
||||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindowInner>(do_QueryInterface(aOwner)).get();
|
||||
if (mOwnerWindow) {
|
||||
mHasOrHasHadOwnerWindow = true;
|
||||
}
|
||||
}
|
||||
BindToOwnerInternal(aOwner);
|
||||
}
|
||||
|
||||
void
|
||||
DOMEventTargetHelper::BindToOwner(DOMEventTargetHelper* aOther)
|
||||
{
|
||||
// Make sure to bind via BindToOwner(nsIGlobalObject*) so
|
||||
// subclasses can override the method to perform additional
|
||||
// actions.
|
||||
if (!aOther) {
|
||||
BindToOwner(static_cast<nsIGlobalObject*>(nullptr));
|
||||
return;
|
||||
|
@ -355,4 +346,26 @@ DOMEventTargetHelper::MaybeDontKeepAlive()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
DOMEventTargetHelper::BindToOwnerInternal(nsIGlobalObject* aOwner)
|
||||
{
|
||||
if (mParentObject) {
|
||||
mParentObject->RemoveEventTargetObject(this);
|
||||
if (mOwnerWindow) {
|
||||
mOwnerWindow = nullptr;
|
||||
}
|
||||
mParentObject = nullptr;
|
||||
mHasOrHasHadOwnerWindow = false;
|
||||
}
|
||||
if (aOwner) {
|
||||
mParentObject = aOwner;
|
||||
aOwner->AddEventTargetObject(this);
|
||||
// Let's cache the result of this QI for fast access and off main thread usage
|
||||
mOwnerWindow = nsCOMPtr<nsPIDOMWindowInner>(do_QueryInterface(aOwner)).get();
|
||||
if (mOwnerWindow) {
|
||||
mHasOrHasHadOwnerWindow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -46,7 +46,10 @@ public:
|
|||
, mHasOrHasHadOwnerWindow(false)
|
||||
, mIsKeptAlive(false)
|
||||
{
|
||||
BindToOwner(aWindow);
|
||||
// Be careful not to call the virtual BindToOwner() in a
|
||||
// constructor.
|
||||
nsIGlobalObject* global = aWindow ? aWindow->AsGlobal() : nullptr;
|
||||
BindToOwnerInternal(global);
|
||||
}
|
||||
explicit DOMEventTargetHelper(nsIGlobalObject* aGlobalObject)
|
||||
: mParentObject(nullptr)
|
||||
|
@ -54,7 +57,9 @@ public:
|
|||
, mHasOrHasHadOwnerWindow(false)
|
||||
, mIsKeptAlive(false)
|
||||
{
|
||||
BindToOwner(aGlobalObject);
|
||||
// Be careful not to call the virtual BindToOwner() in a
|
||||
// constructor.
|
||||
BindToOwnerInternal(aGlobalObject);
|
||||
}
|
||||
explicit DOMEventTargetHelper(DOMEventTargetHelper* aOther)
|
||||
: mParentObject(nullptr)
|
||||
|
@ -62,7 +67,14 @@ public:
|
|||
, mHasOrHasHadOwnerWindow(false)
|
||||
, mIsKeptAlive(false)
|
||||
{
|
||||
BindToOwner(aOther);
|
||||
// Be careful not to call the virtual BindToOwner() in a
|
||||
// constructor.
|
||||
if (!aOther) {
|
||||
BindToOwnerInternal(static_cast<nsIGlobalObject*>(nullptr));
|
||||
return;
|
||||
}
|
||||
BindToOwnerInternal(aOther->GetParentObject());
|
||||
mHasOrHasHadOwnerWindow = aOther->HasOrHasHadOwner();
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -142,9 +154,20 @@ public:
|
|||
// Returns the document associated with this event target, if that document is
|
||||
// the current document of its browsing context. Will return null otherwise.
|
||||
nsIDocument* GetDocumentIfCurrent() const;
|
||||
void BindToOwner(nsIGlobalObject* aOwner);
|
||||
|
||||
// DETH subclasses may override the BindToOwner(nsIGlobalObject*) method
|
||||
// to take action when dynamically binding to a new global. This is only
|
||||
// called on rebind since virtual methods cannot be called from the
|
||||
// constructor. The other BindToOwner() methods will call into this
|
||||
// method.
|
||||
//
|
||||
// NOTE: Any overrides of BindToOwner() *must* invoke
|
||||
// DOMEventTargetHelper::BindToOwner(aOwner).
|
||||
virtual void BindToOwner(nsIGlobalObject* aOwner);
|
||||
|
||||
void BindToOwner(nsPIDOMWindowInner* aOwner);
|
||||
void BindToOwner(DOMEventTargetHelper* aOther);
|
||||
|
||||
virtual void DisconnectFromOwner();
|
||||
using EventTarget::GetParentObject;
|
||||
virtual nsIGlobalObject* GetOwnerGlobal() const override
|
||||
|
@ -189,6 +212,8 @@ protected:
|
|||
void IgnoreKeepAliveIfHasListenersFor(const nsAString& aType);
|
||||
void IgnoreKeepAliveIfHasListenersFor(nsAtom* aType);
|
||||
|
||||
void BindToOwnerInternal(nsIGlobalObject* aOwner);
|
||||
|
||||
private:
|
||||
// The parent global object. The global will clear this when
|
||||
// it is destroyed by calling DisconnectFromOwner().
|
||||
|
|
|
@ -72,7 +72,8 @@ async function _eventListenerLeakStep(target, name, extra) {
|
|||
frame.remove();
|
||||
frame = null;
|
||||
|
||||
// Perform two GC'd to avoid intermittent delayed collection.
|
||||
// Perform many GC's to avoid intermittent delayed collection.
|
||||
await new Promise(resolve => SpecialPowers.exactGC(resolve));
|
||||
await new Promise(resolve => SpecialPowers.exactGC(resolve));
|
||||
await new Promise(resolve => SpecialPowers.exactGC(resolve));
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@ IDBFactory::IDBFactory()
|
|||
: mOwningObject(nullptr)
|
||||
, mBackgroundActor(nullptr)
|
||||
, mInnerWindowID(0)
|
||||
, mActiveTransactionCount(0)
|
||||
, mActiveDatabaseCount(0)
|
||||
, mBackgroundActorFailed(false)
|
||||
, mPrivateBrowsingMode(false)
|
||||
{
|
||||
|
@ -396,6 +398,9 @@ void
|
|||
IDBFactory::UpdateActiveTransactionCount(int32_t aDelta)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_DIAGNOSTIC_ASSERT(aDelta > 0 ||
|
||||
(mActiveTransactionCount + aDelta) < mActiveTransactionCount);
|
||||
mActiveTransactionCount += aDelta;
|
||||
if (mWindow) {
|
||||
mWindow->UpdateActiveIndexedDBTransactionCount(aDelta);
|
||||
}
|
||||
|
@ -405,6 +410,9 @@ void
|
|||
IDBFactory::UpdateActiveDatabaseCount(int32_t aDelta)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_DIAGNOSTIC_ASSERT(aDelta > 0 ||
|
||||
(mActiveDatabaseCount + aDelta) < mActiveDatabaseCount);
|
||||
mActiveDatabaseCount += aDelta;
|
||||
if (mWindow) {
|
||||
mWindow->UpdateActiveIndexedDBDatabaseCount(aDelta);
|
||||
}
|
||||
|
@ -870,6 +878,33 @@ IDBFactory::InitiateRequest(IDBOpenDBRequest* aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
IDBFactory::RebindToNewWindow(nsPIDOMWindowInner* aNewWindow)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aNewWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mWindow);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aNewWindow != mWindow);
|
||||
|
||||
mWindow->UpdateActiveIndexedDBTransactionCount(-1 * mActiveTransactionCount);
|
||||
mWindow->UpdateActiveIndexedDBDatabaseCount(-1 * mActiveDatabaseCount);
|
||||
|
||||
mWindow = aNewWindow;
|
||||
|
||||
mInnerWindowID = aNewWindow->WindowID();
|
||||
mWindow->UpdateActiveIndexedDBTransactionCount(mActiveTransactionCount);
|
||||
mWindow->UpdateActiveIndexedDBDatabaseCount(mActiveDatabaseCount);
|
||||
}
|
||||
|
||||
void
|
||||
IDBFactory::DisconnectFromWindow(nsPIDOMWindowInner* aOldWindow)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aOldWindow);
|
||||
// If CC unlinks us first, then mWindow might be nullptr
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mWindow || mWindow == aOldWindow);
|
||||
|
||||
mWindow = nullptr;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBFactory)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBFactory)
|
||||
|
||||
|
|
|
@ -76,6 +76,8 @@ class IDBFactory final
|
|||
nsCOMPtr<nsIEventTarget> mEventTarget;
|
||||
|
||||
uint64_t mInnerWindowID;
|
||||
uint32_t mActiveTransactionCount;
|
||||
uint32_t mActiveDatabaseCount;
|
||||
|
||||
bool mBackgroundActorFailed;
|
||||
bool mPrivateBrowsingMode;
|
||||
|
@ -225,6 +227,12 @@ public:
|
|||
SystemCallerGuarantee,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
RebindToNewWindow(nsPIDOMWindowInner* aNewWindow);
|
||||
|
||||
void
|
||||
DisconnectFromWindow(nsPIDOMWindowInner* aOldWindow);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ support-files =
|
|||
bfcache_page1.html
|
||||
bfcache_page2.html
|
||||
blob_worker_crash_iframe.html
|
||||
!/dom/events/test/event_leak_utils.js
|
||||
error_events_abort_transactions_iframe.html
|
||||
event_propagation_iframe.html
|
||||
exceptions_in_events_iframe.html
|
||||
|
@ -154,6 +155,7 @@ skip-if = e10s && os == 'win' && os_version == '6.1' # Bug 1342415
|
|||
[test_deleteDatabase_onblocked.html]
|
||||
[test_deleteDatabase_onblocked_duringVersionChange.html]
|
||||
[test_error_events_abort_transactions.html]
|
||||
[test_event_listener_leaks.html]
|
||||
[test_event_propagation.html]
|
||||
[test_event_source.html]
|
||||
[test_exceptions_in_events.html]
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1450358 - Test IDB event listener leak conditions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/dom/events/test/event_leak_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
/* global checkForEventListenerLeaks */
|
||||
|
||||
// Manipulate IDB objects in the frame's context.
|
||||
// Its important here that we create a listener callback from
|
||||
// the DOM objects back to the frame's global in order to
|
||||
// exercise the leak condition.
|
||||
let count = 0;
|
||||
async function useIDB(contentWindow) {
|
||||
count += 1;
|
||||
let db = await new Promise(resolve => {
|
||||
let r = contentWindow.indexedDB.open("idb-leak-test-" + count, 1.0);
|
||||
r.onupgradeneeded = evt => {
|
||||
evt.target.result.createObjectStore("looped");
|
||||
};
|
||||
r.onsuccess = evt => {
|
||||
resolve(evt.target.result);
|
||||
};
|
||||
});
|
||||
|
||||
let tx = db.transaction("looped", "readwrite");
|
||||
let store = tx.objectStore("looped");
|
||||
|
||||
function spin() {
|
||||
contentWindow.spinCount += 1;
|
||||
store.get(0).onsuccess = spin;
|
||||
}
|
||||
|
||||
store.put(0, "purgatory").onsuccess = e => {
|
||||
contentWindow.putCount += 1;
|
||||
spin();
|
||||
};
|
||||
}
|
||||
|
||||
async function runTest() {
|
||||
try {
|
||||
await checkForEventListenerLeaks("IDB", useIDB);
|
||||
} catch (e) {
|
||||
ok(false, e);
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addEventListener("load", runTest, { once: true });
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -688,6 +688,23 @@ void AudioContext::DisconnectFromOwner()
|
|||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::BindToOwner(nsIGlobalObject* aNew)
|
||||
{
|
||||
auto scopeExit = MakeScopeExit([&] {
|
||||
DOMEventTargetHelper::BindToOwner(aNew);
|
||||
});
|
||||
|
||||
if (GetOwner()) {
|
||||
GetOwner()->RemoveAudioContext(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> newWindow = do_QueryInterface(aNew);
|
||||
if (newWindow) {
|
||||
newWindow->AddAudioContext(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioContext::Shutdown()
|
||||
{
|
||||
|
|
|
@ -145,6 +145,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void DisconnectFromOwner() override;
|
||||
virtual void BindToOwner(nsIGlobalObject* aNew) override;
|
||||
|
||||
void Shutdown(); // idempotent
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ AudioNode::AudioNode(AudioContext* aContext,
|
|||
, mAbstractMainThread(aContext->GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other))
|
||||
{
|
||||
MOZ_ASSERT(aContext);
|
||||
DOMEventTargetHelper::BindToOwner(aContext->GetParentObject());
|
||||
aContext->RegisterNode(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ support-files =
|
|||
audiovideo.mp4
|
||||
audioBufferSourceNodeDetached_worker.js
|
||||
corsServer.sjs
|
||||
!/dom/events/test/event_leak_utils.js
|
||||
file_nodeCreationDocumentGone.html
|
||||
invalid.txt
|
||||
layouttest-glue.js
|
||||
|
@ -152,6 +153,7 @@ skip-if = toolkit == 'android' # bug 1056706
|
|||
[test_dynamicsCompressorNode.html]
|
||||
[test_dynamicsCompressorNodePassThrough.html]
|
||||
[test_dynamicsCompressorNodeWithGain.html]
|
||||
[test_event_listener_leaks.html]
|
||||
[test_gainNode.html]
|
||||
[test_gainNodeInLoop.html]
|
||||
[test_gainNodePassThrough.html]
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1450358 - Test AudioContext event listener leak conditions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/dom/events/test/event_leak_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
// Manipulate AudioContext objects in the frame's context.
|
||||
// Its important here that we create a listener callback from
|
||||
// the DOM objects back to the frame's global in order to
|
||||
// exercise the leak condition.
|
||||
async function useAudioContext(contentWindow) {
|
||||
let ctx = new contentWindow.AudioContext();
|
||||
ctx.onstatechange = e => {
|
||||
contentWindow.stateChangeCount += 1;
|
||||
};
|
||||
|
||||
let osc = ctx.createOscillator();
|
||||
osc.type = "sine";
|
||||
osc.frequency.value = 440;
|
||||
osc.start();
|
||||
}
|
||||
|
||||
async function runTest() {
|
||||
try {
|
||||
await checkForEventListenerLeaks("AudioContext", useAudioContext);
|
||||
} catch (e) {
|
||||
ok(false, e);
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addEventListener("load", runTest, { once: true });
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -135,37 +135,40 @@ Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
|
|||
|
||||
// static
|
||||
already_AddRefed<Promise>
|
||||
Promise::All(const GlobalObject& aGlobal,
|
||||
Promise::All(JSContext* aCx,
|
||||
const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global;
|
||||
global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
JS::Rooted<JSObject*> globalObj(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
if (!globalObj) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(globalObj);
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSContext* cx = aGlobal.Context();
|
||||
|
||||
JS::AutoObjectVector promises(cx);
|
||||
JS::AutoObjectVector promises(aCx);
|
||||
if (!promises.reserve(aPromiseList.Length())) {
|
||||
aRv.NoteJSContextException(cx);
|
||||
aRv.NoteJSContextException(aCx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto& promise : aPromiseList) {
|
||||
JS::Rooted<JSObject*> promiseObj(cx, promise->PromiseObj());
|
||||
JS::Rooted<JSObject*> promiseObj(aCx, promise->PromiseObj());
|
||||
// Just in case, make sure these are all in the context compartment.
|
||||
if (!JS_WrapObject(cx, &promiseObj)) {
|
||||
aRv.NoteJSContextException(cx);
|
||||
if (!JS_WrapObject(aCx, &promiseObj)) {
|
||||
aRv.NoteJSContextException(aCx);
|
||||
return nullptr;
|
||||
}
|
||||
promises.infallibleAppend(promiseObj);
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> result(cx, JS::GetWaitForAllPromise(cx, promises));
|
||||
JS::Rooted<JSObject*> result(aCx, JS::GetWaitForAllPromise(aCx, promises));
|
||||
if (!result) {
|
||||
aRv.NoteJSContextException(cx);
|
||||
aRv.NoteJSContextException(aCx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,23 +111,26 @@ public:
|
|||
return mGlobal;
|
||||
}
|
||||
|
||||
// Do the equivalent of Promise.resolve in the current compartment of aCx.
|
||||
// Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this
|
||||
// function MUST return a non-null value.
|
||||
// Do the equivalent of Promise.resolve in the compartment of aGlobal. The
|
||||
// compartment of aCx is ignored. Errors are reported on the ErrorResult; if
|
||||
// aRv comes back !Failed(), this function MUST return a non-null value.
|
||||
static already_AddRefed<Promise>
|
||||
Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
// Do the equivalent of Promise.reject in the current compartment of aCx.
|
||||
// Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this
|
||||
// function MUST return a non-null value.
|
||||
// Do the equivalent of Promise.reject in the compartment of aGlobal. The
|
||||
// compartment of aCx is ignored. Errors are reported on the ErrorResult; if
|
||||
// aRv comes back !Failed(), this function MUST return a non-null value.
|
||||
static already_AddRefed<Promise>
|
||||
Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
// Do the equivalent of Promise.all in the current compartment of aCx. Errors
|
||||
// are reported on the ErrorResult; if aRv comes back !Failed(), this function
|
||||
// MUST return a non-null value.
|
||||
static already_AddRefed<Promise>
|
||||
All(const GlobalObject& aGlobal,
|
||||
const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv);
|
||||
All(JSContext* aCx, const nsTArray<RefPtr<Promise>>& aPromiseList,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Then(JSContext* aCx,
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
// Custom *.sjs file specifically for the needs of Bug 1454242
|
||||
|
||||
const WIN = `
|
||||
<html>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
let newWin = window.open("http://mochi.test:8888/tests/dom/security/test/general/file_same_site_cookies_toplevel_set_cookie.sjs?loadWinAndSetCookie");
|
||||
newWin.onload = function() {
|
||||
newWin.close();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const DUMMY_WIN = `
|
||||
<html>
|
||||
<body>
|
||||
just a dummy window that sets a same-site=lax cookie
|
||||
<script type="application/javascript">
|
||||
window.opener.opener.postMessage({value: 'testSetupComplete'}, '*');
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const FRAME = `
|
||||
<html>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
let cookie = document.cookie;
|
||||
// now reset the cookie for the next test
|
||||
document.cookie = "myKey=;" + "expires=Thu, 01 Jan 1970 00:00:00 GMT";
|
||||
window.parent.postMessage({value: cookie}, 'http://mochi.test:8888');
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const SAME_ORIGIN = "http://mochi.test:8888/"
|
||||
const CROSS_ORIGIN = "http://example.com/";
|
||||
const PATH = "tests/dom/security/test/general/file_same_site_cookies_redirect.sjs";
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
// avoid confusing cache behaviors
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
|
||||
if (request.queryString === "loadWin") {
|
||||
response.write(WIN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString === "loadWinAndSetCookie") {
|
||||
response.setHeader("Set-Cookie", "myKey=laxSameSiteCookie; samesite=lax", true);
|
||||
response.write(DUMMY_WIN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString === "checkCookie") {
|
||||
response.write(FRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
// we should never get here, but just in case return something unexpected
|
||||
response.write("D'oh");
|
||||
}
|
|
@ -13,6 +13,7 @@ support-files =
|
|||
file_same_site_cookies_cross_origin_context.sjs
|
||||
file_same_site_cookies_from_script.sjs
|
||||
file_same_site_cookies_redirect.sjs
|
||||
file_same_site_cookies_toplevel_set_cookie.sjs
|
||||
|
||||
[test_contentpolicytype_targeted_link_iframe.html]
|
||||
[test_nosniff.html]
|
||||
|
@ -31,3 +32,4 @@ skip-if = toolkit == 'android'
|
|||
[test_same_site_cookies_cross_origin_context.html]
|
||||
[test_same_site_cookies_from_script.html]
|
||||
[test_same_site_cookies_redirect.html]
|
||||
[test_same_site_cookies_toplevel_set_cookie.html]
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1454242: Setting samesite cookie should not rely on NS_IsSameSiteForeign</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<img id="cookieImage">
|
||||
<iframe id="testframe"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/*
|
||||
* Description of the test:
|
||||
* 1) We load a window from example.com which loads a window from mochi.test
|
||||
* which then sets a same-site cookie for mochi.test.
|
||||
* 2) We load an iframe from mochi.test.
|
||||
* 3) We observe that the cookie within (1) was allowed to be set and
|
||||
* is available for mochi.test.
|
||||
*/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const SAME_ORIGIN = "http://mochi.test:8888/"
|
||||
const CROSS_ORIGIN = "http://example.com/";
|
||||
const PATH = "tests/dom/security/test/general/file_same_site_cookies_toplevel_set_cookie.sjs";
|
||||
|
||||
let testWin = null;
|
||||
|
||||
window.addEventListener("message", receiveMessage);
|
||||
function receiveMessage(event) {
|
||||
// once the second window (which sets the cookie) loaded, we get a notification
|
||||
// that the test setup is correct and we can now try to query the same-site cookie
|
||||
if (event.data.value === "testSetupComplete") {
|
||||
ok(true, "cookie setup worked");
|
||||
let testframe = document.getElementById("testframe");
|
||||
testframe.src = SAME_ORIGIN + PATH + "?checkCookie";
|
||||
return;
|
||||
}
|
||||
|
||||
// thie second message is the cookie value from verifying the
|
||||
// cookie has been set correctly.
|
||||
is(event.data.value, "myKey=laxSameSiteCookie",
|
||||
"setting same-site cookie on cross origin top-level page");
|
||||
|
||||
window.removeEventListener("message", receiveMessage);
|
||||
testWin.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// fire up the test
|
||||
testWin = window.open(CROSS_ORIGIN + PATH + "?loadWin");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -10,7 +10,6 @@
|
|||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/SVGAnimationElement.h"
|
||||
#include "mozilla/TaskCategory.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsSMILTimedElement.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsSMILAnimationFunction.h"
|
||||
|
@ -630,7 +629,7 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, bool aEndOnly)
|
|||
: STATE_POSTACTIVE;
|
||||
stateChanged = true;
|
||||
if (mElementState == STATE_WAITING) {
|
||||
mCurrentInterval = new nsSMILInterval(firstInterval);
|
||||
mCurrentInterval = MakeUnique<nsSMILInterval>(firstInterval);
|
||||
NotifyNewInterval();
|
||||
}
|
||||
}
|
||||
|
@ -673,7 +672,7 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, bool aEndOnly)
|
|||
if (mCurrentInterval->End()->Time() <= sampleTime) {
|
||||
nsSMILInterval newInterval;
|
||||
mElementState =
|
||||
GetNextInterval(mCurrentInterval, nullptr, nullptr, newInterval)
|
||||
GetNextInterval(mCurrentInterval.get(), nullptr, nullptr, newInterval)
|
||||
? STATE_WAITING
|
||||
: STATE_POSTACTIVE;
|
||||
if (mClient) {
|
||||
|
@ -684,15 +683,15 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, bool aEndOnly)
|
|||
FireTimeEventAsync(eSMILEndEvent, 0);
|
||||
}
|
||||
mCurrentRepeatIteration = 0;
|
||||
mOldIntervals.AppendElement(mCurrentInterval.forget());
|
||||
mOldIntervals.AppendElement(Move(mCurrentInterval));
|
||||
SampleFillValue();
|
||||
if (mElementState == STATE_WAITING) {
|
||||
mCurrentInterval = new nsSMILInterval(newInterval);
|
||||
mCurrentInterval = MakeUnique<nsSMILInterval>(newInterval);
|
||||
}
|
||||
// We are now in a consistent state to dispatch notifications
|
||||
if (didApplyEarlyEnd) {
|
||||
NotifyChangedInterval(
|
||||
mOldIntervals[mOldIntervals.Length() - 1], false, true);
|
||||
mOldIntervals[mOldIntervals.Length() - 1].get(), false, true);
|
||||
}
|
||||
if (mElementState == STATE_WAITING) {
|
||||
NotifyNewInterval();
|
||||
|
@ -768,7 +767,7 @@ nsSMILTimedElement::HandleContainerTimeChange()
|
|||
// the nsSMILTimeValueSpec we'll check if anything has changed and if not, we
|
||||
// won't go any further.
|
||||
if (mElementState == STATE_WAITING || mElementState == STATE_ACTIVE) {
|
||||
NotifyChangedInterval(mCurrentInterval, false, false);
|
||||
NotifyChangedInterval(mCurrentInterval.get(), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1259,7 +1258,7 @@ nsSMILTimedElement::Traverse(nsCycleCollectionTraversalCallback* aCallback)
|
|||
{
|
||||
uint32_t count = mBeginSpecs.Length();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i];
|
||||
nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i].get();
|
||||
MOZ_ASSERT(beginSpec,
|
||||
"null nsSMILTimeValueSpec in list of begin specs");
|
||||
beginSpec->Traverse(aCallback);
|
||||
|
@ -1267,7 +1266,7 @@ nsSMILTimedElement::Traverse(nsCycleCollectionTraversalCallback* aCallback)
|
|||
|
||||
count = mEndSpecs.Length();
|
||||
for (uint32_t j = 0; j < count; ++j) {
|
||||
nsSMILTimeValueSpec* endSpec = mEndSpecs[j];
|
||||
nsSMILTimeValueSpec* endSpec = mEndSpecs[j].get();
|
||||
MOZ_ASSERT(endSpec, "null nsSMILTimeValueSpec in list of end specs");
|
||||
endSpec->Traverse(aCallback);
|
||||
}
|
||||
|
@ -1281,7 +1280,7 @@ nsSMILTimedElement::Unlink()
|
|||
// Remove dependencies on other elements
|
||||
uint32_t count = mBeginSpecs.Length();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i];
|
||||
nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i].get();
|
||||
MOZ_ASSERT(beginSpec,
|
||||
"null nsSMILTimeValueSpec in list of begin specs");
|
||||
beginSpec->Unlink();
|
||||
|
@ -1289,7 +1288,7 @@ nsSMILTimedElement::Unlink()
|
|||
|
||||
count = mEndSpecs.Length();
|
||||
for (uint32_t j = 0; j < count; ++j) {
|
||||
nsSMILTimeValueSpec* endSpec = mEndSpecs[j];
|
||||
nsSMILTimeValueSpec* endSpec = mEndSpecs[j].get();
|
||||
MOZ_ASSERT(endSpec, "null nsSMILTimeValueSpec in list of end specs");
|
||||
endSpec->Unlink();
|
||||
}
|
||||
|
@ -1323,11 +1322,10 @@ nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
|
|||
|
||||
bool hadFailure = false;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
nsAutoPtr<nsSMILTimeValueSpec>
|
||||
spec(new nsSMILTimeValueSpec(*this, aIsBegin));
|
||||
auto spec = MakeUnique<nsSMILTimeValueSpec>(*this, aIsBegin);
|
||||
nsresult rv = spec->SetSpec(tokenizer.nextToken(), aContextNode);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
timeSpecsList.AppendElement(spec.forget());
|
||||
timeSpecsList.AppendElement(Move(spec));
|
||||
} else {
|
||||
hadFailure = true;
|
||||
}
|
||||
|
@ -1613,7 +1611,7 @@ nsSMILTimedElement::FilterIntervals()
|
|||
(i < threshold || !interval->IsDependencyChainLink())) {
|
||||
interval->Unlink(true /*filtered, not deleted*/);
|
||||
} else {
|
||||
filteredList.AppendElement(mOldIntervals[i].forget());
|
||||
filteredList.AppendElement(Move(mOldIntervals[i]));
|
||||
}
|
||||
}
|
||||
mOldIntervals.Clear();
|
||||
|
@ -2089,14 +2087,14 @@ nsSMILTimedElement::UpdateCurrentInterval(bool aForceChangeNotice)
|
|||
? mCurrentInterval->Begin()
|
||||
: nullptr;
|
||||
nsSMILInterval updatedInterval;
|
||||
if (GetNextInterval(GetPreviousInterval(), mCurrentInterval,
|
||||
if (GetNextInterval(GetPreviousInterval(), mCurrentInterval.get(),
|
||||
beginTime, updatedInterval)) {
|
||||
|
||||
if (mElementState == STATE_POSTACTIVE) {
|
||||
|
||||
MOZ_ASSERT(!mCurrentInterval,
|
||||
"In postactive state but the interval has been set");
|
||||
mCurrentInterval = new nsSMILInterval(updatedInterval);
|
||||
mCurrentInterval = MakeUnique<nsSMILInterval>(updatedInterval);
|
||||
mElementState = STATE_WAITING;
|
||||
NotifyNewInterval();
|
||||
|
||||
|
@ -2118,7 +2116,7 @@ nsSMILTimedElement::UpdateCurrentInterval(bool aForceChangeNotice)
|
|||
}
|
||||
|
||||
if (beginChanged || endChanged || aForceChangeNotice) {
|
||||
NotifyChangedInterval(mCurrentInterval, beginChanged, endChanged);
|
||||
NotifyChangedInterval(mCurrentInterval.get(), beginChanged, endChanged);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2132,7 +2130,7 @@ nsSMILTimedElement::UpdateCurrentInterval(bool aForceChangeNotice)
|
|||
if (!mCurrentInterval->End()->SameTimeAndBase(*mCurrentInterval->Begin()))
|
||||
{
|
||||
mCurrentInterval->SetEnd(*mCurrentInterval->Begin());
|
||||
NotifyChangedInterval(mCurrentInterval, false, true);
|
||||
NotifyChangedInterval(mCurrentInterval.get(), false, true);
|
||||
}
|
||||
// The transition to the postactive state will take place on the next
|
||||
// sample (along with firing end events, clearing intervals etc.)
|
||||
|
@ -2340,7 +2338,7 @@ nsSMILTimedElement::NotifyNewInterval()
|
|||
}
|
||||
|
||||
for (auto iter = mTimeDependents.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsSMILInterval* interval = mCurrentInterval;
|
||||
nsSMILInterval* interval = mCurrentInterval.get();
|
||||
// It's possible that in notifying one new time dependent of a new interval
|
||||
// that a chain reaction is triggered which results in the original
|
||||
// interval disappearing. If that's the case we can skip sending further
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsSMILInterval.h"
|
||||
#include "nsSMILInstanceTime.h"
|
||||
#include "nsSMILMilestone.h"
|
||||
|
@ -352,9 +353,9 @@ public:
|
|||
|
||||
protected:
|
||||
// Typedefs
|
||||
typedef nsTArray<nsAutoPtr<nsSMILTimeValueSpec> > TimeValueSpecList;
|
||||
typedef nsTArray<mozilla::UniquePtr<nsSMILTimeValueSpec>> TimeValueSpecList;
|
||||
typedef nsTArray<RefPtr<nsSMILInstanceTime> > InstanceTimeList;
|
||||
typedef nsTArray<nsAutoPtr<nsSMILInterval> > IntervalList;
|
||||
typedef nsTArray<mozilla::UniquePtr<nsSMILInterval>> IntervalList;
|
||||
typedef nsPtrHashKey<nsSMILTimeValueSpec> TimeValueSpecPtrKey;
|
||||
typedef nsTHashtable<TimeValueSpecPtrKey> TimeValueSpecHashSet;
|
||||
|
||||
|
@ -557,7 +558,7 @@ protected:
|
|||
{
|
||||
if (mCurrentInterval) {
|
||||
// Transfer ownership to temp var. (This sets mCurrentInterval to null.)
|
||||
nsAutoPtr<nsSMILInterval> interval(mozilla::Move(mCurrentInterval));
|
||||
auto interval = mozilla::Move(mCurrentInterval);
|
||||
interval->Unlink();
|
||||
}
|
||||
}
|
||||
|
@ -600,7 +601,7 @@ protected:
|
|||
uint32_t mInstanceSerialIndex;
|
||||
|
||||
nsSMILAnimationFunction* mClient;
|
||||
nsAutoPtr<nsSMILInterval> mCurrentInterval;
|
||||
mozilla::UniquePtr<nsSMILInterval> mCurrentInterval;
|
||||
IntervalList mOldIntervals;
|
||||
uint32_t mCurrentRepeatIteration;
|
||||
nsSMILMilestone mPrevRegisteredMilestone;
|
||||
|
|
|
@ -954,6 +954,30 @@ WebSocket::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
|
|||
return WebSocketBinding::Wrap(cx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
WebSocket::BindToOwner(nsIGlobalObject* aNew)
|
||||
{
|
||||
auto scopeExit = MakeScopeExit([&] {
|
||||
DOMEventTargetHelper::BindToOwner(aNew);
|
||||
});
|
||||
|
||||
// If we're disconnected, then there is no state to update.
|
||||
if (!mImpl || mImpl->mDisconnectingOrDisconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update state on the old window.
|
||||
if (GetOwner()) {
|
||||
GetOwner()->UpdateWebSocketCount(-1);
|
||||
}
|
||||
|
||||
// Update state on the new window
|
||||
nsCOMPtr<nsPIDOMWindowInner> newWindow = do_QueryInterface(aNew);
|
||||
if (newWindow) {
|
||||
newWindow->UpdateWebSocketCount(1);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// WebIDL
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// DOMEventTargetHelper
|
||||
void BindToOwner(nsIGlobalObject* aNew) override;
|
||||
|
||||
public: // static helpers:
|
||||
|
||||
// Determine if preferences allow WebSocket
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
skip-if = toolkit == 'android' # bug 982828
|
||||
support-files =
|
||||
!/dom/events/test/event_leak_utils.js
|
||||
file_websocket_basic_wsh.py
|
||||
file_websocket_hello_wsh.py
|
||||
file_websocket_http_resource.txt
|
||||
|
@ -16,6 +17,8 @@ support-files =
|
|||
[test_bug1081686.html]
|
||||
[test_bug1384658.html]
|
||||
support-files = window_bug1384658.html frame_bug1384658.html file_bug1384658.html
|
||||
[test_event_listener_leaks.html]
|
||||
support-files = file_websocket_bigBlob_wsh.py
|
||||
[test_websocket1.html]
|
||||
[test_websocket2.html]
|
||||
[test_websocket3.html]
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1450358 - Test WebSocket event listener leak conditions</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/dom/events/test/event_leak_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
// Manipulate WebSocket objects in the frame's context.
|
||||
// Its important here that we create a listener callback from
|
||||
// the DOM objects back to the frame's global in order to
|
||||
// exercise the leak condition.
|
||||
async function useWebSocket(contentWindow) {
|
||||
const url = "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket_bigBlob";
|
||||
let ws = new contentWindow.WebSocket(url);
|
||||
|
||||
ws.onmessage = _ => {
|
||||
contentWindow.messageCount += 1;
|
||||
};
|
||||
|
||||
contentWindow.openCount = 0;
|
||||
await new Promise((resolve, reject) => {
|
||||
ws.onopen = _ => {
|
||||
contentWindow.openCount += 1;
|
||||
resolve();
|
||||
};
|
||||
ws.onerror = e => {
|
||||
contentWindow.errorCount += 1;
|
||||
reject("websocket error");
|
||||
};
|
||||
});
|
||||
|
||||
is(contentWindow.openCount, 1, "open should be received");
|
||||
}
|
||||
|
||||
async function runTest() {
|
||||
try {
|
||||
await checkForEventListenerLeaks("WebSocket", useWebSocket);
|
||||
} catch (e) {
|
||||
ok(false, e);
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addEventListener("load", runTest, { once: true });
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -93,7 +93,7 @@ DoGrayscale(IDWriteFontFace *aDWFace, Float ppem)
|
|||
}
|
||||
|
||||
static inline DWRITE_FONT_STRETCH
|
||||
DWriteFontStretchFromStretch(int16_t aStretch)
|
||||
DWriteFontStretchFromStretch(uint16_t aStretch)
|
||||
{
|
||||
switch (aStretch) {
|
||||
case NS_FONT_STRETCH_ULTRA_CONDENSED:
|
||||
|
|
|
@ -162,8 +162,6 @@ public:
|
|||
Tile& GetTile(size_t i) { return mRetainedTiles[i]; }
|
||||
|
||||
const nsIntRegion& GetValidRegion() const { return mValidRegion; }
|
||||
const nsIntRegion& GetPaintedRegion() const { return mPaintedRegion; }
|
||||
void ClearPaintedRegion() { mPaintedRegion.SetEmpty(); }
|
||||
|
||||
// Get and set draw scaling. mResolution affects the resolution at which the
|
||||
// contents of the buffer are drawn. mResolution has no effect on the
|
||||
|
@ -179,7 +177,6 @@ public:
|
|||
protected:
|
||||
|
||||
nsIntRegion mValidRegion;
|
||||
nsIntRegion mPaintedRegion;
|
||||
|
||||
/**
|
||||
* mRetainedTiles is a rectangular buffer of mTiles.mSize.width x mTiles.mSize.height
|
||||
|
|
|
@ -33,7 +33,6 @@ void
|
|||
SingleTiledContentClient::UpdatedBuffer(TiledBufferType aType)
|
||||
{
|
||||
mForwarder->UseTiledLayerBuffer(this, mTiledBuffer->GetSurfaceDescriptorTiles());
|
||||
mTiledBuffer->ClearPaintedRegion();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
|
@ -142,6 +141,7 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
}
|
||||
|
||||
// The dirty region relative to the top-left of the tile.
|
||||
nsIntRegion tileVisibleRegion = aNewValidRegion.MovedBy(-mTilingOrigin);
|
||||
nsIntRegion tileDirtyRegion = paintRegion.MovedBy(-mTilingOrigin);
|
||||
|
||||
std::vector<RefPtr<TextureClient>> paintClients;
|
||||
|
@ -153,6 +153,7 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
RefPtr<TextureClient> backBuffer =
|
||||
mTile.GetBackBuffer(mCompositableClient,
|
||||
tileDirtyRegion,
|
||||
tileVisibleRegion,
|
||||
content, mode,
|
||||
extraPainted,
|
||||
aFlags,
|
||||
|
@ -166,15 +167,18 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
|
||||
// Add backbuffer's invalid region to the dirty region to be painted.
|
||||
// This will be empty if we were able to copy from the front in to the back.
|
||||
paintRegion.OrWith(mTile.mInvalidBack.MovedBy(mTilingOrigin));
|
||||
tileDirtyRegion.OrWith(mTile.mInvalidBack);
|
||||
nsIntRegion tileInvalidRegion = mTile.mInvalidBack;
|
||||
tileInvalidRegion.AndWith(tileVisibleRegion);
|
||||
|
||||
paintRegion.OrWith(tileInvalidRegion.MovedBy(mTilingOrigin));
|
||||
tileDirtyRegion.OrWith(tileInvalidRegion);
|
||||
|
||||
// Mark the region we will be painting and the region we copied from the front buffer as
|
||||
// needing to be uploaded to the compositor
|
||||
mTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
|
||||
|
||||
extraPainted.MoveBy(mTilingOrigin);
|
||||
extraPainted.And(extraPainted, aNewValidRegion);
|
||||
mPaintedRegion.OrWith(paintRegion);
|
||||
mPaintedRegion.OrWith(extraPainted);
|
||||
|
||||
if (!backBuffer) {
|
||||
return;
|
||||
|
@ -188,10 +192,8 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
|
||||
// If the old frontbuffer was discarded then attempt to copy what we
|
||||
// can from it to the new backbuffer.
|
||||
bool copiedFromDiscarded = false;
|
||||
nsIntRegion copyableRegion;
|
||||
|
||||
if (discardedFrontBuffer) {
|
||||
nsIntRegion copyableRegion;
|
||||
copyableRegion.And(aNewValidRegion, discardedValidRegion);
|
||||
copyableRegion.SubOut(aDirtyRegion);
|
||||
|
||||
|
@ -254,22 +256,17 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
|||
|
||||
// We don't need to repaint valid content that was just copied.
|
||||
paintRegion.SubOut(copyableRegion);
|
||||
copiedFromDiscarded = true;
|
||||
copyableRegion.MoveBy(-mTilingOrigin);
|
||||
tileDirtyRegion.SubOut(copyableRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode != SurfaceMode::SURFACE_OPAQUE) {
|
||||
nsIntRegion regionToClear = tileDirtyRegion;
|
||||
if (copiedFromDiscarded) {
|
||||
copyableRegion.MoveBy(-mTilingOrigin);
|
||||
regionToClear.SubOut(copyableRegion);
|
||||
}
|
||||
|
||||
auto clear = CapturedTiledPaintState::Clear{
|
||||
dt,
|
||||
dtOnWhite,
|
||||
regionToClear,
|
||||
tileDirtyRegion,
|
||||
};
|
||||
|
||||
if (asyncPaint) {
|
||||
|
|
|
@ -59,7 +59,6 @@ public:
|
|||
}
|
||||
|
||||
void ResetPaintedAndValidState() override {
|
||||
mPaintedRegion.SetEmpty();
|
||||
mValidRegion.SetEmpty();
|
||||
mTile.DiscardBuffers();
|
||||
}
|
||||
|
@ -78,16 +77,11 @@ public:
|
|||
|
||||
SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
|
||||
|
||||
void ClearPaintedRegion() {
|
||||
mPaintedRegion.SetEmpty();
|
||||
}
|
||||
|
||||
private:
|
||||
TileClient mTile;
|
||||
|
||||
RefPtr<ClientLayerManager> mManager;
|
||||
|
||||
nsIntRegion mPaintedRegion;
|
||||
nsIntRegion mValidRegion;
|
||||
bool mWasLastPaintProgressive;
|
||||
|
||||
|
|
|
@ -118,7 +118,6 @@ MultiTiledContentClient::UpdatedBuffer(TiledBufferType aType)
|
|||
MOZ_ASSERT(aType != LOW_PRECISION_TILED_BUFFER || mHasLowPrecision);
|
||||
|
||||
mForwarder->UseTiledLayerBuffer(this, buffer->GetSurfaceDescriptorTiles());
|
||||
buffer->ClearPaintedRegion();
|
||||
}
|
||||
|
||||
SharedFrameMetricsHelper::SharedFrameMetricsHelper()
|
||||
|
@ -522,6 +521,7 @@ CopyFrontToBack(TextureClient* aFront,
|
|||
|
||||
void
|
||||
TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
|
||||
const nsIntRegion& aVisibleRegion,
|
||||
nsIntRegion& aAddPaintedRegion,
|
||||
TilePaintFlags aFlags,
|
||||
std::vector<CapturedTiledPaintState::Copy>* aCopies,
|
||||
|
@ -540,6 +540,7 @@ TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
|
|||
nsIntRegion regionToCopy = mInvalidBack;
|
||||
|
||||
regionToCopy.Sub(regionToCopy, aDirtyRegion);
|
||||
regionToCopy.And(regionToCopy, aVisibleRegion);
|
||||
|
||||
aAddPaintedRegion = regionToCopy;
|
||||
|
||||
|
@ -557,10 +558,10 @@ TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
|
|||
if (mBackBufferOnWhite) {
|
||||
MOZ_ASSERT(mFrontBufferOnWhite);
|
||||
if (CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, gfxRectToCopy, aFlags, aCopies, aClients)) {
|
||||
mInvalidBack.SetEmpty();
|
||||
mInvalidBack.Sub(mInvalidBack, aVisibleRegion);
|
||||
}
|
||||
} else {
|
||||
mInvalidBack.SetEmpty();
|
||||
mInvalidBack.Sub(mInvalidBack, aVisibleRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -653,6 +654,7 @@ CreateBackBufferTexture(TextureClient* aCurrentTexture,
|
|||
TextureClient*
|
||||
TileClient::GetBackBuffer(CompositableClient& aCompositable,
|
||||
const nsIntRegion& aDirtyRegion,
|
||||
const nsIntRegion& aVisibleRegion,
|
||||
gfxContentType aContent,
|
||||
SurfaceMode aMode,
|
||||
nsIntRegion& aAddPaintedRegion,
|
||||
|
@ -684,9 +686,15 @@ TileClient::GetBackBuffer(CompositableClient& aCompositable,
|
|||
!mFrontBuffer->IsReadLocked() &&
|
||||
(aMode != SurfaceMode::SURFACE_COMPONENT_ALPHA || (
|
||||
mFrontBufferOnWhite && !mFrontBufferOnWhite->IsReadLocked()))) {
|
||||
// If we had a backbuffer we no longer care about it since we'll
|
||||
// re-use the front buffer.
|
||||
DiscardBackBuffer();
|
||||
// If we had a backbuffer we no longer need it since we can re-use the
|
||||
// front buffer here. It can be worth it to hold on to the back buffer
|
||||
// so we don't need to pay the cost of initializing a new back buffer
|
||||
// later (copying pixels and texture upload). But this could increase
|
||||
// our memory usage and lead to OOM more frequently from spikes in usage,
|
||||
// so we have this behavior behind a pref.
|
||||
if (!gfxPrefs::LayersTileRetainBackBuffer()) {
|
||||
DiscardBackBuffer();
|
||||
}
|
||||
Flip();
|
||||
} else {
|
||||
if (!mBackBuffer || mBackBuffer->IsReadLocked()) {
|
||||
|
@ -714,7 +722,7 @@ TileClient::GetBackBuffer(CompositableClient& aCompositable,
|
|||
mInvalidBack = IntRect(IntPoint(), mBackBufferOnWhite->GetSize());
|
||||
}
|
||||
|
||||
ValidateBackBufferFromFront(aDirtyRegion, aAddPaintedRegion, aFlags, aCopies, aClients);
|
||||
ValidateBackBufferFromFront(aDirtyRegion, aVisibleRegion, aAddPaintedRegion, aFlags, aCopies, aClients);
|
||||
}
|
||||
|
||||
OpenMode lockMode = aFlags & TilePaintFlags::Async ? OpenMode::OPEN_READ_WRITE_ASYNC
|
||||
|
@ -1092,7 +1100,6 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
|
|||
|
||||
mTiles = newTiles;
|
||||
mValidRegion = newValidRegion;
|
||||
mPaintedRegion.OrWith(paintRegion);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1120,8 +1127,11 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
|
|||
MOZ_ASSERT(aTile.mAllocator);
|
||||
}
|
||||
|
||||
nsIntRegion offsetScaledDirtyRegion = aDirtyRegion.MovedBy(-aTileOrigin);
|
||||
offsetScaledDirtyRegion.ScaleRoundOut(mResolution, mResolution);
|
||||
nsIntRegion tileDirtyRegion = aDirtyRegion.MovedBy(-aTileOrigin);
|
||||
tileDirtyRegion.ScaleRoundOut(mResolution, mResolution);
|
||||
|
||||
nsIntRegion tileVisibleRegion = mNewValidRegion.MovedBy(-aTileOrigin);
|
||||
tileVisibleRegion.ScaleRoundOut(mResolution, mResolution);
|
||||
|
||||
std::vector<CapturedTiledPaintState::Copy> asyncPaintCopies;
|
||||
std::vector<RefPtr<TextureClient>> asyncPaintClients;
|
||||
|
@ -1130,7 +1140,8 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
|
|||
RefPtr<TextureClient> backBufferOnWhite;
|
||||
RefPtr<TextureClient> backBuffer =
|
||||
aTile.GetBackBuffer(mCompositableClient,
|
||||
offsetScaledDirtyRegion,
|
||||
tileDirtyRegion,
|
||||
tileVisibleRegion,
|
||||
content, mode,
|
||||
extraPainted,
|
||||
aFlags,
|
||||
|
@ -1140,22 +1151,28 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
|
|||
|
||||
// Mark the area we need to paint in the back buffer as invalid in the
|
||||
// front buffer as they will become out of sync.
|
||||
aTile.mInvalidFront.OrWith(offsetScaledDirtyRegion);
|
||||
aTile.mInvalidFront.OrWith(tileDirtyRegion);
|
||||
|
||||
// Add backbuffer's invalid region to the dirty region to be painted.
|
||||
// This will be empty if we were able to copy from the front in to the back.
|
||||
nsIntRegion invalidBack = aTile.mInvalidBack;
|
||||
invalidBack.MoveBy(aTileOrigin);
|
||||
invalidBack.ScaleInverseRoundOut(mResolution, mResolution);
|
||||
invalidBack.AndWith(mNewValidRegion);
|
||||
aDirtyRegion.OrWith(invalidBack);
|
||||
offsetScaledDirtyRegion.OrWith(aTile.mInvalidBack);
|
||||
// Add the backbuffer's invalid region intersected with the visible region to the
|
||||
// dirty region we will be painting. This will be empty if we are able to copy
|
||||
// from the front into the back.
|
||||
nsIntRegion tileInvalidRegion = aTile.mInvalidBack;
|
||||
tileInvalidRegion.AndWith(tileVisibleRegion);
|
||||
|
||||
aTile.mUpdateRect = offsetScaledDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
|
||||
nsIntRegion invalidRegion = tileInvalidRegion;
|
||||
invalidRegion.MoveBy(aTileOrigin);
|
||||
invalidRegion.ScaleInverseRoundOut(mResolution, mResolution);
|
||||
|
||||
tileDirtyRegion.OrWith(tileInvalidRegion);
|
||||
aDirtyRegion.OrWith(invalidRegion);
|
||||
|
||||
// Mark the region we will be painting and the region we copied from the front buffer as
|
||||
// needing to be uploaded to the compositor
|
||||
aTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
|
||||
|
||||
// Add the region we copied from the front buffer into the painted region
|
||||
extraPainted.MoveBy(aTileOrigin);
|
||||
extraPainted.And(extraPainted, mNewValidRegion);
|
||||
mPaintedRegion.Or(mPaintedRegion, extraPainted);
|
||||
|
||||
if (!backBuffer) {
|
||||
return false;
|
||||
|
@ -1182,7 +1199,7 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
|
|||
auto clear = CapturedTiledPaintState::Clear{
|
||||
dt,
|
||||
dtOnWhite,
|
||||
offsetScaledDirtyRegion
|
||||
tileDirtyRegion
|
||||
};
|
||||
|
||||
gfx::Tile paintTile;
|
||||
|
@ -1220,7 +1237,7 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
|
|||
mTilingOrigin.y = std::min(mTilingOrigin.y, paintTile.mTileOrigin.y);
|
||||
|
||||
// The new buffer is now validated, remove the dirty region from it.
|
||||
aTile.mInvalidBack.SubOut(offsetScaledDirtyRegion);
|
||||
aTile.mInvalidBack.SubOut(tileDirtyRegion);
|
||||
|
||||
aTile.Flip();
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ struct TileClient
|
|||
*/
|
||||
TextureClient* GetBackBuffer(CompositableClient&,
|
||||
const nsIntRegion& aDirtyRegion,
|
||||
const nsIntRegion& aVisibleRegion,
|
||||
gfxContentType aContent, SurfaceMode aMode,
|
||||
nsIntRegion& aAddPaintedRegion,
|
||||
TilePaintFlags aFlags,
|
||||
|
@ -170,6 +171,7 @@ private:
|
|||
// Copies dirty pixels from the front buffer into the back buffer,
|
||||
// and records the copied region in aAddPaintedRegion.
|
||||
void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion,
|
||||
const nsIntRegion& aVisibleRegion,
|
||||
nsIntRegion& aAddPaintedRegion,
|
||||
TilePaintFlags aFlags,
|
||||
std::vector<CapturedTiledPaintState::Copy>* aCopies,
|
||||
|
@ -382,7 +384,6 @@ public:
|
|||
void* aCallbackData) override;
|
||||
|
||||
void ResetPaintedAndValidState() override {
|
||||
mPaintedRegion.SetEmpty();
|
||||
mValidRegion.SetEmpty();
|
||||
mTiles.mSize.width = 0;
|
||||
mTiles.mSize.height = 0;
|
||||
|
|
|
@ -584,15 +584,6 @@ struct DIGroup
|
|||
|
||||
PaintItemRange(aGrouper, aStartItem, aEndItem, context, recorder);
|
||||
|
||||
if (aStartItem->Frame()->PresContext()->GetPaintFlashing()) {
|
||||
context->SetMatrix(Matrix());
|
||||
float r = float(rand()) / RAND_MAX;
|
||||
float g = float(rand()) / RAND_MAX;
|
||||
float b = float(rand()) / RAND_MAX;
|
||||
dt->FillRect(gfx::Rect(0, 0, dtSize.width, dtSize.height), gfx::ColorPattern(gfx::Color(r, g, b, 0.5)));
|
||||
dt->FlushItem(IntRect(IntPoint(0, 0), dtSize));
|
||||
}
|
||||
|
||||
// XXX: set this correctly perhaps using aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped).Contains(paintBounds);?
|
||||
bool isOpaque = false;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#define GFX_FONT_PROPERTY_TYPES_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
/*
|
||||
* This file is separate from gfxFont.h so that layout can include it
|
||||
|
@ -18,113 +20,314 @@
|
|||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* A type that will in future encode a value as fixed point.
|
||||
* Generic template for font property type classes that use a fixed-point
|
||||
* internal representation.
|
||||
* Template parameters:
|
||||
* T - the integer type to use as the internal representation (e.g. uint16_t)
|
||||
* * NOTE that T must NOT be plain /int/, as that would result in
|
||||
* ambiguity between constructors from /int/ and /T/, which mean
|
||||
* different things.
|
||||
* FractionBits - number of bits to use for the fractional part
|
||||
* Min, Max - [inclusive] limits to the range of values that may be stored
|
||||
* Values are constructed from and exposed as floating-point, but stored
|
||||
* internally as fixed point, so there will be a quantization effect on
|
||||
* fractional values, depending on the number of fractional bits used.
|
||||
* Using (16-bit) fixed-point types rather than floats for these style
|
||||
* attributes reduces the memory footprint of gfxFontEntry and gfxFontStyle;
|
||||
* it will also tend to reduce the number of distinct font instances that
|
||||
* get created, particularly when styles are animated or set to arbitrary
|
||||
* values (e.g. by sliders in the UI), which should reduce pressure on
|
||||
* graphics resources and improve cache hit rates.
|
||||
*/
|
||||
class FontFixedPointValue
|
||||
template<class T,unsigned FractionBits,int Min,int Max>
|
||||
class FontPropertyValue
|
||||
{
|
||||
public:
|
||||
// Ugh. We need a default constructor to allow this type to be used in the
|
||||
// union in nsCSSValue. Furthermore we need the default and copy
|
||||
// union in nsCSSValue. Furthermore we need the default and copy
|
||||
// constructors to be "trivial" (i.e. the compiler implemented defaults that
|
||||
// do no initialization).
|
||||
// Annoyingly it seems we can't make the default implementations constexpr
|
||||
// (at least in clang). We'd like to do that to allow Thin() et. al. below
|
||||
// Annoyingly we can't make the default implementations constexpr (at least
|
||||
// in clang). That would be nice to do in order to allow the methods of
|
||||
// subclasses that always return the same value (e.g., FontWeight::Thin())
|
||||
// to also be constexpr. :/
|
||||
FontFixedPointValue() = default;
|
||||
FontFixedPointValue(const FontFixedPointValue& aOther) = default;
|
||||
FontPropertyValue() = default;
|
||||
explicit FontPropertyValue(const FontPropertyValue& aOther) = default;
|
||||
FontPropertyValue& operator= (const FontPropertyValue& aOther) = default;
|
||||
|
||||
// Not currently encoded, but it will be in future
|
||||
explicit FontFixedPointValue(int16_t aValue)
|
||||
: mEncoded(aValue)
|
||||
{}
|
||||
|
||||
explicit FontFixedPointValue(int32_t aValue)
|
||||
: mEncoded(aValue)
|
||||
{}
|
||||
|
||||
explicit FontFixedPointValue(float aValue)
|
||||
: mEncoded(int16_t(aValue))
|
||||
{}
|
||||
|
||||
float ToFloat() const {
|
||||
return float(mEncoded);
|
||||
bool operator==(const FontPropertyValue& aOther) const
|
||||
{
|
||||
return mValue == aOther.mValue;
|
||||
}
|
||||
bool operator!=(const FontPropertyValue& aOther) const
|
||||
{
|
||||
return mValue != aOther.mValue;
|
||||
}
|
||||
bool operator<(const FontPropertyValue& aOther) const
|
||||
{
|
||||
return mValue < aOther.mValue;
|
||||
}
|
||||
bool operator>(const FontPropertyValue& aOther) const
|
||||
{
|
||||
return mValue > aOther.mValue;
|
||||
}
|
||||
bool operator<=(const FontPropertyValue& aOther) const
|
||||
{
|
||||
return mValue <= aOther.mValue;
|
||||
}
|
||||
bool operator>=(const FontPropertyValue& aOther) const
|
||||
{
|
||||
return mValue >= aOther.mValue;
|
||||
}
|
||||
|
||||
int16_t ToIntRounded() const {
|
||||
return mEncoded;
|
||||
// The difference between two values, returned as a raw floating-point number
|
||||
// (which might not be a valid property value in its own right).
|
||||
float operator-(const FontPropertyValue& aOther) const
|
||||
{
|
||||
return (mValue - aOther.mValue) * kInverseScale;
|
||||
}
|
||||
|
||||
bool operator==(const FontFixedPointValue& aOther) const {
|
||||
return mEncoded == aOther.mEncoded;
|
||||
}
|
||||
|
||||
bool operator!=(const FontFixedPointValue& aOther) const {
|
||||
return mEncoded != aOther.mEncoded;
|
||||
}
|
||||
|
||||
bool operator<(const FontFixedPointValue& aOther) const {
|
||||
return mEncoded < aOther.mEncoded;
|
||||
}
|
||||
|
||||
bool operator<=(const FontFixedPointValue& aOther) const {
|
||||
return mEncoded <= aOther.mEncoded;
|
||||
}
|
||||
|
||||
bool operator>=(const FontFixedPointValue& aOther) const {
|
||||
return mEncoded >= aOther.mEncoded;
|
||||
}
|
||||
|
||||
bool operator>(const FontFixedPointValue& aOther) const {
|
||||
return mEncoded > aOther.mEncoded;
|
||||
}
|
||||
|
||||
int16_t ForHash() const {
|
||||
return mEncoded;
|
||||
/// Return the raw internal representation, for purposes of hashing.
|
||||
T ForHash() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
protected:
|
||||
int16_t mEncoded;
|
||||
typedef T internal_type;
|
||||
|
||||
// Construct from a floating-point or integer value, checking that it is
|
||||
// within the allowed range and converting to fixed-point representation.
|
||||
explicit FontPropertyValue(float aValue)
|
||||
: mValue(std::round(aValue * kScale))
|
||||
{
|
||||
MOZ_ASSERT(aValue >= kMin && aValue <= kMax);
|
||||
}
|
||||
explicit FontPropertyValue(int aValue)
|
||||
: mValue(aValue << kFractionBits)
|
||||
{
|
||||
MOZ_ASSERT(aValue >= Min && aValue <= Max);
|
||||
}
|
||||
|
||||
// Construct directly from a fixed-point value of type T, with no check;
|
||||
// note that there may be special "flag" values that are outside the normal
|
||||
// min/max range (e.g. for font-style:italic, distinct from oblique angle).
|
||||
explicit FontPropertyValue(T aValue)
|
||||
: mValue(aValue)
|
||||
{
|
||||
}
|
||||
|
||||
// This is protected as it may not be the most appropriate accessor for a
|
||||
// given instance to expose. It's up to each individual property to provide
|
||||
// public accessors that forward to this as required.
|
||||
float ToFloat() const { return mValue * kInverseScale; }
|
||||
int ToIntRounded() const { return (mValue + kPointFive) >> FractionBits; }
|
||||
|
||||
static constexpr float kScale = float(1u << FractionBits);
|
||||
static constexpr float kInverseScale = 1.0f / kScale;
|
||||
static constexpr float kMin = float(Min);
|
||||
static constexpr float kMax = float(Max);
|
||||
static const unsigned kFractionBits = FractionBits;
|
||||
|
||||
// Constant representing 0.5 in the internal representation (note this
|
||||
// assumes that kFractionBits is greater than zero!)
|
||||
static const T kPointFive = 1u << (kFractionBits - 1);
|
||||
|
||||
T mValue;
|
||||
};
|
||||
|
||||
class FontWeight : public FontFixedPointValue
|
||||
/**
|
||||
* font-weight: range 1..1000, fractional values permitted; keywords
|
||||
* 'normal', 'bold' aliased to 400, 700 respectively; relative keywords
|
||||
* 'lighter', 'bolder' (not currently handled here).
|
||||
*
|
||||
* We use an unsigned 10.6 fixed-point value (range 0.0 - 1023.984375)
|
||||
*/
|
||||
class FontWeight final : public FontPropertyValue<uint16_t,6,1,1000>
|
||||
{
|
||||
public:
|
||||
// Ugh, to get union in nsCSSValue compiling
|
||||
// See comment in FontPropertyValue regarding requirement for a trivial
|
||||
// default constructor.
|
||||
FontWeight() = default;
|
||||
FontWeight(const FontWeight& aOther) = default;
|
||||
|
||||
// Not currently encoded, but it will be in future
|
||||
explicit FontWeight(int16_t aValue)
|
||||
: FontFixedPointValue(aValue)
|
||||
{}
|
||||
|
||||
explicit FontWeight(int32_t aValue)
|
||||
: FontFixedPointValue(aValue)
|
||||
{}
|
||||
|
||||
explicit FontWeight(float aValue)
|
||||
: FontFixedPointValue(int16_t(aValue))
|
||||
{}
|
||||
|
||||
bool operator==(const FontWeight& aOther) const
|
||||
: FontPropertyValue(aValue)
|
||||
{
|
||||
return mEncoded == aOther.mEncoded;
|
||||
}
|
||||
|
||||
/// The "distance" between two font weights
|
||||
float operator-(const FontWeight& aOther) const {
|
||||
return this->ToFloat() - aOther.ToFloat();
|
||||
/**
|
||||
* CSS font weights can have fractional values, but this constructor exists
|
||||
* for convenience when writing constants such as FontWeight(700) in code.
|
||||
*/
|
||||
explicit FontWeight(int aValue)
|
||||
: FontPropertyValue(aValue)
|
||||
{
|
||||
}
|
||||
|
||||
static FontWeight Thin() {
|
||||
return FontWeight{100};
|
||||
static FontWeight Normal()
|
||||
{
|
||||
return FontWeight(kNormal);
|
||||
}
|
||||
static FontWeight Normal() {
|
||||
return FontWeight{400};
|
||||
|
||||
static FontWeight Thin()
|
||||
{
|
||||
return FontWeight(kThin);
|
||||
}
|
||||
static FontWeight Bold() {
|
||||
return FontWeight{700};
|
||||
|
||||
static FontWeight Bold()
|
||||
{
|
||||
return FontWeight(kBold);
|
||||
}
|
||||
|
||||
bool IsNormal() const { return mValue == kNormal; }
|
||||
bool IsBold() const { return mValue >= kBoldThreshold; }
|
||||
|
||||
float ToFloat() const { return FontPropertyValue::ToFloat(); }
|
||||
int ToIntRounded() const { return FontPropertyValue::ToIntRounded(); }
|
||||
|
||||
private:
|
||||
explicit FontWeight(internal_type aValue)
|
||||
: FontPropertyValue(aValue)
|
||||
{
|
||||
}
|
||||
|
||||
static const internal_type kNormal = 400u << kFractionBits;
|
||||
static const internal_type kBold = 700u << kFractionBits;
|
||||
static const internal_type kBoldThreshold = 600u << kFractionBits;
|
||||
static const internal_type kThin = 100u << kFractionBits;
|
||||
static const internal_type kExtraBold = 900u << kFractionBits;
|
||||
};
|
||||
|
||||
/**
|
||||
* font-stretch is represented as a percentage relative to 'normal'.
|
||||
*
|
||||
* css-fonts says the value must be >= 0%, and normal is 100%. Keywords
|
||||
* from ultra-condensed to ultra-expanded are aliased to percentages
|
||||
* from 50% to 200%; values outside that range are unlikely to be common,
|
||||
* but could occur.
|
||||
*
|
||||
* Like font-weight, we use an unsigned 10.6 fixed-point value (range
|
||||
* 0.0 - 1023.984375).
|
||||
*
|
||||
* We arbitrarily limit here to 1000%. (If that becomes a problem, we
|
||||
* could reduce the number of fractional bits and increase the limit.)
|
||||
*/
|
||||
class FontStretch final : public FontPropertyValue<uint16_t,6,0,1000>
|
||||
{
|
||||
public:
|
||||
// See comment in FontPropertyValue regarding requirement for a trivial
|
||||
// default constructor.
|
||||
FontStretch() = default;
|
||||
|
||||
explicit FontStretch(float aPercent)
|
||||
: FontPropertyValue(aPercent)
|
||||
{
|
||||
}
|
||||
|
||||
static FontStretch Normal()
|
||||
{
|
||||
return FontStretch(kNormal);
|
||||
}
|
||||
static FontStretch UltraCondensed()
|
||||
{
|
||||
return FontStretch(kUltraCondensed);
|
||||
}
|
||||
static FontStretch ExtraCondensed()
|
||||
{
|
||||
return FontStretch(kExtraCondensed);
|
||||
}
|
||||
static FontStretch Condensed()
|
||||
{
|
||||
return FontStretch(kCondensed);
|
||||
}
|
||||
static FontStretch SemiCondensed()
|
||||
{
|
||||
return FontStretch(kSemiCondensed);
|
||||
}
|
||||
static FontStretch SemiExpanded()
|
||||
{
|
||||
return FontStretch(kSemiExpanded);
|
||||
}
|
||||
static FontStretch Expanded()
|
||||
{
|
||||
return FontStretch(kExpanded);
|
||||
}
|
||||
static FontStretch ExtraExpanded()
|
||||
{
|
||||
return FontStretch(kExtraExpanded);
|
||||
}
|
||||
static FontStretch UltraExpanded()
|
||||
{
|
||||
return FontStretch(kUltraExpanded);
|
||||
}
|
||||
|
||||
bool IsNormal() const { return mValue == kNormal; }
|
||||
float Percentage() const { return ToFloat(); }
|
||||
|
||||
private:
|
||||
static const internal_type kUltraCondensed = 50u << kFractionBits;
|
||||
static const internal_type kExtraCondensed = (62u << kFractionBits) + kPointFive;
|
||||
static const internal_type kCondensed = 75u << kFractionBits;
|
||||
static const internal_type kSemiCondensed = (87u << kFractionBits) + kPointFive;
|
||||
static const internal_type kNormal = 100u << kFractionBits;
|
||||
static const internal_type kSemiExpanded = (112u << kFractionBits) + kPointFive;
|
||||
static const internal_type kExpanded = 125u << kFractionBits;
|
||||
static const internal_type kExtraExpanded = 150u << kFractionBits;
|
||||
static const internal_type kUltraExpanded = 200u << kFractionBits;
|
||||
};
|
||||
|
||||
/**
|
||||
* font-style: normal | italic | oblique <angle>?
|
||||
* values of <angle> below -90 or above 90 not permitted
|
||||
* - Use a signed 8.8 fixed-point value
|
||||
* (representable range -128.0 - 127.99609375)
|
||||
* - Define min value (-128.0) as meaning 'normal'
|
||||
* - Define max value (127.99609375) as 'italic'
|
||||
* - Other values represent 'oblique <angle>'
|
||||
* - Note that 'oblique 0deg' is distinct from 'normal' (should it be?)
|
||||
*/
|
||||
class FontStyle final : public FontPropertyValue<int16_t,8,-90,90>
|
||||
{
|
||||
public:
|
||||
// See comment in FontPropertyValue regarding requirement for a trivial
|
||||
// default constructor.
|
||||
FontStyle() = default;
|
||||
|
||||
static FontStyle Normal()
|
||||
{
|
||||
return FontStyle(kNormal);
|
||||
}
|
||||
|
||||
static FontStyle Italic()
|
||||
{
|
||||
return FontStyle(kItalic);
|
||||
}
|
||||
|
||||
static FontStyle Oblique(float aAngle = 14.0f)
|
||||
{
|
||||
return FontStyle(aAngle);
|
||||
}
|
||||
|
||||
bool IsNormal() const { return mValue == kNormal; }
|
||||
bool IsItalic() const { return mValue == kItalic; }
|
||||
bool IsOblique() const { return mValue != kItalic && mValue != kNormal; }
|
||||
|
||||
float ObliqueAngle() const
|
||||
{
|
||||
// It's not meaningful to get the oblique angle from a style that is
|
||||
// actually 'normal' or 'italic'.
|
||||
MOZ_ASSERT(!IsItalic() && !IsNormal());
|
||||
return ToFloat();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit FontStyle(float aAngle)
|
||||
: FontPropertyValue(aAngle)
|
||||
{
|
||||
}
|
||||
|
||||
static const int16_t kNormal = INT16_MIN;
|
||||
static const int16_t kItalic = INT16_MAX;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <dwrite.h>
|
||||
|
||||
static inline DWRITE_FONT_STRETCH
|
||||
DWriteFontStretchFromStretch(int16_t aStretch)
|
||||
DWriteFontStretchFromStretch(uint16_t aStretch)
|
||||
{
|
||||
switch (aStretch) {
|
||||
case NS_FONT_STRETCH_ULTRA_CONDENSED:
|
||||
|
@ -47,8 +47,8 @@ DWriteFontStretchFromStretch(int16_t aStretch)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int16_t
|
||||
FontStretchFromDWriteStretch(DWRITE_FONT_STRETCH aStretch)
|
||||
static inline uint16_t
|
||||
FontStretchFromDWriteStretch(DWRITE_FONT_STRETCH aStretch)
|
||||
{
|
||||
switch (aStretch) {
|
||||
case DWRITE_FONT_STRETCH_ULTRA_CONDENSED:
|
||||
|
|
|
@ -958,7 +958,7 @@ gfxDWriteFontList::GetDefaultFontForPlatform(const gfxFontStyle *aStyle)
|
|||
gfxFontEntry *
|
||||
gfxDWriteFontList::LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
{
|
||||
gfxFontEntry *lookup;
|
||||
|
@ -982,7 +982,7 @@ gfxDWriteFontList::LookupLocalFont(const nsAString& aFontName,
|
|||
gfxFontEntry *
|
||||
gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define GFX_DWRITEFONTLIST_H
|
||||
|
||||
#include "mozilla/FontPropertyTypes.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "gfxDWriteCommon.h"
|
||||
#include "dwrite_3.h"
|
||||
|
@ -118,10 +119,9 @@ public:
|
|||
(dwriteStyle == DWRITE_FONT_STYLE_OBLIQUE ?
|
||||
NS_FONT_STYLE_OBLIQUE : NS_FONT_STYLE_NORMAL));
|
||||
mStretch = FontStretchFromDWriteStretch(aFont->GetStretch());
|
||||
uint16_t weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100);
|
||||
int weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100);
|
||||
|
||||
weight = std::max<uint16_t>(100, weight);
|
||||
weight = std::min<uint16_t>(900, weight);
|
||||
weight = mozilla::Clamp(weight, 100, 900);
|
||||
mWeight = FontWeight(weight);
|
||||
|
||||
mIsCJK = UNINITIALIZED_VALUE;
|
||||
|
@ -141,7 +141,7 @@ public:
|
|||
gfxDWriteFontEntry(const nsAString& aFaceName,
|
||||
IDWriteFont *aFont,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr),
|
||||
mIsSystemFont(false), mForceGDIClassic(false),
|
||||
|
@ -168,7 +168,7 @@ public:
|
|||
IDWriteFontFile *aFontFile,
|
||||
IDWriteFontFileStream *aFontFileStream,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
: gfxFontEntry(aFaceName), mFont(nullptr),
|
||||
mFontFile(aFontFile), mFontFileStream(aFontFileStream),
|
||||
|
@ -405,12 +405,12 @@ public:
|
|||
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle);
|
||||
|
||||
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength);
|
||||
|
|
|
@ -258,7 +258,7 @@ FT2FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold
|
|||
FT2FontEntry*
|
||||
FT2FontEntry::CreateFontEntry(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength)
|
||||
|
@ -371,7 +371,7 @@ FTFaceGetWeight(FT_Face aFace)
|
|||
|
||||
NS_ASSERTION(result >= 100 && result <= 900, "Invalid weight in font!");
|
||||
|
||||
return FontWeight(result);
|
||||
return FontWeight(int(result));
|
||||
}
|
||||
|
||||
// Used to create the font entry for installed faces on the device,
|
||||
|
@ -968,7 +968,7 @@ gfxFT2FontList::AppendFacesFromCachedFaceList(
|
|||
if (!(end = strchr(beginning, ','))) {
|
||||
break;
|
||||
}
|
||||
int32_t stretch = strtol(beginning, nullptr, 10);
|
||||
uint32_t stretch = strtoul(beginning, nullptr, 10);
|
||||
|
||||
FontListEntry fle(familyName, faceName, aFileName,
|
||||
weight, stretch, italic, index);
|
||||
|
@ -1465,7 +1465,7 @@ gfxFT2FontList::InitFontListForPlatform()
|
|||
gfxFontEntry*
|
||||
gfxFT2FontList::LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
{
|
||||
// walk over list of names
|
||||
|
@ -1547,7 +1547,7 @@ gfxFT2FontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle)
|
|||
gfxFontEntry*
|
||||
gfxFT2FontList::MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength)
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
static FT2FontEntry*
|
||||
CreateFontEntry(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength);
|
||||
|
@ -123,12 +123,12 @@ public:
|
|||
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle) override;
|
||||
|
||||
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength) override;
|
||||
|
|
|
@ -312,7 +312,7 @@ CreateFaceForPattern(FcPattern* aPattern)
|
|||
|
||||
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t *aData,
|
||||
uint32_t aLength,
|
||||
|
@ -335,7 +335,7 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
|
|||
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName,
|
||||
FcPattern* aFontPattern,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
: gfxFontEntry(aFaceName), mFontPattern(aFontPattern),
|
||||
mFTFace(nullptr), mFTFaceInitialized(false),
|
||||
|
@ -1858,7 +1858,7 @@ gfxFcPlatformFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle)
|
|||
gfxFontEntry*
|
||||
gfxFcPlatformFontList::LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
{
|
||||
nsAutoString keyName(aFontName);
|
||||
|
@ -1877,7 +1877,7 @@ gfxFcPlatformFontList::LookupLocalFont(const nsAString& aFontName,
|
|||
gfxFontEntry*
|
||||
gfxFcPlatformFontList::MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength)
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
// of the font data and the FT_Face
|
||||
explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t *aData,
|
||||
uint32_t aLength,
|
||||
|
@ -105,7 +105,7 @@ public:
|
|||
explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
|
||||
FcPattern* aFontPattern,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle);
|
||||
|
||||
gfxFontEntry* Clone() const override;
|
||||
|
@ -290,12 +290,12 @@ public:
|
|||
gfxFontEntry*
|
||||
LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch, uint8_t aStyle) override;
|
||||
uint16_t aStretch, uint8_t aStyle) override;
|
||||
|
||||
gfxFontEntry*
|
||||
MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength) override;
|
||||
|
|
|
@ -4125,7 +4125,7 @@ gfxFontStyle::gfxFontStyle() :
|
|||
|
||||
gfxFontStyle::gfxFontStyle(uint8_t aStyle,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
gfxFloat aSize,
|
||||
nsAtom *aLanguage, bool aExplicitLanguage,
|
||||
float aSizeAdjust, bool aSystemFont,
|
||||
|
|
|
@ -79,7 +79,7 @@ struct gfxFontStyle {
|
|||
typedef mozilla::FontWeight FontWeight;
|
||||
|
||||
gfxFontStyle();
|
||||
gfxFontStyle(uint8_t aStyle, FontWeight aWeight, int16_t aStretch,
|
||||
gfxFontStyle(uint8_t aStyle, FontWeight aWeight, uint16_t aStretch,
|
||||
gfxFloat aSize, nsAtom *aLanguage, bool aExplicitLanguage,
|
||||
float aSizeAdjust, bool aSystemFont,
|
||||
bool aPrinterFont,
|
||||
|
@ -142,9 +142,8 @@ struct gfxFontStyle {
|
|||
// The weight of the font: 100, 200, ... 900.
|
||||
FontWeight weight;
|
||||
|
||||
// The stretch of the font (the sum of various NS_FONT_STRETCH_*
|
||||
// constants; see gfxFontConstants.h).
|
||||
int8_t stretch;
|
||||
// The stretch of the font (NS_FONT_STRETCH_*, see gfxFontConstants.h).
|
||||
uint8_t stretch;
|
||||
|
||||
// The style of font (normal, italic, oblique)
|
||||
uint8_t style;
|
||||
|
|
|
@ -21,15 +21,15 @@
|
|||
#define NS_FONT_WEIGHT_BOLD 700
|
||||
#define NS_FONT_WEIGHT_THIN 100
|
||||
|
||||
#define NS_FONT_STRETCH_ULTRA_CONDENSED (-4)
|
||||
#define NS_FONT_STRETCH_EXTRA_CONDENSED (-3)
|
||||
#define NS_FONT_STRETCH_CONDENSED (-2)
|
||||
#define NS_FONT_STRETCH_SEMI_CONDENSED (-1)
|
||||
#define NS_FONT_STRETCH_NORMAL 0
|
||||
#define NS_FONT_STRETCH_SEMI_EXPANDED 1
|
||||
#define NS_FONT_STRETCH_EXPANDED 2
|
||||
#define NS_FONT_STRETCH_EXTRA_EXPANDED 3
|
||||
#define NS_FONT_STRETCH_ULTRA_EXPANDED 4
|
||||
#define NS_FONT_STRETCH_ULTRA_CONDENSED 50
|
||||
#define NS_FONT_STRETCH_EXTRA_CONDENSED 62
|
||||
#define NS_FONT_STRETCH_CONDENSED 75
|
||||
#define NS_FONT_STRETCH_SEMI_CONDENSED 87
|
||||
#define NS_FONT_STRETCH_NORMAL 100
|
||||
#define NS_FONT_STRETCH_SEMI_EXPANDED 112
|
||||
#define NS_FONT_STRETCH_EXPANDED 125
|
||||
#define NS_FONT_STRETCH_EXTRA_EXPANDED 150
|
||||
#define NS_FONT_STRETCH_ULTRA_EXPANDED 200
|
||||
|
||||
#define NS_FONT_SMOOTHING_AUTO 0
|
||||
#define NS_FONT_SMOOTHING_GRAYSCALE 1
|
||||
|
|
|
@ -1190,18 +1190,18 @@ StyleDistance(uint32_t aFontStyle, uint32_t aTargetStyle)
|
|||
return 1; // neither is normal; must be italic vs oblique ==> 1
|
||||
}
|
||||
|
||||
#define REVERSE_STRETCH_DISTANCE 5
|
||||
#define REVERSE_STRETCH_DISTANCE 200
|
||||
|
||||
// stretch distance ==> [0,13]
|
||||
// stretch distance ==> [0,350]
|
||||
static inline uint32_t
|
||||
StretchDistance(int16_t aFontStretch, int16_t aTargetStretch)
|
||||
StretchDistance(int32_t aFontStretch, int32_t aTargetStretch)
|
||||
{
|
||||
int32_t distance = 0;
|
||||
if (aTargetStretch != aFontStretch) {
|
||||
// stretch values are in the range -4 .. +4
|
||||
// if aTargetStretch is positive, we prefer more-positive values;
|
||||
// if zero or negative, prefer more-negative
|
||||
if (aTargetStretch > 0) {
|
||||
// stretch values are in the range 50 .. 200
|
||||
// if aTargetStretch is >100, we prefer larger values;
|
||||
// if <=100, prefer smaller
|
||||
if (aTargetStretch > 100) {
|
||||
distance = (aFontStretch - aTargetStretch);
|
||||
} else {
|
||||
distance = (aTargetStretch - aFontStretch);
|
||||
|
@ -1209,7 +1209,7 @@ StretchDistance(int16_t aFontStretch, int16_t aTargetStretch)
|
|||
// if the computed "distance" here is negative, it means that
|
||||
// aFontEntry lies in the "non-preferred" direction from aTargetStretch,
|
||||
// so we treat that as larger than any preferred-direction distance
|
||||
// (max possible is 4) by adding an extra 5 to the absolute value
|
||||
// (max possible is 150) by adding an extra 200 to the absolute value
|
||||
if (distance < 0) {
|
||||
distance = -distance + REVERSE_STRETCH_DISTANCE;
|
||||
}
|
||||
|
@ -1435,7 +1435,7 @@ gfxFontFamily::CheckForSimpleFamily()
|
|||
return;
|
||||
}
|
||||
|
||||
int16_t firstStretch = mAvailableFonts[0]->Stretch();
|
||||
uint16_t firstStretch = mAvailableFonts[0]->Stretch();
|
||||
|
||||
gfxFontEntry *faces[4] = { 0 };
|
||||
for (uint8_t i = 0; i < count; ++i) {
|
||||
|
|
|
@ -142,7 +142,7 @@ public:
|
|||
virtual nsString RealFaceName();
|
||||
|
||||
FontWeight Weight() const { return mWeight; }
|
||||
int16_t Stretch() const { return mStretch; }
|
||||
uint16_t Stretch() const { return mStretch; }
|
||||
|
||||
bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; }
|
||||
bool IsLocalUserFont() const { return mIsLocalUserFont; }
|
||||
|
@ -150,7 +150,7 @@ public:
|
|||
bool IsItalic() const { return mStyle == NS_FONT_STYLE_ITALIC; }
|
||||
bool IsOblique() const { return mStyle == NS_FONT_STYLE_OBLIQUE; }
|
||||
bool IsUpright() const { return mStyle == NS_FONT_STYLE_NORMAL; }
|
||||
bool IsBold() const { return mWeight >= FontWeight(600); } // bold == weights 600 and above
|
||||
bool IsBold() const { return mWeight.IsBold(); } // bold == weights 600 and above
|
||||
bool IgnoreGDEF() const { return mIgnoreGDEF; }
|
||||
bool IgnoreGSUB() const { return mIgnoreGSUB; }
|
||||
|
||||
|
@ -405,7 +405,7 @@ public:
|
|||
uint32_t mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
|
||||
|
||||
FontWeight mWeight;
|
||||
int16_t mStretch;
|
||||
uint16_t mStretch;
|
||||
|
||||
RefPtr<gfxCharacterMap> mCharacterMap;
|
||||
uint32_t mUVSOffset;
|
||||
|
|
|
@ -445,20 +445,22 @@ gfxGDIFont::FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize)
|
|||
{
|
||||
GDIFontEntry *fe = static_cast<GDIFontEntry*>(GetFontEntry());
|
||||
|
||||
FontWeight weight;
|
||||
// Figure out the lfWeight value to use for GDI font selection,
|
||||
// or zero to use the entry's current LOGFONT value.
|
||||
LONG weight;
|
||||
if (fe->IsUserFont()) {
|
||||
if (fe->IsLocalUserFont()) {
|
||||
// for local user fonts, don't change the original weight
|
||||
// in the entry's logfont, because that could alter the
|
||||
// choice of actual face used (bug 724231)
|
||||
weight = FontWeight(0);
|
||||
weight = 0;
|
||||
} else {
|
||||
// avoid GDI synthetic bold which occurs when weight
|
||||
// specified is >= font data weight + 200
|
||||
weight = mNeedsBold ? FontWeight(700) : FontWeight(200);
|
||||
weight = mNeedsBold ? 700 : 200;
|
||||
}
|
||||
} else {
|
||||
weight = mNeedsBold ? FontWeight(700) : fe->Weight();
|
||||
weight = mNeedsBold ? 700 : fe->Weight().ToIntRounded();
|
||||
}
|
||||
|
||||
fe->FillLogFont(&aLogFont, weight, aSize);
|
||||
|
|
|
@ -117,7 +117,7 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName,
|
|||
gfxWindowsFontType aFontType,
|
||||
uint8_t aStyle,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
gfxUserFontData *aUserFontData)
|
||||
: gfxFontEntry(aFaceName),
|
||||
mFontType(aFontType),
|
||||
|
@ -256,7 +256,7 @@ GDIFontEntry::LookupUnscaledFont(HFONT aFont)
|
|||
|
||||
void
|
||||
GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
|
||||
FontWeight aWeight,
|
||||
LONG aWeight,
|
||||
gfxFloat aSize)
|
||||
{
|
||||
memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW));
|
||||
|
@ -272,8 +272,8 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
|
|||
// for installed families with no bold face, and for downloaded fonts
|
||||
// (but NOT for local user fonts, because it could cause a different,
|
||||
// glyph-incompatible face to be used)
|
||||
if (aWeight.ToFloat() != 0.0f) {
|
||||
aLogFont->lfWeight = LONG(aWeight.ToFloat());
|
||||
if (aWeight != 0) {
|
||||
aLogFont->lfWeight = aWeight;
|
||||
}
|
||||
|
||||
// for non-local() user fonts, we never want to apply italics here;
|
||||
|
@ -396,7 +396,7 @@ GDIFontEntry::CreateFontEntry(const nsAString& aName,
|
|||
gfxWindowsFontType aFontType,
|
||||
uint8_t aStyle,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
gfxUserFontData* aUserFontData)
|
||||
{
|
||||
// jtdfix - need to set charset, unicode ranges, pitch/family
|
||||
|
@ -711,7 +711,7 @@ gfxGDIFontList::EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe,
|
|||
gfxFontEntry*
|
||||
gfxGDIFontList::LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
{
|
||||
gfxFontEntry *lookup;
|
||||
|
@ -737,7 +737,7 @@ gfxGDIFontList::LookupLocalFont(const nsAString& aFontName,
|
|||
fe->mIsLocalUserFont = true;
|
||||
|
||||
// make the new font entry match the userfont entry style characteristics
|
||||
fe->mWeight = (aWeight == FontWeight(0) ? FontWeight(400) : aWeight);
|
||||
fe->mWeight = aWeight;
|
||||
fe->mStyle = aStyle;
|
||||
|
||||
return fe;
|
||||
|
@ -803,7 +803,7 @@ FixupSymbolEncodedFont(uint8_t* aFontData, uint32_t aLength)
|
|||
gfxFontEntry*
|
||||
gfxGDIFontList::MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength)
|
||||
|
@ -867,11 +867,9 @@ gfxGDIFontList::MakePlatformFont(const nsAString& aFontName,
|
|||
|
||||
// make a new font entry using the unique name
|
||||
WinUserFontData *winUserFontData = new WinUserFontData(fontRef);
|
||||
FontWeight w = (aWeight == FontWeight(0) ? FontWeight(400) : aWeight);
|
||||
|
||||
GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName,
|
||||
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
|
||||
aStyle, w, aStretch, winUserFontData);
|
||||
aStyle, aWeight, aStretch, winUserFontData);
|
||||
|
||||
if (fe) {
|
||||
fe->mIsDataUserFont = true;
|
||||
|
|
|
@ -115,7 +115,7 @@ public:
|
|||
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override;
|
||||
|
||||
void FillLogFont(LOGFONTW *aLogFont,
|
||||
FontWeight aWeight,
|
||||
LONG aWeight,
|
||||
gfxFloat aSize);
|
||||
|
||||
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics,
|
||||
|
@ -170,13 +170,13 @@ public:
|
|||
gfxWindowsFontType aFontType,
|
||||
uint8_t aStyle,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
gfxUserFontData* aUserFontData);
|
||||
|
||||
// create a font entry for a font referenced by its fullname
|
||||
static GDIFontEntry* LoadLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle);
|
||||
|
||||
gfxWindowsFontType mFontType;
|
||||
|
@ -188,7 +188,7 @@ protected:
|
|||
friend class gfxGDIFont;
|
||||
|
||||
GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType,
|
||||
uint8_t aStyle, FontWeight aWeight, int16_t aStretch,
|
||||
uint8_t aStyle, FontWeight aWeight, uint16_t aStretch,
|
||||
gfxUserFontData *aUserFontData);
|
||||
|
||||
void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType);
|
||||
|
@ -339,12 +339,12 @@ public:
|
|||
|
||||
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle);
|
||||
|
||||
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength);
|
||||
|
|
|
@ -132,12 +132,12 @@ public:
|
|||
|
||||
gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle) override;
|
||||
|
||||
gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength) override;
|
||||
|
|
|
@ -1534,7 +1534,7 @@ gfxMacPlatformFontList::AppleWeightToCSSWeight(int32_t aAppleWeight)
|
|||
gfxFontEntry*
|
||||
gfxMacPlatformFontList::LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
{
|
||||
nsAutoreleasePool localPool;
|
||||
|
@ -1567,7 +1567,7 @@ static void ReleaseData(void *info, const void *data, size_t size)
|
|||
gfxFontEntry*
|
||||
gfxMacPlatformFontList::MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength)
|
||||
|
|
|
@ -1759,7 +1759,7 @@ gfxPlatform::IsFontFormatSupported(uint32_t aFormatFlags)
|
|||
gfxFontEntry*
|
||||
gfxPlatform::LookupLocalFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
{
|
||||
return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aFontName,
|
||||
|
@ -1771,7 +1771,7 @@ gfxPlatform::LookupLocalFont(const nsAString& aFontName,
|
|||
gfxFontEntry*
|
||||
gfxPlatform::MakePlatformFont(const nsAString& aFontName,
|
||||
FontWeight aWeight,
|
||||
int16_t aStretch,
|
||||
uint16_t aStretch,
|
||||
uint8_t aStyle,
|
||||
const uint8_t* aFontData,
|
||||
uint32_t aLength)
|
||||
|
@ -2730,7 +2730,14 @@ gfxPlatform::UsesOffMainThreadCompositing()
|
|||
bool
|
||||
gfxPlatform::UsesTiling() const
|
||||
{
|
||||
return gfxPrefs::LayersTilesEnabled();
|
||||
bool isSkiaPOMTP = XRE_IsContentProcess() &&
|
||||
GetDefaultContentBackend() == BackendType::SKIA &&
|
||||
gfxVars::UseOMTP() &&
|
||||
(gfxPrefs::LayersOMTPPaintWorkers() == -1 ||
|
||||
gfxPrefs::LayersOMTPPaintWorkers() > 1);
|
||||
|
||||
return gfxPrefs::LayersTilesEnabled() ||
|
||||
(gfxPrefs::LayersTilesEnabledIfSkiaPOMTP() && isSkiaPOMTP);
|
||||
}
|
||||
|
||||
/***
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче