mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
cda04ea11e
@ -1510,10 +1510,11 @@
|
||||
<input />
|
||||
</fieldset>
|
||||
|
||||
<figure id="figure">
|
||||
<img src="../moz.png" alt="An awesome picture">
|
||||
<figcaption id="figcaption">Caption for the awesome picture</figcaption>
|
||||
</figure>
|
||||
<!-- Depending on whether or not the image is cached, layout may be able to
|
||||
optimize away spaces between the figure, img and figcaption tags. As
|
||||
such, we should keep everything on one line to get consistent results.
|
||||
-->
|
||||
<figure id="figure"><img src="../moz.png" alt="An awesome picture"><figcaption id="figcaption">Caption for the awesome picture</figcaption></figure>
|
||||
|
||||
<footer id="footer">Some copyright info</footer>
|
||||
<article>
|
||||
|
@ -234,6 +234,17 @@
|
||||
title="no name from title"/>
|
||||
</markup>
|
||||
|
||||
<!--
|
||||
Disabled due to intermittent failures (bug 1436323) which became more
|
||||
frequent due to the landing of bug 1383682. The latter bug made loading
|
||||
of images from cache much more consistent, which appears to have impacted
|
||||
the timing for this test case. If the image is switched to a unique
|
||||
image (e.g. always decoding since there is no cache), the failure rate
|
||||
increases, presumably because the test is dependent on a specific ordering
|
||||
of events, and implicitly assumes the image is loaded immediately.
|
||||
-->
|
||||
|
||||
<!--
|
||||
<markup id="HTMLInputImageTest"
|
||||
ref="html:input" ruleset="HTMLInputImage">
|
||||
<html:span id="l1" textequiv="test2">test2</html:span>
|
||||
@ -249,6 +260,7 @@
|
||||
data="no name from data"
|
||||
title="name from title"/>
|
||||
</markup>
|
||||
-->
|
||||
|
||||
<markup id="HTMLInputImageNoValidSrcTest"
|
||||
ref="html:input" ruleset="HTMLInputImageNoValidSrc">
|
||||
|
@ -227,7 +227,9 @@
|
||||
<div id="c6">This <abbr title="accessibility">a11y</abbr> test</div>
|
||||
<div id="c7">This <acronym title="personal computer">PC</acronym> is broken</div>
|
||||
|
||||
<!-- only whitespace between images should be exposed -->
|
||||
<div id="c8"> <img src="../moz.png"> <img src="../moz.png"> </div>
|
||||
<!-- Whitespace between images should be exposed. Whitespace between the
|
||||
div and img tags will be inconsistent depending on the image cache
|
||||
state and what optimizations layout was able to apply. -->
|
||||
<div id="c8"><img src="../moz.png"> <img src="../moz.png"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -170,8 +170,11 @@
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="container1"> <img src="../moz.png"> <img id="img1" src="../moz.png"> <img src="../moz.png"> </div>
|
||||
<div> <a id="container2"></a> <a><img src="../moz.png"></a> </div>
|
||||
<!-- Whitespace between the div and img tags will be inconsistent depending
|
||||
on the image cache state and what optimizations layout was able to
|
||||
apply. -->
|
||||
<div id="container1"><img src="../moz.png"> <img id="img1" src="../moz.png"> <img src="../moz.png"></div>
|
||||
<div><a id="container2"></a> <a><img src="../moz.png"></a></div>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
|
@ -1,9 +1,9 @@
|
||||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 13.0
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-12...release-13
|
||||
Commit: https://github.com/devtools-html/debugger.html/commit/3c10bd43b5
|
||||
Version 14.0
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-13...release-14
|
||||
Commit: https://github.com/devtools-html/debugger.html/commit/5805cf467
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
||||
|
@ -956,7 +956,7 @@ menuseparator {
|
||||
.file,
|
||||
.folder,
|
||||
.domain {
|
||||
background-color: var(--theme-splitter-color);
|
||||
background-color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.worker,
|
||||
@ -1022,7 +1022,7 @@ img.arrow {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
padding-top: 9px;
|
||||
background: var(--theme-splitter-color);
|
||||
background: var(--disclosure-arrow);
|
||||
mask-size: 100%;
|
||||
display: inline-block;
|
||||
margin-bottom: 1px;
|
||||
@ -1067,7 +1067,8 @@ html .arrow.expanded svg {
|
||||
fill: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.angular svg, .source-icon svg {
|
||||
.angular svg,
|
||||
.source-icon svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
@ -1095,6 +1096,11 @@ html .arrow.expanded svg {
|
||||
white-space: nowrap;
|
||||
overflow: auto;
|
||||
min-width: 100%;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
align-content: start;
|
||||
|
||||
}
|
||||
|
||||
.managed-tree .tree button {
|
||||
@ -1233,7 +1239,7 @@ html[dir="rtl"] .arrow svg,
|
||||
.close-btn .close {
|
||||
mask: url("chrome://devtools/skin/images/debugger/close.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background-color: var(--theme-comment-alt);
|
||||
background-color: var(--theme-comment);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
transition: all 0.15s ease-in-out;
|
||||
@ -1317,11 +1323,11 @@ html[dir="rtl"] .arrow svg,
|
||||
|
||||
.search-field .magnifying-glass path,
|
||||
.search-field .magnifying-glass ellipse {
|
||||
stroke: var(--theme-splitter-color);
|
||||
stroke: var(--theme-comment);
|
||||
}
|
||||
|
||||
.search-field input::placeholder {
|
||||
color: var(--theme-body-color-inactive);
|
||||
color: var(--theme-toolbar-color);
|
||||
}
|
||||
|
||||
.search-field input:focus {
|
||||
@ -1399,6 +1405,7 @@ html[dir="rtl"] .arrow svg,
|
||||
padding: 4px 0 4px 30px;
|
||||
line-height: 16px;
|
||||
font-size: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.project-text-search .matches-summary {
|
||||
@ -1514,8 +1521,7 @@ html[dir="rtl"] .arrow svg,
|
||||
}
|
||||
|
||||
.sources-list .managed-tree .tree .node {
|
||||
padding: 0px 0px 0px 3px;
|
||||
height: 21px;
|
||||
padding: 0 10px 0 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@ -1531,10 +1537,6 @@ html[dir="rtl"] .arrow svg,
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.theme-dark .sources-list .tree .node:not(.focused) img.arrow {
|
||||
background: var(--theme-content-color3);
|
||||
}
|
||||
|
||||
.theme-dark .source-list .tree .node.focused {
|
||||
background-color: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
@ -1669,7 +1671,7 @@ html[dir="rtl"] .arrow svg,
|
||||
|
||||
.outline-list {
|
||||
list-style-type: none;
|
||||
width: 100%;
|
||||
flex: 1 0 100%;
|
||||
padding: 10px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
@ -1688,19 +1690,18 @@ html[dir="rtl"] .arrow svg,
|
||||
}
|
||||
|
||||
.outline-list__element {
|
||||
padding-bottom: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.2rem;
|
||||
padding: 3px 10px 3px 10px;
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.outline-list__element:hover {
|
||||
background: var(--theme-toolbar-background-hover);
|
||||
.outline-list__element-icon {
|
||||
padding-right: 0.4rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.outline-list__element .function {
|
||||
padding-left: 10px;
|
||||
.outline-list__element:hover {
|
||||
background: var(--theme-toolbar-background-hover);
|
||||
}
|
||||
/* 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
|
||||
@ -1965,7 +1966,7 @@ html .toggle-button.end.vertical svg {
|
||||
}
|
||||
|
||||
.search-bottom-bar .search-modifiers button svg {
|
||||
fill: var(--theme-comment-alt);
|
||||
fill: var(--theme-comment);
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
@ -1997,7 +1998,7 @@ html .toggle-button.end.vertical svg {
|
||||
margin: 0 0 0 6px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--theme-comment-alt);
|
||||
color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.search-bottom-bar .search-type-toggles .search-type-btn:active {
|
||||
@ -2989,8 +2990,7 @@ html .breakpoints-list .breakpoint.paused {
|
||||
.input-expression::placeholder {
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
color: var(--theme-comment-alt);
|
||||
opacity: 1;
|
||||
color: var(--theme-comment);
|
||||
}
|
||||
|
||||
.input-expression:focus {
|
||||
@ -3309,10 +3309,12 @@ html .breakpoints-list .breakpoint.paused {
|
||||
|
||||
:root {
|
||||
--accordion-header-background: var(--theme-toolbar-background);
|
||||
--disclosure-arrow: #b2b2b2;
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
--accordion-header-background: #222225;
|
||||
--disclosure-arrow: #7f7f81;
|
||||
}
|
||||
|
||||
.accordion {
|
||||
@ -3383,6 +3385,10 @@ html .breakpoints-list .breakpoint.paused {
|
||||
.accordion .header-buttons button::-moz-focus-inner {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.accordion .arrow svg {
|
||||
fill: var(--disclosure-arrow);
|
||||
}
|
||||
/* 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/>. */
|
||||
@ -3408,7 +3414,11 @@ img.pause,
|
||||
img.stepOver,
|
||||
img.stepIn,
|
||||
img.stepOut,
|
||||
img.resume {
|
||||
img.resume,
|
||||
img.rewind,
|
||||
img.reverseStepOver,
|
||||
img.reverseStepIn,
|
||||
img.reverseStepOut {
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
@ -3432,6 +3442,26 @@ img.resume {
|
||||
mask: url("chrome://devtools/skin/images/debugger/resume.svg") no-repeat;
|
||||
}
|
||||
|
||||
.command-bar img.rewind {
|
||||
mask: url("chrome://devtools/skin/images/debugger/resume.svg") no-repeat;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.command-bar img.reverseStepOver {
|
||||
mask: url("chrome://devtools/skin/images/debugger/stepOver.svg") no-repeat;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.command-bar img.reverseStepIn {
|
||||
mask: url("chrome://devtools/skin/images/debugger/stepIn.svg") no-repeat;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.command-bar img.reverseStepOut {
|
||||
mask: url("chrome://devtools/skin/images/debugger/stepOut.svg") no-repeat;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.command-bar > .pause-exceptions.uncaught.enabled > img.pause-exceptions {
|
||||
background-color: var(--theme-highlight-purple);
|
||||
}
|
||||
@ -3697,10 +3727,6 @@ img.ignore-exceptions {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.theme-dark .secondary-panes .accordion .arrow svg {
|
||||
fill: var(--theme-content-color3);
|
||||
}
|
||||
|
||||
.secondary-panes .breakpoints-buttons {
|
||||
display: flex;
|
||||
}
|
||||
@ -3734,7 +3760,6 @@ img.ignore-exceptions {
|
||||
padding: 50px 0 0 0;
|
||||
text-align: center;
|
||||
font-size: 1.25em;
|
||||
color: var(--theme-comment-alt);
|
||||
background-color: var(--theme-toolbar-background);
|
||||
font-weight: lighter;
|
||||
z-index: 10;
|
||||
@ -3777,6 +3802,7 @@ img.ignore-exceptions {
|
||||
text-align: left;
|
||||
float: left;
|
||||
margin-left: 25px;
|
||||
color: var(--theme-comment);
|
||||
}
|
||||
|
||||
html .welcomebox .toggle-button-end.collapsed {
|
||||
@ -4033,15 +4059,16 @@ html .welcomebox .toggle-button-end.collapsed {
|
||||
.theme-dark .result-list {
|
||||
background-color: var(--theme-body-background);
|
||||
}
|
||||
.result-item .title .fuzzy-match {
|
||||
.result-item .title .highlight {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.result-item .subtitle .fuzzy-match {
|
||||
.result-item .subtitle .highlight {
|
||||
color: var(--grey-90);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.theme-dark .result-item .title .fuzzy-match,
|
||||
.theme-dark .result-item .subtitle .fuzzy-match {
|
||||
.theme-dark .result-item .title .highlight,
|
||||
.theme-dark .result-item .subtitle .highlight {
|
||||
color: white;
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -33263,7 +33263,24 @@ let symbolDeclarations = new Map();
|
||||
|
||||
function getFunctionParameterNames(path) {
|
||||
if (path.node.params != null) {
|
||||
return path.node.params.map(param => param.name);
|
||||
return path.node.params.map(param => {
|
||||
if (param.type !== "AssignmentPattern") {
|
||||
return param.name;
|
||||
}
|
||||
|
||||
// Parameter with default value
|
||||
if (param.left.type === "Identifier" && param.right.type === "Identifier") {
|
||||
return `${param.left.name} = ${param.right.name}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "StringLiteral") {
|
||||
return `${param.left.name} = ${param.right.value}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "ObjectExpression") {
|
||||
return `${param.left.name} = {}`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "ArrayExpression") {
|
||||
return `${param.left.name} = []`;
|
||||
} else if (param.left.type === "Identifier" && param.right.type === "NullLiteral") {
|
||||
return `${param.left.name} = null`;
|
||||
}
|
||||
});
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@ -33861,7 +33878,7 @@ self.onmessage = workerHandler({
|
||||
getNextStep: _steps.getNextStep,
|
||||
getEmptyLines: _getEmptyLines2.default,
|
||||
hasSyntaxError: _validate.hasSyntaxError,
|
||||
isReactComponent: _frameworks.isReactComponent
|
||||
getFramework: _frameworks.getFramework
|
||||
});
|
||||
|
||||
/***/ }),
|
||||
@ -34598,7 +34615,7 @@ module.exports = findLastIndex;
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isReactComponent = isReactComponent;
|
||||
exports.getFramework = getFramework;
|
||||
|
||||
var _getSymbols = __webpack_require__(1457);
|
||||
|
||||
@ -34606,13 +34623,19 @@ var _getSymbols2 = _interopRequireDefault(_getSymbols);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function isReactComponent(sourceId) {
|
||||
const { imports, classes, callExpressions } = (0, _getSymbols2.default)(sourceId);
|
||||
return (importsReact(imports) || requiresReact(callExpressions)) && extendsComponent(classes);
|
||||
function getFramework(sourceId) {
|
||||
if (isReactComponent(sourceId)) {
|
||||
return "React";
|
||||
}
|
||||
} /* 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 isReactComponent(sourceId) {
|
||||
const { imports, classes, callExpressions } = (0, _getSymbols2.default)(sourceId);
|
||||
return (importsReact(imports) || requiresReact(callExpressions)) && extendsComponent(classes);
|
||||
}
|
||||
|
||||
function importsReact(imports) {
|
||||
return imports.some(importObj => importObj.source === "react" && importObj.specifiers.some(specifier => specifier === "React"));
|
||||
}
|
||||
@ -35266,6 +35289,20 @@ var _getFunctionName2 = _interopRequireDefault(_getFunctionName);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/**
|
||||
* "implicit"
|
||||
* Variables added automaticly like "this" and "arguments"
|
||||
*
|
||||
* "var"
|
||||
* Variables declared with "var" or non-block function declarations
|
||||
*
|
||||
* "let"
|
||||
* Variables declared with "let".
|
||||
*
|
||||
* "const"
|
||||
* Variables declared with "const", imported bindings, or added as const
|
||||
* bindings like inner function expressions and inner class names.
|
||||
*/
|
||||
/* 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/. */
|
||||
@ -35289,7 +35326,7 @@ function isNode(node, type) {
|
||||
return node ? node.type === type : false;
|
||||
}
|
||||
|
||||
function getFunctionScope(scope) {
|
||||
function getVarScope(scope) {
|
||||
let s = scope;
|
||||
while (s.type !== "function" && s.type !== "module") {
|
||||
if (!s.parent) {
|
||||
@ -35361,29 +35398,22 @@ function toParsedScopes(children, sourceId) {
|
||||
return undefined;
|
||||
}
|
||||
return children.map(scope => {
|
||||
// Removing unneed information from TempScope such as parent reference and
|
||||
// name types. We also need to convert BabelLocation to the Location type.
|
||||
// Removing unneed information from TempScope such as parent reference.
|
||||
// We also need to convert BabelLocation to the Location type.
|
||||
const bindings = Object.keys(scope.names).reduce((_bindings, n) => {
|
||||
const nameRefs = scope.names[n];
|
||||
switch (nameRefs.type) {
|
||||
case "var":
|
||||
case "let":
|
||||
case "const":
|
||||
case "param":
|
||||
case "fn":
|
||||
case "import":
|
||||
_bindings[n] = {
|
||||
declarations: nameRefs.declarations.map(({ start, end }) => ({
|
||||
start: fromBabelLocation(start, sourceId),
|
||||
end: fromBabelLocation(end, sourceId)
|
||||
})),
|
||||
refs: nameRefs.refs.map(({ start, end }) => ({
|
||||
start: fromBabelLocation(start, sourceId),
|
||||
end: fromBabelLocation(end, sourceId)
|
||||
}))
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
_bindings[n] = {
|
||||
type: nameRefs.type,
|
||||
declarations: nameRefs.declarations.map(({ start, end }) => ({
|
||||
start: fromBabelLocation(start, sourceId),
|
||||
end: fromBabelLocation(end, sourceId)
|
||||
})),
|
||||
refs: nameRefs.refs.map(({ start, end }) => ({
|
||||
start: fromBabelLocation(start, sourceId),
|
||||
end: fromBabelLocation(end, sourceId)
|
||||
}))
|
||||
};
|
||||
return _bindings;
|
||||
}, Object.create(null));
|
||||
return {
|
||||
@ -35391,7 +35421,7 @@ function toParsedScopes(children, sourceId) {
|
||||
end: fromBabelLocation(scope.loc.end, sourceId),
|
||||
type: scope.type === "module" ? "block" : scope.type,
|
||||
displayName: scope.displayName,
|
||||
bindings,
|
||||
bindings: bindings,
|
||||
children: toParsedScopes(scope.children, sourceId)
|
||||
};
|
||||
});
|
||||
@ -35449,6 +35479,11 @@ function createParseJSScopeVisitor(sourceId) {
|
||||
parent = createTempScope("block", "Lexical Global", parent, location);
|
||||
|
||||
parent = createTempScope("module", "Module", parent, location);
|
||||
parent.names.this = {
|
||||
type: "implicit",
|
||||
declarations: [],
|
||||
refs: []
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (path.isFunction()) {
|
||||
@ -35470,18 +35505,53 @@ function createParseJSScopeVisitor(sourceId) {
|
||||
end: location.end
|
||||
});
|
||||
if (path.isFunctionDeclaration() && isNode(tree.id, "Identifier")) {
|
||||
const functionName = {
|
||||
type: "fn",
|
||||
// This ignores Annex B function declaration hoisting, which
|
||||
// is probably a fine assumption.
|
||||
const fnScope = getVarScope(parent);
|
||||
scope.names[tree.id.name] = {
|
||||
type: fnScope === scope ? "var" : "let",
|
||||
declarations: [tree.id.loc],
|
||||
refs: []
|
||||
};
|
||||
getFunctionScope(parent).names[tree.id.name] = functionName;
|
||||
scope.names[tree.id.name] = functionName;
|
||||
}
|
||||
tree.params.forEach(param => parseDeclarator(param, scope, "param"));
|
||||
tree.params.forEach(param => parseDeclarator(param, scope, "var"));
|
||||
|
||||
if (!path.isArrowFunctionExpression()) {
|
||||
scope.names.this = {
|
||||
type: "implicit",
|
||||
declarations: [],
|
||||
refs: []
|
||||
};
|
||||
scope.names.arguments = {
|
||||
type: "implicit",
|
||||
declarations: [],
|
||||
refs: []
|
||||
};
|
||||
}
|
||||
|
||||
parent = scope;
|
||||
return;
|
||||
}
|
||||
if (path.isClass()) {
|
||||
if (path.isClassDeclaration() && path.get("id").isIdentifier()) {
|
||||
parent.names[tree.id.name] = {
|
||||
type: "let",
|
||||
declarations: [tree.id.loc],
|
||||
refs: []
|
||||
};
|
||||
}
|
||||
|
||||
if (path.get("id").isIdentifier()) {
|
||||
savedParents.set(path, parent);
|
||||
parent = createTempScope("block", "Class", parent, location);
|
||||
|
||||
parent.names[tree.id.name] = {
|
||||
type: "const",
|
||||
declarations: [tree.id.loc],
|
||||
refs: []
|
||||
};
|
||||
}
|
||||
}
|
||||
if (path.isForXStatement() || path.isForStatement()) {
|
||||
const init = tree.init || tree.left;
|
||||
if (isNode(init, "VariableDeclaration") && isLetOrConst(init)) {
|
||||
@ -35499,7 +35569,7 @@ function createParseJSScopeVisitor(sourceId) {
|
||||
if (path.isCatchClause()) {
|
||||
savedParents.set(path, parent);
|
||||
parent = createTempScope("block", "Catch", parent, location);
|
||||
parseDeclarator(tree.param, parent, "param");
|
||||
parseDeclarator(tree.param, parent, "var");
|
||||
return;
|
||||
}
|
||||
if (path.isBlockStatement()) {
|
||||
@ -35510,9 +35580,11 @@ function createParseJSScopeVisitor(sourceId) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (path.isVariableDeclaration()) {
|
||||
if (path.isVariableDeclaration() && (path.node.kind === "var" ||
|
||||
// Lexical declarations in for statements are handled above.
|
||||
!path.parentPath.isForStatement({ init: tree }) || !path.parentPath.isXStatement({ left: tree }))) {
|
||||
// Finds right lexical environment
|
||||
const hoistAt = !isLetOrConst(tree) ? getFunctionScope(parent) : parent;
|
||||
const hoistAt = !isLetOrConst(tree) ? getVarScope(parent) : parent;
|
||||
tree.declarations.forEach(declarator => {
|
||||
parseDeclarator(declarator.id, hoistAt, tree.kind);
|
||||
});
|
||||
@ -35523,7 +35595,7 @@ function createParseJSScopeVisitor(sourceId) {
|
||||
|
||||
path.get("specifiers").forEach(spec => {
|
||||
parent.names[spec.node.local.name] = {
|
||||
type: "import",
|
||||
type: "const",
|
||||
declarations: [spec.node.local.loc],
|
||||
refs: []
|
||||
};
|
||||
@ -35542,10 +35614,26 @@ function createParseJSScopeVisitor(sourceId) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (path.isThisExpression()) {
|
||||
const scope = findIdentifierInScopes(parent, "this");
|
||||
if (scope) {
|
||||
scope.names.this.refs.push(tree.loc);
|
||||
}
|
||||
}
|
||||
|
||||
if (path.parentPath.isClassProperty({ value: tree })) {
|
||||
savedParents.set(path, parent);
|
||||
parent = createTempScope("block", "Class Field", parent, location);
|
||||
parent.names.this = {
|
||||
type: "implicit",
|
||||
declarations: [],
|
||||
refs: []
|
||||
};
|
||||
parent.names.arguments = {
|
||||
type: "implicit",
|
||||
declarations: [],
|
||||
refs: []
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,10 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
async function waitForBreakpointCount(dbg, count) {
|
||||
return waitForState(dbg, state => dbg.selectors.getBreakpoints(state).size === count)
|
||||
return waitForState(
|
||||
dbg,
|
||||
state => dbg.selectors.getBreakpoints(state).size === count
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
|
@ -80,12 +80,12 @@ add_task(async function() {
|
||||
await stepIn(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
await dbg.actions.jumpToMappedSelectedLocation()
|
||||
await dbg.actions.jumpToMappedSelectedLocation();
|
||||
await stepOver(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
assertDebugLine(dbg, 71);
|
||||
|
||||
await dbg.actions.jumpToMappedSelectedLocation()
|
||||
await dbg.actions.jumpToMappedSelectedLocation();
|
||||
await stepOut(dbg);
|
||||
await stepOut(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
@ -29,13 +29,13 @@ add_task(async function() {
|
||||
await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
|
||||
|
||||
// Expand nodes and make sure more sources appear.
|
||||
assertSourceCount(dbg, 2);
|
||||
await assertSourceCount(dbg, 2);
|
||||
await clickElement(dbg, "sourceArrow", 2);
|
||||
|
||||
assertSourceCount(dbg, 7);
|
||||
await assertSourceCount(dbg, 7);
|
||||
await clickElement(dbg, "sourceArrow", 3);
|
||||
|
||||
assertSourceCount(dbg, 8);
|
||||
await assertSourceCount(dbg, 8);
|
||||
|
||||
// Select a source.
|
||||
ok(
|
||||
|
@ -285,9 +285,15 @@ function assertNotPaused(dbg) {
|
||||
* @static
|
||||
*/
|
||||
function assertPausedLocation(dbg) {
|
||||
const { selectors: { getSelectedSource, getVisibleSelectedFrame }, getState } = dbg;
|
||||
const {
|
||||
selectors: { getSelectedSource, getVisibleSelectedFrame },
|
||||
getState
|
||||
} = dbg;
|
||||
|
||||
ok(isSelectedFrameSelected(dbg, getState()), "top frame's source is selected");
|
||||
ok(
|
||||
isSelectedFrameSelected(dbg, getState()),
|
||||
"top frame's source is selected"
|
||||
);
|
||||
|
||||
// Check the pause location
|
||||
const frame = getVisibleSelectedFrame(getState());
|
||||
@ -447,7 +453,7 @@ async function waitForMappedScopes(dbg) {
|
||||
await waitForState(
|
||||
dbg,
|
||||
state => {
|
||||
const scopes = dbg.selectors.getScopes(state);
|
||||
const scopes = dbg.selectors.getSelectedScope(state);
|
||||
return scopes && scopes.sourceBindings;
|
||||
},
|
||||
"mapped scopes"
|
||||
@ -949,14 +955,14 @@ const selectors = {
|
||||
sourceMapLink: ".source-footer .mapped-source",
|
||||
sourcesFooter: ".sources-panel .source-footer",
|
||||
editorFooter: ".editor-pane .source-footer",
|
||||
sourceNode: i => `.sources-list .tree-node:nth-child(${i})`,
|
||||
sourceNode: i => `.sources-list .tree-node:nth-child(${i}) .node`,
|
||||
sourceNodes: ".sources-list .tree-node",
|
||||
sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`,
|
||||
resultItems: ".result-list .result-item",
|
||||
fileMatch: ".managed-tree .result",
|
||||
popup: ".popover",
|
||||
tooltip: ".tooltip",
|
||||
outlineItem: i => `.outline-list__element:nth-child(${i})`,
|
||||
outlineItem: i => `.outline-list__element:nth-child(${i}) .function-signature`,
|
||||
outlineItems: ".outline-list__element"
|
||||
};
|
||||
|
||||
@ -1082,3 +1088,17 @@ function getCM(dbg) {
|
||||
const el = dbg.win.document.querySelector(".CodeMirror");
|
||||
return el.CodeMirror;
|
||||
}
|
||||
|
||||
// NOTE: still experimental, the screenshots might not be exactly correct
|
||||
async function takeScreenshot(dbg) {
|
||||
let canvas = dbg.win.document.createElementNS(
|
||||
"http://www.w3.org/1999/xhtml",
|
||||
"html:canvas"
|
||||
);
|
||||
let context = canvas.getContext("2d");
|
||||
canvas.width = dbg.win.innerWidth;
|
||||
canvas.height = dbg.win.innerHeight;
|
||||
context.drawWindow(dbg.win, 0, 0, canvas.width, canvas.height, "white");
|
||||
await waitForTime(1000);
|
||||
dump(`[SCREENSHOT] ${canvas.toDataURL()}\n`);
|
||||
}
|
||||
|
@ -164,26 +164,38 @@ blackboxCheckboxTooltip2=Toggle blackboxing
|
||||
|
||||
# LOCALIZATION NOTE (sources.search.key2): Key shortcut to open the search for
|
||||
# searching all the source files the debugger has seen.
|
||||
# Do not localize "CmdOrCtrl+P", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
sources.search.key2=CmdOrCtrl+P
|
||||
|
||||
# LOCALIZATION NOTE (sources.search.alt.key): A second key shortcut to open the
|
||||
# search for searching all the source files the debugger has seen.
|
||||
# Do not localize "CmdOrCtrl+O", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
sources.search.alt.key=CmdOrCtrl+O
|
||||
|
||||
# LOCALIZATION NOTE (projectTextSearch.key): A key shortcut to open the
|
||||
# full project text search for searching all the files the debugger has seen.
|
||||
# Do not localize "CmdOrCtrl+Shift+F", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
projectTextSearch.key=CmdOrCtrl+Shift+F
|
||||
|
||||
# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the
|
||||
# modal for searching functions in a file.
|
||||
# Do not localize "CmdOrCtrl+Shift+O", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
functionSearch.key=CmdOrCtrl+Shift+O
|
||||
|
||||
# LOCALIZATION NOTE (toggleBreakpoint.key): A key shortcut to toggle
|
||||
# breakpoints.
|
||||
# Do not localize "CmdOrCtrl+B", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
toggleBreakpoint.key=CmdOrCtrl+B
|
||||
|
||||
# LOCALIZATION NOTE (toggleCondPanel.key): A key shortcut to toggle
|
||||
# the conditional breakpoint panel.
|
||||
# Do not localize "CmdOrCtrl+Shift+B", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
toggleCondPanel.key=CmdOrCtrl+Shift+B
|
||||
|
||||
# LOCALIZATION NOTE (stepOut.key): A key shortcut to
|
||||
@ -216,6 +228,8 @@ sources.noSourcesAvailable=This page has no sources
|
||||
|
||||
# LOCALIZATION NOTE (sourceSearch.search.key2): Key shortcut to open the search
|
||||
# for searching within a the currently opened files in the editor
|
||||
# Do not localize "CmdOrCtrl+F", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
sourceSearch.search.key2=CmdOrCtrl+F
|
||||
|
||||
# LOCALIZATION NOTE (sourceSearch.search.placeholder): placeholder text in
|
||||
@ -224,10 +238,14 @@ sourceSearch.search.placeholder=Search in file…
|
||||
|
||||
# LOCALIZATION NOTE (sourceSearch.search.again.key2): Key shortcut to highlight
|
||||
# the next occurrence of the last search triggered from a source search
|
||||
# Do not localize "CmdOrCtrl+G", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
sourceSearch.search.again.key2=CmdOrCtrl+G
|
||||
|
||||
# LOCALIZATION NOTE (sourceSearch.search.againPrev.key2): Key shortcut to highlight
|
||||
# the previous occurrence of the last search triggered from a source search
|
||||
# Do not localize "CmdOrCtrl+Shift+G", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
sourceSearch.search.againPrev.key2=CmdOrCtrl+Shift+G
|
||||
|
||||
# LOCALIZATION NOTE (sourceSearch.resultsSummary1): Shows a summary of
|
||||
@ -550,16 +568,16 @@ watchExpressions.refreshButton=Refresh
|
||||
# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's
|
||||
# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on
|
||||
# a mac we use the unicode character.
|
||||
welcome.search=%S to search for sources
|
||||
welcome.search=%S To search for sources
|
||||
|
||||
# LOCALIZATION NOTE (welcome.findInFiles): The center pane welcome panel's
|
||||
# search prompt. e.g. cmd+f to search for files. On windows, it's ctrl+shift+f, on
|
||||
# a mac we use the unicode character.
|
||||
welcome.findInFiles=%S to find in files
|
||||
welcome.findInFiles=%S To find in files
|
||||
|
||||
# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome
|
||||
# panel. %S is replaced by the keyboard shortcut to search for functions.
|
||||
welcome.searchFunction=%S to search for functions in file
|
||||
welcome.searchFunction=%S To search for functions in file
|
||||
|
||||
# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search
|
||||
# prompt for searching for files.
|
||||
@ -687,8 +705,10 @@ functionSearchSeparatorLabel=←
|
||||
|
||||
# LOCALIZATION NOTE(gotoLineModal.placeholder): The placeholder
|
||||
# text displayed when the user searches for specific lines in a file
|
||||
# Do not localize "CmdOrCtrl+;", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
gotoLineModal.placeholder=Go to line…
|
||||
gotoLineModal.key=CmdOrCtrl+Shift+;
|
||||
gotoLineModal.key=CmdOrCtrl+;
|
||||
gotoLineModal.title=Go to a line number in a file
|
||||
|
||||
# LOCALIZATION NOTE(symbolSearch.search.functionsPlaceholder): The placeholder
|
||||
@ -703,6 +723,8 @@ symbolSearch.search.variablesPlaceholder.title=Search for a variable in a file
|
||||
|
||||
# LOCALIZATION NOTE(symbolSearch.search.key2): The Key Shortcut for
|
||||
# searching for a function or variable
|
||||
# Do not localize "CmdOrCtrl+Shift+O", or change the format of the string. These are
|
||||
# key identifiers, not messages displayed to the user.
|
||||
symbolSearch.search.key2=CmdOrCtrl+Shift+O
|
||||
|
||||
# LOCALIZATION NOTE(symbolSearch.searchModifier.modifiersLabel): A label
|
||||
@ -825,6 +847,10 @@ shortcuts.stepOut=Step Out
|
||||
# keyboard shortcut action for source file search
|
||||
shortcuts.fileSearch=Source File Search
|
||||
|
||||
# LOCALIZATION NOTE (shortcuts.gotoLine): text describing
|
||||
# keyboard shortcut for jumping to a specific line
|
||||
shortcuts.gotoLine=Go to line
|
||||
|
||||
# LOCALIZATION NOTE (shortcuts.searchAgain): text describing
|
||||
# keyboard shortcut action for searching again
|
||||
shortcuts.searchAgain=Search Again
|
||||
|
@ -45,7 +45,7 @@ pref("devtools.debugger.project-directory-root", "");
|
||||
|
||||
pref("devtools.debugger.features.wasm", true);
|
||||
pref("devtools.debugger.features.shortcuts", true);
|
||||
pref("devtools.debugger.features.root", false);
|
||||
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", false);
|
||||
|
@ -13823,6 +13823,11 @@ class CGDictionary(CGThing):
|
||||
# they're not unrestricted float/double.
|
||||
return not type.isFloat() or not type.isUnrestricted()
|
||||
|
||||
if type.isRecord():
|
||||
# Records are okay, as long as the value type is.
|
||||
# Per spec, only strings are allowed as keys.
|
||||
return CGDictionary.typeSafeToJSONify(type.inner)
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
|
@ -1,20 +0,0 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
|
||||
<script>
|
||||
function boom()
|
||||
{
|
||||
document.getElementById("path").pathSegList.pathSegTypeAsLetter;
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="boom()">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="400px" width="400px">
|
||||
<path id="path" style="stroke: blue" d="M 200.50000,387.89713 L 201.19970,12.500000" />
|
||||
</svg>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,20 +0,0 @@
|
||||
<svg width='100%' height='100%'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
onload='boom()'>
|
||||
|
||||
<html:script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
try {
|
||||
document.getElementById("path").pathSegList.getItem(-10000000);
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
|
||||
</html:script>
|
||||
|
||||
<path id='path' d='M300,25 C320,250 375,150 400,150 S400,340 330,350'/>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 386 B |
@ -1,17 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onload="setTimeout(boom, 30);" class="reftest-wait">
|
||||
|
||||
<script>
|
||||
function boom()
|
||||
{
|
||||
try {
|
||||
document.getElementById("path_1").pathSegList.insertItemBefore({}, 0);
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
|
||||
<path id='path_1' d='M300,25 C500,100 575,300 330,350'/>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 371 B |
@ -1,17 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onload="setTimeout(boom, 30);" class="reftest-wait">
|
||||
|
||||
<script>
|
||||
function boom()
|
||||
{
|
||||
try {
|
||||
document.getElementById("path_1").pathSegList.insertItemBefore({}, 0);
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
</script>
|
||||
|
||||
<path id='path_1' d='M300,25 C500,100 575,300 330,350'/>
|
||||
|
||||
</svg>
|
Before Width: | Height: | Size: 371 B |
@ -1,11 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<path/>
|
||||
|
||||
<script xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
|
||||
var x=document.getElementsByTagName('path')[0];
|
||||
var y = x.pathSegList;
|
||||
var z = x.createSVGPathSegMovetoRel(0,0);
|
||||
y.appendItem(z,0);
|
||||
y.replaceItem(z, 0);
|
||||
]]></script>
|
||||
</svg>
|
Before Width: | Height: | Size: 277 B |
@ -4,14 +4,10 @@ load 336994-1.html
|
||||
load 344888-1.svg
|
||||
load 345445-1.svg
|
||||
load 360836-1.svg
|
||||
load 367357-1.xhtml
|
||||
load 369051-1.svg
|
||||
load 369249-1.svg
|
||||
load 369291-1.svg
|
||||
load 369291-2.svg
|
||||
load 369568-1.svg
|
||||
load 372046-1.svg
|
||||
load 372046-2.svg
|
||||
load 374882-1.svg
|
||||
load 380101-1.svg
|
||||
load 381777-1.svg
|
||||
@ -41,7 +37,6 @@ load 414188-1.svg
|
||||
load 427325-1.svg
|
||||
load 428228-1.svg
|
||||
load 428841-1.svg
|
||||
load 435209-1.svg
|
||||
load 436418-mpathRoot-1.svg
|
||||
load 448244-1.svg
|
||||
load 466576-1.xhtml
|
||||
|
@ -55,8 +55,7 @@ skip-if = true # disabled-for-intermittent-failures--bug-701060
|
||||
[test_object-delayed-intrinsic-size.html]
|
||||
[test_onerror.xhtml]
|
||||
[test_pathAnimInterpolation.xhtml]
|
||||
[test_pathLength.html]
|
||||
[test_pathSeg.xhtml]
|
||||
skip-if = true # We need to polyfill the SVG DOM for path data
|
||||
[test_pointAtLength.xhtml]
|
||||
[test_pointer-events-1a.xhtml]
|
||||
[test_pointer-events-1b.xhtml]
|
||||
@ -77,7 +76,6 @@ skip-if = android_version == '18' # bug 1147994
|
||||
[test_SVGMatrix.xhtml]
|
||||
[test_SVG_namespace_ids.html]
|
||||
[test_SVGNumberList.xhtml]
|
||||
[test_SVGPathSegList.xhtml]
|
||||
[test_SVGPointList.xhtml]
|
||||
[test_SVGStringList.xhtml]
|
||||
[test_SVGStyleElement.xhtml]
|
||||
|
@ -1,128 +0,0 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=611138
|
||||
-->
|
||||
<head>
|
||||
<title>Generic tests for SVG animated length lists</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="MutationEventChecker.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=611138">Mozilla Bug 611138</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display:none;">
|
||||
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100" height="100">
|
||||
<path id="path"/>
|
||||
</svg>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/*
|
||||
This file runs a series of SVGPathSegList specific tests. Generic SVGXxxList
|
||||
tests can be found in test_SVGxxxList.xhtml. Anything that can be generalized
|
||||
to other list types belongs there.
|
||||
*/
|
||||
|
||||
function run_tests()
|
||||
{
|
||||
document.getElementById('svg').pauseAnimations();
|
||||
|
||||
var d;
|
||||
var seg;
|
||||
var path = document.getElementById("path");
|
||||
var list = path.pathSegList;
|
||||
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=611138
|
||||
// Here we are doing a replace with a segment (arc) that has more arguments
|
||||
// than the total number of arguments in the entire path + 2 (the +2
|
||||
// refering to the encoding of the segment types for the two segments).
|
||||
path.setAttribute('d', 'M0,0 L100,100');
|
||||
var arc = path.createSVGPathSegArcAbs(400, 0, 200, 200, 0, 1, 1);
|
||||
list.replaceItem(arc, 1);
|
||||
|
||||
is(list.numberOfItems, 2, 'The length of the list should be the same after a valid replaceItem() call');
|
||||
is(list.getItem(1), arc, 'The inserted object should now be the object at the index being replaced');
|
||||
|
||||
// Test whether and when we normalize the 'd' attribute:
|
||||
|
||||
d = " \n M 10 , 10 \n L 20 10 \n ";
|
||||
path.setAttribute('d', d);
|
||||
is(path.getAttribute('d'), d, "Values passed to setAttribute for the 'd' attribute should not be normalised");
|
||||
list.getItem(1).y = 20;
|
||||
isnot(path.getAttribute('d'), d, "The 'd' attribute should change when its underlying DOM list changes");
|
||||
|
||||
// Test that path manipulations still work even when the path is invalid due
|
||||
// to it not starting with a moveto segment:
|
||||
|
||||
path.setAttribute('d', 'M0,0 L1,1');
|
||||
is(list.numberOfItems, 2, 'setAttribute should result in two items')
|
||||
|
||||
seg = list.getItem(1);
|
||||
list.removeItem(0);
|
||||
ok(list.numberOfItems == 1 && list.getItem(0) == seg,
|
||||
'If removeItem removes the initial moveto leaving an invalid path, the other items should still be left in the list')
|
||||
|
||||
seg = path.createSVGPathSegLinetoAbs(1, 2);
|
||||
list.appendItem(seg);
|
||||
ok(list.numberOfItems == 2 && list.getItem(1) == seg,
|
||||
'appendItem should be able to append to an invalid path');
|
||||
|
||||
seg = path.createSVGPathSegLinetoAbs(1, 2);
|
||||
list.replaceItem(seg, 1);
|
||||
ok(list.numberOfItems == 2 && list.getItem(1) == seg,
|
||||
'replaceItem should be able to replace items in an invalid path');
|
||||
|
||||
seg = path.createSVGPathSegLinetoAbs(1, 2);
|
||||
list.insertItemBefore(seg, 1);
|
||||
ok(list.numberOfItems == 3 && list.getItem(1) == seg,
|
||||
'insertItemBefore should be able insert items into an invalid path');
|
||||
|
||||
seg = path.createSVGPathSegLinetoAbs(1, 2);
|
||||
list.initialize(seg);
|
||||
ok(list.numberOfItems == 1 && list.getItem(0) == seg,
|
||||
'initialize should be able initialize an invalid path with a non-moveto item');
|
||||
|
||||
// Test mutation events
|
||||
|
||||
eventChecker = new MutationEventChecker;
|
||||
d = 'M0,0 L12,34'
|
||||
path.setAttribute('d', d);
|
||||
eventChecker.watchAttr(path, "d");
|
||||
|
||||
// -- Actual changes
|
||||
eventChecker.expect("modify modify modify");
|
||||
list[0].x = 10;
|
||||
list[0].y = 5;
|
||||
path.setAttribute("d", "M20,5 L12,34");
|
||||
|
||||
// -- Redundant changes
|
||||
eventChecker.expect("");
|
||||
list[0].x = 20;
|
||||
list[1].y = 34;
|
||||
path.setAttribute("d", "M20,5 L12,34");
|
||||
|
||||
// -- Attribute removal
|
||||
eventChecker.expect("remove");
|
||||
path.removeAttribute("d");
|
||||
|
||||
// -- Non-existent attribute removal
|
||||
eventChecker.expect("");
|
||||
path.removeAttribute("d");
|
||||
path.removeAttributeNS(null, "d");
|
||||
eventChecker.finish();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", run_tests);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -222,61 +222,6 @@ var tests = [
|
||||
is(itemA.y, itemB.y, message);
|
||||
}
|
||||
},
|
||||
{
|
||||
// SVGPathSegList test:
|
||||
target_element_id: 'path',
|
||||
attr_name: 'd',
|
||||
prop_name: null, // SVGAnimatedPathData is an inherited interface!
|
||||
bv_name: 'pathSegList',
|
||||
av_name: 'animatedPathSegList',
|
||||
el_type: 'SVGPathElement',
|
||||
prop_type: null,
|
||||
list_type: 'SVGPathSegList',
|
||||
item_type: 'SVGPathSeg',
|
||||
attr_val_3a: 'M 10,10 L 50,50 L 90,10',
|
||||
attr_val_3b: 'M 10,50 L 50,10 L 90,50',
|
||||
attr_val_4 : 'M 10,10 L 50,50 L 90,10 M 200,100',
|
||||
attr_val_5a: 'M 10,10 L 50,50 L 90,10 L 130,50 L 170,10',
|
||||
attr_val_5b: 'M 50,10 L 50,10 L 90,50 L 130,10 L 170,50',
|
||||
attr_val_5b_firstItem_x3_constructor: function(constructor) {
|
||||
var expected = constructor();
|
||||
is(expected.pathSegTypeAsLetter, "M",
|
||||
"test error -- expected constructor to generate a segment of type M");
|
||||
expected.x = 150;
|
||||
expected.y = 30;
|
||||
return expected;
|
||||
},
|
||||
item_constructor: function() {
|
||||
// XXX return different values each time
|
||||
return document.getElementById('path').createSVGPathSegMovetoAbs(1, 1);
|
||||
},
|
||||
item_is: function(itemA, itemB, message) {
|
||||
ok(typeof(itemA.pathSegTypeAsLetter) != 'undefined' &&
|
||||
typeof(itemB.pathSegTypeAsLetter) != 'undefined',
|
||||
'expecting pathSegTypeAsLetter property');
|
||||
|
||||
// First: are we dealing with the same type of segment?
|
||||
is(itemA.pathSegTypeAsLetter, itemB.pathSegTypeAsLetter, message);
|
||||
if (itemA.pathSegTypeAsLetter != itemB.pathSegTypeAsLetter)
|
||||
return; // The rest of this function is nonsense if types don't match.
|
||||
|
||||
// Make sure property-counts match (so we can iterate across itemA's
|
||||
// properties and not worry about itemB having extra properties that
|
||||
// we might be skipping over).
|
||||
is(keys(itemA).length, keys(itemB).length,
|
||||
'expecting same property-count when comparing path segs of same type.');
|
||||
|
||||
// Compare the properties, skipping the constant properties inherited
|
||||
// from 'SVGPathSeg', and skipping the pathSegTypeAsLetter field since we
|
||||
// already checked that above.
|
||||
for (var prop in itemA) {
|
||||
if (!SVGPathSeg.hasOwnProperty(prop) &&
|
||||
prop != 'pathSegTypeAsLetter') {
|
||||
is(itemA[prop], itemB[prop], message);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// SVGStringList test:
|
||||
target_element_id: 'g',
|
||||
@ -1170,14 +1115,12 @@ function run_animation_timeline_tests()
|
||||
'in the '+t.list_type+' for '+t.bv_path+' to 5.');
|
||||
|
||||
// TODO
|
||||
if (t.list_type != 'SVGPathSegList') {
|
||||
ok(t.animVal.getItem(3) === t.old_animVal_items[3],
|
||||
'When affected by SMIL animation, list items in the '+t.list_type+
|
||||
' for '+t.bv_path+' that are at indexes that existed prior to the '+
|
||||
'start of the animation should be the exact same objects as the '+
|
||||
'objects that were at those indexes prior to the start of the '+
|
||||
'animation.');
|
||||
}
|
||||
|
||||
t.old_animVal_items = get_array_of_list_items(t.animVal);
|
||||
|
||||
|
@ -48,13 +48,6 @@ var tests = [
|
||||
subtests: [ { values: null, length: 3 },
|
||||
{ values: "10", length: 1 },
|
||||
{ values: "1 2 3 4 5", length: 5 } ] },
|
||||
{ element: path,
|
||||
attribute: "d",
|
||||
listProperty: "pathSegList",
|
||||
type: "SVGPathSegList",
|
||||
subtests: [ { values: null, length: 2 },
|
||||
{ values: "M50,50", length: 1 },
|
||||
{ values: "M0,0 h10 v20 h30 v40", length: 5 } ] },
|
||||
{ element: poly,
|
||||
attribute: "points",
|
||||
listProperty: "animatedPoints",
|
||||
|
@ -1,58 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1024926
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test path length changes when manipulated</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1024926">Mozilla Bug 1024926</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<svg width="100%" height="1" id="svg">
|
||||
<path id="path_lines" d="M50,100l0,0l0,-50l100,0l86.3325,122.665z"></path>
|
||||
<path id="path_straight_curve" d="M0,0 C100,0 150,0 200,0" />
|
||||
<path id="path_straight_arc" d="M0,0 A100,0 0 0 0 200, 0" />
|
||||
</svg>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Test a closed path with a series of lines.
|
||||
var path = document.getElementById("path_lines");
|
||||
is(path.getTotalLength(), 500, "Unexpected path length");
|
||||
|
||||
// Test a path that's been shortened via the DOM.
|
||||
for (var i = 0; i < 2; i++) {
|
||||
path.pathSegList.removeItem(path.pathSegList.numberOfItems - 1);
|
||||
}
|
||||
is(path.getTotalLength(), 150, "Unexpected path length");
|
||||
|
||||
// Test a path that's been shortened to be empty, via the DOM.
|
||||
while (path.pathSegList.numberOfItems > 0) {
|
||||
path.pathSegList.removeItem(0);
|
||||
}
|
||||
is(path.getTotalLength(), 0, "Unexpected path length");
|
||||
|
||||
// Test a path with a curve command ("C") that is really a straight line.
|
||||
path = document.getElementById("path_straight_curve");
|
||||
is(path.getTotalLength(), 200, "Unexpected path length, for straight line " +
|
||||
"generated by 'C' command");
|
||||
|
||||
// Test a path with an arc command ("A") that is really a straight line.
|
||||
path = document.getElementById("path_straight_arc");
|
||||
is(path.getTotalLength(), 200, "Unexpected path length, for straight line " +
|
||||
"generated by 'A' command");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,142 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=459953
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 459953</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=459953">Mozilla Bug 459953</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runTest()
|
||||
{
|
||||
var svgns="http://www.w3.org/2000/svg";
|
||||
|
||||
var path1=document.createElementNS(svgns, "path");
|
||||
|
||||
var sseg;
|
||||
|
||||
var a=10,s=20,d=30,z=9; //Arbitrary numbers for arguments
|
||||
|
||||
var whatever=true; //This is often so, but here it does not matter
|
||||
|
||||
sseg=path1.createSVGPathSegMovetoAbs(a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegMovetoRel(a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegLinetoAbs(a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegLinetoRel(a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegLinetoVerticalAbs(a);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegLinetoVerticalRel(a);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegLinetoHorizontalAbs(a);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegLinetoHorizontalRel(a);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoCubicAbs(a, s, d, z, a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoCubicRel(a, s, d, z, a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoCubicSmoothAbs(a, s, d, z);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoCubicSmoothRel(a, s, d, z);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoQuadraticAbs(a, s, d, z);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoQuadraticRel(a, s, d, z);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoQuadraticSmoothAbs(a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegCurvetoQuadraticSmoothRel(a, s);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegArcAbs(a, s, d, z, a, whatever, whatever);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegArcRel(a, s, d, z, a, whatever, whatever);
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
sseg=path1.createSVGPathSegClosePath();
|
||||
path1.pathSegList.appendItem(sseg);
|
||||
|
||||
for(var i=0;i<path1.pathSegList.numberOfItems;i++){
|
||||
var seg=path1.pathSegList.getItem(i);
|
||||
switch(seg.pathSegType){
|
||||
case seg.PATHSEG_MOVETO_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "M", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_MOVETO_REL:
|
||||
is(seg.pathSegTypeAsLetter, "m", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CLOSEPATH:
|
||||
is(seg.pathSegTypeAsLetter, "z", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_LINETO_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "L", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_LINETO_REL:
|
||||
is(seg.pathSegTypeAsLetter, "l", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_LINETO_VERTICAL_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "V", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_LINETO_VERTICAL_REL:
|
||||
is(seg.pathSegTypeAsLetter, "v", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_LINETO_HORIZONTAL_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "H", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_LINETO_HORIZONTAL_REL:
|
||||
is(seg.pathSegTypeAsLetter, "h", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_CUBIC_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "C", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_CUBIC_REL:
|
||||
is(seg.pathSegTypeAsLetter, "c", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "S", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
|
||||
is(seg.pathSegTypeAsLetter, "s", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_QUADRATIC_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "Q", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_QUADRATIC_REL:
|
||||
is(seg.pathSegTypeAsLetter, "q", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "T", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
|
||||
is(seg.pathSegTypeAsLetter, "t", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_ARC_ABS:
|
||||
is(seg.pathSegTypeAsLetter, "A", "wrong path segment letter");
|
||||
break;
|
||||
case seg.PATHSEG_ARC_REL:
|
||||
is(seg.pathSegTypeAsLetter, "a", "wrong path segment letter");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", runTest);
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1026,48 +1026,8 @@ var interfaceNamesInGlobalScope =
|
||||
{name: "SVGNumberList", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathElement", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSeg", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegArcAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegArcRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegClosePath", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoCubicAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoCubicRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoCubicSmoothAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoCubicSmoothRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoQuadraticAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoQuadraticRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoQuadraticSmoothAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegCurvetoQuadraticSmoothRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegLinetoAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegLinetoHorizontalAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegLinetoHorizontalRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegLinetoRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegLinetoVerticalAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegLinetoVerticalRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegList", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegMovetoAbs", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPathSegMovetoRel", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SVGPatternElement", insecureContext: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
@ -2113,10 +2113,10 @@ nsWebBrowserPersist::CalculateUniqueFilename(nsIURI *aURI, nsCOMPtr<nsIURI>& aOu
|
||||
localFile->SetLeafName(filenameAsUnichar);
|
||||
|
||||
// Resync the URI with the file after the extension has been appended
|
||||
return NS_MutateURI(aURI)
|
||||
.Apply<nsIFileURLMutator>(&nsIFileURLMutator::SetFile,
|
||||
localFile)
|
||||
.Finalize(aOutURI);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURI, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
fileURL->SetFile(localFile); // this should recalculate uri
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2292,10 +2292,9 @@ nsWebBrowserPersist::CalculateAndAppendFileExt(nsIURI *aURI,
|
||||
localFile->SetLeafName(NS_ConvertUTF8toUTF16(newFileName));
|
||||
|
||||
// Resync the URI with the file after the extension has been appended
|
||||
return NS_MutateURI(aURI)
|
||||
.Apply<nsIFileURLMutator>(&nsIFileURLMutator::SetFile,
|
||||
localFile)
|
||||
.Finalize(aOutURI);
|
||||
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURI, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
fileURL->SetFile(localFile); // this should recalculate uri
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -12,44 +12,6 @@
|
||||
interface SVGPathElement : SVGGeometryElement {
|
||||
|
||||
unsigned long getPathSegAtLength(float distance);
|
||||
[NewObject]
|
||||
SVGPathSegClosePath createSVGPathSegClosePath();
|
||||
[NewObject]
|
||||
SVGPathSegMovetoAbs createSVGPathSegMovetoAbs(float x, float y);
|
||||
[NewObject]
|
||||
SVGPathSegMovetoRel createSVGPathSegMovetoRel(float x, float y);
|
||||
[NewObject]
|
||||
SVGPathSegLinetoAbs createSVGPathSegLinetoAbs(float x, float y);
|
||||
[NewObject]
|
||||
SVGPathSegLinetoRel createSVGPathSegLinetoRel(float x, float y);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoCubicAbs createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoCubicRel createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoQuadraticAbs createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoQuadraticRel createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1);
|
||||
[NewObject]
|
||||
SVGPathSegArcAbs createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, boolean largeArcFlag, boolean sweepFlag);
|
||||
[NewObject]
|
||||
SVGPathSegArcRel createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, boolean largeArcFlag, boolean sweepFlag);
|
||||
[NewObject]
|
||||
SVGPathSegLinetoHorizontalAbs createSVGPathSegLinetoHorizontalAbs(float x);
|
||||
[NewObject]
|
||||
SVGPathSegLinetoHorizontalRel createSVGPathSegLinetoHorizontalRel(float x);
|
||||
[NewObject]
|
||||
SVGPathSegLinetoVerticalAbs createSVGPathSegLinetoVerticalAbs(float y);
|
||||
[NewObject]
|
||||
SVGPathSegLinetoVerticalRel createSVGPathSegLinetoVerticalRel(float y);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoCubicSmoothAbs createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoCubicSmoothRel createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoQuadraticSmoothAbs createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y);
|
||||
[NewObject]
|
||||
SVGPathSegCurvetoQuadraticSmoothRel createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y);
|
||||
};
|
||||
|
||||
SVGPathElement implements SVGAnimatedPathData;
|
||||
|
@ -10,6 +10,7 @@
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSeg {
|
||||
|
||||
// Path Segment Types
|
||||
@ -40,9 +41,11 @@ interface SVGPathSeg {
|
||||
readonly attribute DOMString pathSegTypeAsLetter;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegClosePath : SVGPathSeg {
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegMovetoAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -50,6 +53,7 @@ interface SVGPathSegMovetoAbs : SVGPathSeg {
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegMovetoRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -57,6 +61,7 @@ interface SVGPathSegMovetoRel : SVGPathSeg {
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegLinetoAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -64,6 +69,7 @@ interface SVGPathSegLinetoAbs : SVGPathSeg {
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegLinetoRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -71,6 +77,7 @@ interface SVGPathSegLinetoRel : SVGPathSeg {
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoCubicAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -86,6 +93,7 @@ interface SVGPathSegCurvetoCubicAbs : SVGPathSeg {
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoCubicRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -101,6 +109,7 @@ interface SVGPathSegCurvetoCubicRel : SVGPathSeg {
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoQuadraticAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -112,6 +121,7 @@ interface SVGPathSegCurvetoQuadraticAbs : SVGPathSeg {
|
||||
attribute float y1;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoQuadraticRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -123,6 +133,7 @@ interface SVGPathSegCurvetoQuadraticRel : SVGPathSeg {
|
||||
attribute float y1;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegArcAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -140,6 +151,7 @@ interface SVGPathSegArcAbs : SVGPathSeg {
|
||||
attribute boolean sweepFlag;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegArcRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -157,26 +169,31 @@ interface SVGPathSegArcRel : SVGPathSeg {
|
||||
attribute boolean sweepFlag;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegLinetoHorizontalAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegLinetoHorizontalRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegLinetoVerticalAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegLinetoVerticalRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoCubicSmoothAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -188,6 +205,7 @@ interface SVGPathSegCurvetoCubicSmoothAbs : SVGPathSeg {
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoCubicSmoothRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -199,6 +217,7 @@ interface SVGPathSegCurvetoCubicSmoothRel : SVGPathSeg {
|
||||
attribute float y2;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoQuadraticSmoothAbs : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
@ -206,6 +225,7 @@ interface SVGPathSegCurvetoQuadraticSmoothAbs : SVGPathSeg {
|
||||
attribute float y;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface SVGPathSegCurvetoQuadraticSmoothRel : SVGPathSeg {
|
||||
[SetterThrows]
|
||||
attribute float x;
|
||||
|
@ -13,19 +13,7 @@
|
||||
interface SVGPathSegList {
|
||||
readonly attribute unsigned long numberOfItems;
|
||||
[Throws]
|
||||
void clear();
|
||||
[Throws]
|
||||
SVGPathSeg initialize(SVGPathSeg newItem);
|
||||
[Throws]
|
||||
getter SVGPathSeg getItem(unsigned long index);
|
||||
[Throws]
|
||||
SVGPathSeg insertItemBefore(SVGPathSeg newItem, unsigned long index);
|
||||
[Throws]
|
||||
SVGPathSeg replaceItem(SVGPathSeg newItem, unsigned long index);
|
||||
[Throws]
|
||||
SVGPathSeg removeItem(unsigned long index);
|
||||
[Throws]
|
||||
SVGPathSeg appendItem(SVGPathSeg newItem);
|
||||
|
||||
// Mozilla-specific stuff
|
||||
readonly attribute unsigned long length; // synonym for numberOfItems
|
||||
|
@ -55,8 +55,7 @@ dictionary MakePublicKeyCredentialOptions {
|
||||
sequence<PublicKeyCredentialDescriptor> excludeCredentials = [];
|
||||
AuthenticatorSelectionCriteria authenticatorSelection;
|
||||
AttestationConveyancePreference attestation = "none";
|
||||
// Extensions are not supported yet.
|
||||
// AuthenticationExtensions extensions; // Add in Bug 1406458
|
||||
AuthenticationExtensionsClientInputs extensions;
|
||||
};
|
||||
|
||||
dictionary PublicKeyCredentialEntity {
|
||||
@ -102,11 +101,16 @@ dictionary PublicKeyCredentialRequestOptions {
|
||||
USVString rpId;
|
||||
sequence<PublicKeyCredentialDescriptor> allowCredentials = [];
|
||||
UserVerificationRequirement userVerification = "preferred";
|
||||
// Extensions are not supported yet.
|
||||
// AuthenticationExtensions extensions; // Add in Bug 1406458
|
||||
AuthenticationExtensionsClientInputs extensions;
|
||||
};
|
||||
|
||||
typedef record<DOMString, any> AuthenticationExtensions;
|
||||
dictionary AuthenticationExtensionsClientInputs {
|
||||
};
|
||||
|
||||
dictionary AuthenticationExtensionsClientOutputs {
|
||||
};
|
||||
|
||||
typedef record<DOMString, DOMString> AuthenticationExtensionsAuthenticatorInputs;
|
||||
|
||||
dictionary CollectedClientData {
|
||||
required DOMString type;
|
||||
@ -114,9 +118,8 @@ dictionary CollectedClientData {
|
||||
required DOMString origin;
|
||||
required DOMString hashAlgorithm;
|
||||
DOMString tokenBindingId;
|
||||
// Extensions are not supported yet.
|
||||
// AuthenticationExtensions clientExtensions; // Add in Bug 1406458
|
||||
// AuthenticationExtensions authenticatorExtensions; // Add in Bug 1406458
|
||||
AuthenticationExtensionsClientInputs clientExtensions;
|
||||
AuthenticationExtensionsAuthenticatorInputs authenticatorExtensions;
|
||||
};
|
||||
|
||||
enum PublicKeyCredentialType {
|
||||
|
@ -761,7 +761,7 @@ protected:
|
||||
friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
|
||||
friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
|
||||
friend already_AddRefed<TextureHost> CreateTextureHostWithBackend(
|
||||
TextureClient*, LayersBackend&);
|
||||
TextureClient*, ISurfaceAllocator*, LayersBackend&);
|
||||
|
||||
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
|
||||
public:
|
||||
|
@ -116,15 +116,9 @@ TextureHost::CreateIPDLActor(HostIPCAllocator* aAllocator,
|
||||
uint64_t aSerial,
|
||||
const wr::MaybeExternalImageId& aExternalImageId)
|
||||
{
|
||||
if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
|
||||
aSharedData.get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::Tuintptr_t &&
|
||||
!aAllocator->IsSameProcess())
|
||||
{
|
||||
NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
|
||||
return nullptr;
|
||||
}
|
||||
TextureParent* actor = new TextureParent(aAllocator, aSerial, aExternalImageId);
|
||||
if (!actor->Init(aSharedData, aLayersBackend, aFlags)) {
|
||||
actor->ActorDestroy(ipc::IProtocol::ActorDestroyReason::FailedConstructor);
|
||||
delete actor;
|
||||
return nullptr;
|
||||
}
|
||||
@ -232,6 +226,11 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
|
||||
|
||||
#ifdef MOZ_X11
|
||||
case SurfaceDescriptor::TSurfaceDescriptorX11: {
|
||||
if (!aDeallocator->IsSameProcess()) {
|
||||
NS_ERROR("A client process is trying to peek at our address space using a X11Texture!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SurfaceDescriptorX11& desc = aDesc.get_SurfaceDescriptorX11();
|
||||
result = MakeAndAddRef<X11TextureHost>(aFlags, desc);
|
||||
break;
|
||||
@ -248,7 +247,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
|
||||
MOZ_CRASH("GFX: Unsupported Surface type host");
|
||||
}
|
||||
|
||||
if (WrapWithWebRenderTextureHost(aDeallocator, aBackend, aFlags)) {
|
||||
if (result && WrapWithWebRenderTextureHost(aDeallocator, aBackend, aFlags)) {
|
||||
MOZ_ASSERT(aExternalImageId.isSome());
|
||||
result = new WebRenderTextureHost(aDesc, aFlags, result, aExternalImageId.ref());
|
||||
}
|
||||
@ -269,13 +268,50 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
|
||||
const MemoryOrShmem& data = bufferDesc.data();
|
||||
switch (data.type()) {
|
||||
case MemoryOrShmem::TShmem: {
|
||||
result = new ShmemTextureHost(data.get_Shmem(),
|
||||
bufferDesc.desc(),
|
||||
aDeallocator,
|
||||
aFlags);
|
||||
const ipc::Shmem& shmem = data.get_Shmem();
|
||||
const BufferDescriptor& desc = bufferDesc.desc();
|
||||
if (!shmem.IsReadable()) {
|
||||
// We failed to map the shmem so we can't verify its size. This
|
||||
// should not be a fatal error, so just create the texture with
|
||||
// nothing backing it.
|
||||
result = new ShmemTextureHost(shmem, desc, aDeallocator, aFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
size_t bufSize = shmem.Size<char>();
|
||||
size_t reqSize = SIZE_MAX;
|
||||
switch (desc.type()) {
|
||||
case BufferDescriptor::TYCbCrDescriptor: {
|
||||
const YCbCrDescriptor& ycbcr = desc.get_YCbCrDescriptor();
|
||||
reqSize =
|
||||
ImageDataSerializer::ComputeYCbCrBufferSize(ycbcr.ySize(), ycbcr.yStride(),
|
||||
ycbcr.cbCrSize(), ycbcr.cbCrStride());
|
||||
break;
|
||||
}
|
||||
case BufferDescriptor::TRGBDescriptor: {
|
||||
const RGBDescriptor& rgb = desc.get_RGBDescriptor();
|
||||
reqSize = ImageDataSerializer::ComputeRGBBufferSize(rgb.size(), rgb.format());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gfxCriticalError() << "Bad buffer host descriptor " << (int)desc.type();
|
||||
MOZ_CRASH("GFX: Bad descriptor");
|
||||
}
|
||||
|
||||
if (bufSize < reqSize) {
|
||||
NS_ERROR("A client process gave a shmem too small to fit for its descriptor!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result = new ShmemTextureHost(shmem, desc, aDeallocator, aFlags);
|
||||
break;
|
||||
}
|
||||
case MemoryOrShmem::Tuintptr_t: {
|
||||
if (!aDeallocator->IsSameProcess()) {
|
||||
NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(data.get_uintptr_t()),
|
||||
bufferDesc.desc(),
|
||||
aFlags);
|
||||
@ -293,6 +329,11 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
case SurfaceDescriptor::TSurfaceDescriptorDIB: {
|
||||
if (!aDeallocator->IsSameProcess()) {
|
||||
NS_ERROR("A client process is trying to peek at our address space using a DIBTexture!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result = new DIBTextureHost(aFlags, aDesc);
|
||||
break;
|
||||
}
|
||||
|
@ -23,10 +23,9 @@ X11TextureHost::X11TextureHost(TextureFlags aFlags,
|
||||
const SurfaceDescriptorX11& aDescriptor)
|
||||
: TextureHost(aFlags)
|
||||
{
|
||||
RefPtr<gfxXlibSurface> surface = aDescriptor.OpenForeign();
|
||||
mSurface = surface.get();
|
||||
mSurface = aDescriptor.OpenForeign();
|
||||
|
||||
if (!(aFlags & TextureFlags::DEALLOCATE_CLIENT)) {
|
||||
if (mSurface && !(aFlags & TextureFlags::DEALLOCATE_CLIENT)) {
|
||||
mSurface->TakePixmap();
|
||||
}
|
||||
}
|
||||
@ -34,7 +33,7 @@ X11TextureHost::X11TextureHost(TextureFlags aFlags,
|
||||
bool
|
||||
X11TextureHost::Lock()
|
||||
{
|
||||
if (!mCompositor) {
|
||||
if (!mCompositor || !mSurface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -75,6 +74,9 @@ X11TextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
|
||||
SurfaceFormat
|
||||
X11TextureHost::GetFormat() const
|
||||
{
|
||||
if (!mSurface) {
|
||||
return SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
gfxContentType type = mSurface->GetContentType();
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
if (mCompositor->GetBackendType() == LayersBackend::LAYERS_OPENGL) {
|
||||
@ -87,6 +89,9 @@ X11TextureHost::GetFormat() const
|
||||
IntSize
|
||||
X11TextureHost::GetSize() const
|
||||
{
|
||||
if (!mSurface) {
|
||||
return IntSize();
|
||||
}
|
||||
return mSurface->GetSize();
|
||||
}
|
||||
|
||||
|
@ -763,10 +763,6 @@ CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aBackend, aFlags);
|
||||
break;
|
||||
}
|
||||
case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
|
||||
result = new DXGITextureHostD3D11(aFlags,
|
||||
aDesc.get_SurfaceDescriptorD3D10());
|
||||
@ -778,7 +774,7 @@ CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NS_WARNING("Unsupported SurfaceDescriptor type");
|
||||
MOZ_ASSERT_UNREACHABLE("Unsupported SurfaceDescriptor type");
|
||||
}
|
||||
}
|
||||
return result.forget();
|
||||
|
@ -32,6 +32,8 @@ MacIOSurfaceTextureHostOGL::~MacIOSurfaceTextureHostOGL()
|
||||
GLTextureSource*
|
||||
MacIOSurfaceTextureHostOGL::CreateTextureSourceForPlane(size_t aPlane)
|
||||
{
|
||||
MOZ_ASSERT(mSurface);
|
||||
|
||||
GLuint textureHandle;
|
||||
gl::GLContext* gl = mProvider->GetGLContext();
|
||||
gl->fGenTextures(1, &textureHandle);
|
||||
@ -94,11 +96,17 @@ MacIOSurfaceTextureHostOGL::SetTextureSourceProvider(TextureSourceProvider* aPro
|
||||
|
||||
gfx::SurfaceFormat
|
||||
MacIOSurfaceTextureHostOGL::GetFormat() const {
|
||||
if (!mSurface) {
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
return mSurface->GetFormat();
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
MacIOSurfaceTextureHostOGL::GetReadFormat() const {
|
||||
if (!mSurface) {
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
return mSurface->GetReadFormat();
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,6 @@
|
||||
#include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
|
||||
#endif
|
||||
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
#include "mozilla/layers/X11TextureHost.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
@ -46,14 +42,6 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc,
|
||||
aDeallocator,
|
||||
aBackend,
|
||||
aFlags);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
case SurfaceDescriptor::TSurfaceTextureDescriptor: {
|
||||
const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
|
||||
@ -88,14 +76,6 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
case SurfaceDescriptor::TSurfaceDescriptorX11: {
|
||||
const auto& desc = aDesc.get_SurfaceDescriptorX11();
|
||||
result = new X11TextureHost(aFlags, desc);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: {
|
||||
const auto& desc = aDesc.get_SurfaceDescriptorSharedGLTexture();
|
||||
result = new GLTextureHost(aFlags, desc.texture(),
|
||||
@ -105,7 +85,10 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
|
||||
desc.hasAlpha());
|
||||
break;
|
||||
}
|
||||
default: return nullptr;
|
||||
default: {
|
||||
MOZ_ASSERT_UNREACHABLE("Unsupported SurfaceDescriptor type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
@ -8,6 +8,22 @@
|
||||
|
||||
#include "Layers.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class TestSurfaceAllocator final : public ISurfaceAllocator
|
||||
{
|
||||
public:
|
||||
TestSurfaceAllocator() {}
|
||||
~TestSurfaceAllocator() override {}
|
||||
|
||||
bool IsSameProcess() const override { return true; }
|
||||
};
|
||||
|
||||
} // layers
|
||||
} // mozilla
|
||||
|
||||
/* Create layer tree from a simple layer tree description syntax.
|
||||
* Each index is either the first letter of the layer type or
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/TextureHost.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "TestLayers.h"
|
||||
#include "TextureHelper.h"
|
||||
|
||||
using mozilla::gfx::Feature;
|
||||
@ -22,6 +23,7 @@ using mozilla::layers::BasicCompositor;
|
||||
using mozilla::layers::Compositor;
|
||||
using mozilla::layers::CompositorOptions;
|
||||
using mozilla::layers::LayersBackend;
|
||||
using mozilla::layers::TestSurfaceAllocator;
|
||||
using mozilla::layers::TextureClient;
|
||||
using mozilla::layers::TextureHost;
|
||||
using mozilla::widget::CompositorWidget;
|
||||
@ -31,8 +33,9 @@ using mozilla::widget::InProcessCompositorWidget;
|
||||
* This function will create the possible TextureClient and TextureHost pairs
|
||||
* according to the given backend.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
CreateTextureWithBackend(LayersBackend& aLayersBackend,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
nsTArray<RefPtr<TextureClient>>& aTextureClients,
|
||||
nsTArray<RefPtr<TextureHost>>& aTextureHosts)
|
||||
{
|
||||
@ -43,7 +46,8 @@ CreateTextureWithBackend(LayersBackend& aLayersBackend,
|
||||
|
||||
for (uint32_t i = 0; i < aTextureClients.Length(); i++) {
|
||||
aTextureHosts.AppendElement(
|
||||
CreateTextureHostWithBackend(aTextureClients[i], aLayersBackend));
|
||||
CreateTextureHostWithBackend(aTextureClients[i], aDeallocator,
|
||||
aLayersBackend));
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,13 +119,15 @@ CheckCompatibilityWithBasicCompositor(LayersBackend aBackends,
|
||||
TEST(Gfx, TestTextureCompatibility)
|
||||
{
|
||||
nsTArray<LayersBackend> backendHints;
|
||||
RefPtr<TestSurfaceAllocator> deallocator = new TestSurfaceAllocator();
|
||||
|
||||
GetPlatformBackends(backendHints);
|
||||
for (uint32_t i = 0; i < backendHints.Length(); i++) {
|
||||
nsTArray<RefPtr<TextureClient>> textureClients;
|
||||
nsTArray<RefPtr<TextureHost>> textureHosts;
|
||||
|
||||
CreateTextureWithBackend(backendHints[i], textureClients, textureHosts);
|
||||
CreateTextureWithBackend(backendHints[i], deallocator,
|
||||
textureClients, textureHosts);
|
||||
CheckCompatibilityWithBasicCompositor(backendHints[i], textureHosts);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "TestLayers.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
@ -147,7 +148,8 @@ void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface)
|
||||
ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
|
||||
|
||||
// host deserialization
|
||||
RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, nullptr,
|
||||
RefPtr<TestSurfaceAllocator> deallocator = new TestSurfaceAllocator();
|
||||
RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, deallocator,
|
||||
LayersBackend::LAYERS_NONE,
|
||||
texture->GetFlags());
|
||||
|
||||
@ -193,7 +195,8 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
|
||||
ASSERT_EQ(ycbcrDesc.stereoMode(), ycbcrData.mStereoMode);
|
||||
|
||||
// host deserialization
|
||||
RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
|
||||
RefPtr<TestSurfaceAllocator> deallocator = new TestSurfaceAllocator();
|
||||
RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, deallocator,
|
||||
LayersBackend::LAYERS_NONE,
|
||||
client->GetFlags());
|
||||
|
||||
|
@ -140,6 +140,7 @@ CreateTextureClientWithBackend(LayersBackend aLayersBackend)
|
||||
*/
|
||||
already_AddRefed<TextureHost>
|
||||
CreateTextureHostWithBackend(TextureClient* aClient,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
LayersBackend& aLayersBackend)
|
||||
{
|
||||
if (!aClient) {
|
||||
@ -153,7 +154,7 @@ CreateTextureHostWithBackend(TextureClient* aClient,
|
||||
aClient->ToSurfaceDescriptor(descriptor);
|
||||
|
||||
wr::MaybeExternalImageId id = Nothing();
|
||||
return TextureHost::Create(descriptor, nullptr, aLayersBackend,
|
||||
return TextureHost::Create(descriptor, aDeallocator, aLayersBackend,
|
||||
aClient->GetFlags(), id);
|
||||
}
|
||||
|
||||
|
@ -85,8 +85,11 @@ RenderCompositorANGLE::Initialize()
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferCount = 2;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
// Do not use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, since it makes HWND unreusable.
|
||||
//desc.BufferCount = 2;
|
||||
//desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
desc.BufferCount = 1;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
|
||||
desc.Scaling = DXGI_SCALING_NONE;
|
||||
desc.Flags = 0;
|
||||
|
||||
|
@ -43,7 +43,8 @@ public:
|
||||
// Other, internal-only methods:
|
||||
virtual void SetHasImage() = 0;
|
||||
virtual bool NotificationsDeferred() const = 0;
|
||||
virtual void SetNotificationsDeferred(bool aDeferNotifications) = 0;
|
||||
virtual void MarkPendingNotify() = 0;
|
||||
virtual void ClearPendingNotify() = 0;
|
||||
|
||||
virtual already_AddRefed<nsIEventTarget> GetEventTarget() const
|
||||
{
|
||||
|
@ -95,7 +95,8 @@ public:
|
||||
// Other notifications are ignored.
|
||||
virtual void SetHasImage() override { }
|
||||
virtual bool NotificationsDeferred() const override { return false; }
|
||||
virtual void SetNotificationsDeferred(bool) override { }
|
||||
virtual void MarkPendingNotify() override { }
|
||||
virtual void ClearPendingNotify() override { }
|
||||
|
||||
private:
|
||||
virtual ~NextPartObserver() { }
|
||||
@ -122,7 +123,7 @@ private:
|
||||
|
||||
MultipartImage::MultipartImage(Image* aFirstPart)
|
||||
: ImageWrapper(aFirstPart)
|
||||
, mDeferNotifications(false)
|
||||
, mPendingNotify(false)
|
||||
{
|
||||
mNextPartObserver = new NextPartObserver(this);
|
||||
}
|
||||
@ -333,13 +334,19 @@ MultipartImage::SetHasImage()
|
||||
bool
|
||||
MultipartImage::NotificationsDeferred() const
|
||||
{
|
||||
return mDeferNotifications;
|
||||
return mPendingNotify;
|
||||
}
|
||||
|
||||
void
|
||||
MultipartImage::SetNotificationsDeferred(bool aDeferNotifications)
|
||||
MultipartImage::MarkPendingNotify()
|
||||
{
|
||||
mDeferNotifications = aDeferNotifications;
|
||||
mPendingNotify = true;
|
||||
}
|
||||
|
||||
void
|
||||
MultipartImage::ClearPendingNotify()
|
||||
{
|
||||
mPendingNotify = false;
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
|
@ -59,7 +59,8 @@ public:
|
||||
virtual void OnLoadComplete(bool aLastPart) override;
|
||||
virtual void SetHasImage() override;
|
||||
virtual bool NotificationsDeferred() const override;
|
||||
virtual void SetNotificationsDeferred(bool aDeferNotifications) override;
|
||||
virtual void MarkPendingNotify() override;
|
||||
virtual void ClearPendingNotify() override;
|
||||
|
||||
protected:
|
||||
virtual ~MultipartImage();
|
||||
@ -76,7 +77,7 @@ private:
|
||||
RefPtr<ProgressTracker> mTracker;
|
||||
RefPtr<NextPartObserver> mNextPartObserver;
|
||||
RefPtr<Image> mNextPart;
|
||||
bool mDeferNotifications : 1;
|
||||
bool mPendingNotify : 1;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
@ -141,7 +141,7 @@ class AsyncNotifyRunnable : public Runnable
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should be running on the main thread");
|
||||
MOZ_ASSERT(mTracker, "mTracker should not be null");
|
||||
for (uint32_t i = 0; i < mObservers.Length(); ++i) {
|
||||
mObservers[i]->SetNotificationsDeferred(false);
|
||||
mObservers[i]->ClearPendingNotify();
|
||||
mTracker->SyncNotify(mObservers[i]);
|
||||
}
|
||||
|
||||
@ -171,6 +171,11 @@ ProgressTracker::Notify(IProgressObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aObserver->NotificationsDeferred()) {
|
||||
// There is a pending notification, or the observer isn't ready yet.
|
||||
return;
|
||||
}
|
||||
|
||||
if (MOZ_LOG_TEST(gImgLog, LogLevel::Debug)) {
|
||||
RefPtr<Image> image = GetImage();
|
||||
if (image && image->GetURI()) {
|
||||
@ -185,7 +190,7 @@ ProgressTracker::Notify(IProgressObserver* aObserver)
|
||||
}
|
||||
}
|
||||
|
||||
aObserver->SetNotificationsDeferred(true);
|
||||
aObserver->MarkPendingNotify();
|
||||
|
||||
// If we have an existing runnable that we can use, we just append this
|
||||
// observer to its list of observers to be notified. This ensures we don't
|
||||
@ -221,7 +226,7 @@ class AsyncNotifyCurrentStateRunnable : public Runnable
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should be running on the main thread");
|
||||
mObserver->SetNotificationsDeferred(false);
|
||||
mObserver->ClearPendingNotify();
|
||||
|
||||
mProgressTracker->SyncNotify(mObserver);
|
||||
return NS_OK;
|
||||
@ -241,6 +246,11 @@ ProgressTracker::NotifyCurrentState(IProgressObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (aObserver->NotificationsDeferred()) {
|
||||
// There is a pending notification, or the observer isn't ready yet.
|
||||
return;
|
||||
}
|
||||
|
||||
if (MOZ_LOG_TEST(gImgLog, LogLevel::Debug)) {
|
||||
RefPtr<Image> image = GetImage();
|
||||
nsAutoCString spec;
|
||||
@ -251,7 +261,7 @@ ProgressTracker::NotifyCurrentState(IProgressObserver* aObserver)
|
||||
"ProgressTracker::NotifyCurrentState", "uri", spec.get());
|
||||
}
|
||||
|
||||
aObserver->SetNotificationsDeferred(true);
|
||||
aObserver->MarkPendingNotify();
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev = new AsyncNotifyCurrentStateRunnable(this,
|
||||
aObserver);
|
||||
@ -516,7 +526,7 @@ ProgressTracker::RemoveObserver(IProgressObserver* aObserver)
|
||||
|
||||
if (aObserver->NotificationsDeferred() && runnable) {
|
||||
runnable->RemoveObserver(aObserver);
|
||||
aObserver->SetNotificationsDeferred(false);
|
||||
aObserver->ClearPendingNotify();
|
||||
}
|
||||
|
||||
return removed;
|
||||
|
@ -1768,7 +1768,7 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
|
||||
// In the mean time, we must defer notifications because we are added to
|
||||
// the imgRequest's proxy list, and we can get extra notifications
|
||||
// resulting from methods such as StartDecoding(). See bug 579122.
|
||||
proxy->SetNotificationsDeferred(true);
|
||||
proxy->MarkValidating();
|
||||
|
||||
// Attach the proxy without notifying
|
||||
request->GetValidator()->AddProxy(proxy);
|
||||
@ -1834,7 +1834,7 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request,
|
||||
// In the mean time, we must defer notifications because we are added to
|
||||
// the imgRequest's proxy list, and we can get extra notifications
|
||||
// resulting from methods such as StartDecoding(). See bug 579122.
|
||||
req->SetNotificationsDeferred(true);
|
||||
req->MarkValidating();
|
||||
|
||||
// Add the proxy without notifying
|
||||
hvc->AddProxy(req);
|
||||
@ -2936,13 +2936,45 @@ imgCacheValidator::AddProxy(imgRequestProxy* aProxy)
|
||||
// the network.
|
||||
aProxy->AddToLoadGroup();
|
||||
|
||||
mProxies.AppendObject(aProxy);
|
||||
mProxies.AppendElement(aProxy);
|
||||
}
|
||||
|
||||
void
|
||||
imgCacheValidator::RemoveProxy(imgRequestProxy* aProxy)
|
||||
{
|
||||
mProxies.RemoveObject(aProxy);
|
||||
mProxies.RemoveElement(aProxy);
|
||||
}
|
||||
|
||||
void
|
||||
imgCacheValidator::UpdateProxies()
|
||||
{
|
||||
// We have finished validating the request, so we can safely take ownership
|
||||
// of the proxy list. imgRequestProxy::SyncNotifyListener can mutate the list
|
||||
// if imgRequestProxy::CancelAndForgetObserver is called by its owner. Note
|
||||
// that any potential notifications should still be suppressed in
|
||||
// imgRequestProxy::ChangeOwner because we haven't cleared the validating
|
||||
// flag yet, and thus they will remain deferred.
|
||||
AutoTArray<RefPtr<imgRequestProxy>, 4> proxies(Move(mProxies));
|
||||
|
||||
for (auto& proxy : proxies) {
|
||||
// First update the state of all proxies before notifying any of them
|
||||
// to ensure a consistent state (e.g. in case the notification causes
|
||||
// other proxies to be touched indirectly.)
|
||||
MOZ_ASSERT(proxy->IsValidating());
|
||||
MOZ_ASSERT(proxy->NotificationsDeferred(),
|
||||
"Proxies waiting on cache validation should be "
|
||||
"deferring notifications!");
|
||||
if (mNewRequest) {
|
||||
proxy->ChangeOwner(mNewRequest);
|
||||
}
|
||||
proxy->ClearValidating();
|
||||
}
|
||||
|
||||
for (auto& proxy : proxies) {
|
||||
// Notify synchronously, because we're already in OnStartRequest, an
|
||||
// asynchronously-called function.
|
||||
proxy->SyncNotifyListener();
|
||||
}
|
||||
}
|
||||
|
||||
/** nsIRequestObserver methods **/
|
||||
@ -2982,25 +3014,11 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
}
|
||||
|
||||
if (isFromCache && sameURI) {
|
||||
uint32_t count = mProxies.Count();
|
||||
for (int32_t i = count-1; i>=0; i--) {
|
||||
imgRequestProxy* proxy = static_cast<imgRequestProxy*>(mProxies[i]);
|
||||
|
||||
// Proxies waiting on cache validation should be deferring
|
||||
// notifications. Undefer them.
|
||||
MOZ_ASSERT(proxy->NotificationsDeferred(),
|
||||
"Proxies waiting on cache validation should be "
|
||||
"deferring notifications!");
|
||||
proxy->SetNotificationsDeferred(false);
|
||||
|
||||
// Notify synchronously, because we're already in OnStartRequest, an
|
||||
// asynchronously-called function.
|
||||
proxy->SyncNotifyListener();
|
||||
}
|
||||
|
||||
// We don't need to load this any more.
|
||||
aRequest->Cancel(NS_BINDING_ABORTED);
|
||||
|
||||
// Clear the validator before updating the proxies. The notifications may
|
||||
// clone an existing request, and its state could be inconsistent.
|
||||
mRequest->SetLoadId(context);
|
||||
mRequest->SetValidator(nullptr);
|
||||
|
||||
@ -3009,6 +3027,7 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
mNewRequest = nullptr;
|
||||
mNewEntry = nullptr;
|
||||
|
||||
UpdateProxies();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@ -3035,6 +3054,8 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
// Doom the old request's cache entry
|
||||
mRequest->RemoveFromCache();
|
||||
|
||||
// Clear the validator before updating the proxies. The notifications may
|
||||
// clone an existing request, and its state could be inconsistent.
|
||||
mRequest->SetValidator(nullptr);
|
||||
mRequest = nullptr;
|
||||
|
||||
@ -3055,17 +3076,7 @@ imgCacheValidator::OnStartRequest(nsIRequest* aRequest, nsISupports* ctxt)
|
||||
// changes the caching behaviour for imgRequests.
|
||||
mImgLoader->PutIntoCache(mNewRequest->CacheKey(), mNewEntry);
|
||||
|
||||
uint32_t count = mProxies.Count();
|
||||
for (int32_t i = count-1; i>=0; i--) {
|
||||
imgRequestProxy* proxy = static_cast<imgRequestProxy*>(mProxies[i]);
|
||||
proxy->ChangeOwner(mNewRequest);
|
||||
|
||||
// Notify synchronously, because we're already in OnStartRequest, an
|
||||
// asynchronously-called function.
|
||||
proxy->SetNotificationsDeferred(false);
|
||||
proxy->SyncNotifyListener();
|
||||
}
|
||||
|
||||
UpdateProxies();
|
||||
mNewRequest = nullptr;
|
||||
mNewEntry = nullptr;
|
||||
|
||||
|
@ -568,6 +568,7 @@ public:
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
|
||||
private:
|
||||
void UpdateProxies();
|
||||
virtual ~imgCacheValidator();
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mDestListener;
|
||||
@ -576,7 +577,7 @@ private:
|
||||
nsCOMPtr<nsIChannel> mRedirectChannel;
|
||||
|
||||
RefPtr<imgRequest> mRequest;
|
||||
nsCOMArray<imgIRequest> mProxies;
|
||||
AutoTArray<RefPtr<imgRequestProxy>, 4> mProxies;
|
||||
|
||||
RefPtr<imgRequest> mNewRequest;
|
||||
RefPtr<imgCacheEntry> mNewEntry;
|
||||
|
@ -120,7 +120,8 @@ imgRequestProxy::imgRequestProxy() :
|
||||
mForceDispatchLoadGroup(false),
|
||||
mListenerIsStrongRef(false),
|
||||
mDecodeRequested(false),
|
||||
mDeferNotifications(false),
|
||||
mPendingNotify(false),
|
||||
mValidating(false),
|
||||
mHadListener(false),
|
||||
mHadDispatch(false)
|
||||
{
|
||||
@ -163,15 +164,13 @@ imgRequestProxy::~imgRequestProxy()
|
||||
// above assert.
|
||||
NullOutListener();
|
||||
|
||||
if (GetOwner()) {
|
||||
/* Call RemoveProxy with a successful status. This will keep the
|
||||
channel, if still downloading data, from being canceled if 'this' is
|
||||
the last observer. This allows the image to continue to download and
|
||||
be cached even if no one is using it currently.
|
||||
*/
|
||||
mCanceled = true;
|
||||
GetOwner()->RemoveProxy(this, NS_OK);
|
||||
}
|
||||
/* Call RemoveProxy with a successful status. This will keep the
|
||||
channel, if still downloading data, from being canceled if 'this' is
|
||||
the last observer. This allows the image to continue to download and
|
||||
be cached even if no one is using it currently.
|
||||
*/
|
||||
mCanceled = true;
|
||||
RemoveFromOwner(NS_OK);
|
||||
|
||||
RemoveFromLoadGroup();
|
||||
LOG_FUNC(gImgLog, "imgRequestProxy::~imgRequestProxy");
|
||||
@ -237,6 +236,7 @@ imgRequestProxy::ChangeOwner(imgRequest* aNewOwner)
|
||||
GetOwner()->RemoveProxy(this, NS_OK);
|
||||
|
||||
mBehaviour->SetOwner(aNewOwner);
|
||||
MOZ_ASSERT(!GetValidator(), "New owner cannot be validating!");
|
||||
|
||||
// If we were locked, apply the locks here
|
||||
for (uint32_t i = 0; i < oldLockCount; i++) {
|
||||
@ -251,14 +251,29 @@ imgRequestProxy::ChangeOwner(imgRequest* aNewOwner)
|
||||
}
|
||||
|
||||
AddToOwner(nullptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
imgRequestProxy::MarkValidating()
|
||||
{
|
||||
MOZ_ASSERT(GetValidator());
|
||||
mValidating = true;
|
||||
}
|
||||
|
||||
void
|
||||
imgRequestProxy::ClearValidating()
|
||||
{
|
||||
MOZ_ASSERT(mValidating);
|
||||
MOZ_ASSERT(!GetValidator());
|
||||
mValidating = false;
|
||||
|
||||
// If we'd previously requested a synchronous decode, request a decode on the
|
||||
// new image.
|
||||
if (mDecodeRequested) {
|
||||
mDecodeRequested = false;
|
||||
StartDecoding(imgIContainer::FLAG_NONE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -351,11 +366,28 @@ imgRequestProxy::AddToOwner(nsIDocument* aLoadingDocument)
|
||||
mEventTarget = do_GetMainThread();
|
||||
}
|
||||
|
||||
if (!GetOwner()) {
|
||||
imgRequest* owner = GetOwner();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetOwner()->AddProxy(this);
|
||||
owner->AddProxy(this);
|
||||
}
|
||||
|
||||
void
|
||||
imgRequestProxy::RemoveFromOwner(nsresult aStatus)
|
||||
{
|
||||
imgRequest* owner = GetOwner();
|
||||
if (owner) {
|
||||
if (mValidating) {
|
||||
imgCacheValidator* validator = owner->GetValidator();
|
||||
MOZ_ASSERT(validator);
|
||||
validator->RemoveProxy(this);
|
||||
mValidating = false;
|
||||
}
|
||||
|
||||
owner->RemoveProxy(this, aStatus);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -494,10 +526,7 @@ imgRequestProxy::Cancel(nsresult status)
|
||||
void
|
||||
imgRequestProxy::DoCancel(nsresult status)
|
||||
{
|
||||
if (GetOwner()) {
|
||||
GetOwner()->RemoveProxy(this, status);
|
||||
}
|
||||
|
||||
RemoveFromOwner(status);
|
||||
RemoveFromLoadGroup();
|
||||
NullOutListener();
|
||||
}
|
||||
@ -519,17 +548,7 @@ imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
|
||||
|
||||
mCanceled = true;
|
||||
mForceDispatchLoadGroup = true;
|
||||
|
||||
imgRequest* owner = GetOwner();
|
||||
if (owner) {
|
||||
imgCacheValidator* validator = owner->GetValidator();
|
||||
if (validator) {
|
||||
validator->RemoveProxy(this);
|
||||
}
|
||||
|
||||
owner->RemoveProxy(this, aStatus);
|
||||
}
|
||||
|
||||
RemoveFromOwner(aStatus);
|
||||
RemoveFromLoadGroup();
|
||||
mForceDispatchLoadGroup = false;
|
||||
|
||||
@ -541,8 +560,11 @@ imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
|
||||
NS_IMETHODIMP
|
||||
imgRequestProxy::StartDecoding(uint32_t aFlags)
|
||||
{
|
||||
// Flag this, so we know to transfer the request if our owner changes
|
||||
mDecodeRequested = true;
|
||||
// Flag this, so we know to request after validation if pending.
|
||||
if (IsValidating()) {
|
||||
mDecodeRequested = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<Image> image = GetImage();
|
||||
if (image) {
|
||||
@ -559,8 +581,11 @@ imgRequestProxy::StartDecoding(uint32_t aFlags)
|
||||
bool
|
||||
imgRequestProxy::StartDecodingWithResult(uint32_t aFlags)
|
||||
{
|
||||
// Flag this, so we know to transfer the request if our owner changes
|
||||
mDecodeRequested = true;
|
||||
// Flag this, so we know to request after validation if pending.
|
||||
if (IsValidating()) {
|
||||
mDecodeRequested = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<Image> image = GetImage();
|
||||
if (image) {
|
||||
@ -717,8 +742,16 @@ imgRequestProxy::GetImage(imgIContainer** aImage)
|
||||
NS_IMETHODIMP
|
||||
imgRequestProxy::GetImageStatus(uint32_t* aStatus)
|
||||
{
|
||||
RefPtr<ProgressTracker> progressTracker = GetProgressTracker();
|
||||
*aStatus = progressTracker->GetImageStatus();
|
||||
if (IsValidating()) {
|
||||
// We are currently validating the image, and so our status could revert if
|
||||
// we discard the cache. We should also be deferring notifications, such
|
||||
// that the caller will be notified when validation completes. Rather than
|
||||
// risk misleading the caller, return nothing.
|
||||
*aStatus = imgIRequest::STATUS_NONE;
|
||||
} else {
|
||||
RefPtr<ProgressTracker> progressTracker = GetProgressTracker();
|
||||
*aStatus = progressTracker->GetImageStatus();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -859,15 +892,16 @@ imgRequestProxy::PerformClone(imgINotificationObserver* aObserver,
|
||||
// surprised.
|
||||
NS_ADDREF(*aClone = clone);
|
||||
|
||||
if (GetOwner() && GetOwner()->GetValidator()) {
|
||||
imgCacheValidator* validator = GetValidator();
|
||||
if (validator) {
|
||||
// Note that if we have a validator, we don't want to issue notifications at
|
||||
// here because we want to defer until that completes. AddProxy will add us
|
||||
// to the load group; we cannot avoid that in this case, because we don't
|
||||
// know when the validation will complete, and if it will cause us to
|
||||
// discard our cached state anyways. We are probably already blocked by the
|
||||
// original LoadImage(WithChannel) request in any event.
|
||||
clone->SetNotificationsDeferred(true);
|
||||
GetOwner()->GetValidator()->AddProxy(clone);
|
||||
clone->MarkValidating();
|
||||
validator->AddProxy(clone);
|
||||
} else {
|
||||
// We only want to add the request to the load group of the owning document
|
||||
// if it is still in progress. Some callers cannot handle a supurious load
|
||||
@ -1270,6 +1304,16 @@ imgRequestProxy::GetOwner() const
|
||||
return mBehaviour->GetOwner();
|
||||
}
|
||||
|
||||
imgCacheValidator*
|
||||
imgRequestProxy::GetValidator() const
|
||||
{
|
||||
imgRequest* owner = GetOwner();
|
||||
if (!owner) {
|
||||
return nullptr;
|
||||
}
|
||||
return owner->GetValidator();
|
||||
}
|
||||
|
||||
////////////////// imgRequestProxyStatic methods
|
||||
|
||||
class StaticBehaviour : public ProxyBehaviour
|
||||
|
@ -30,6 +30,7 @@
|
||||
{0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \
|
||||
}
|
||||
|
||||
class imgCacheValidator;
|
||||
class imgINotificationObserver;
|
||||
class imgStatusNotifyRunnable;
|
||||
class ProxyBehaviour;
|
||||
@ -111,15 +112,25 @@ public:
|
||||
virtual void SetHasImage() override;
|
||||
|
||||
// Whether we want notifications from ProgressTracker to be deferred until
|
||||
// an event it has scheduled has been fired.
|
||||
// an event it has scheduled has been fired and/or validation is complete.
|
||||
virtual bool NotificationsDeferred() const override
|
||||
{
|
||||
return mDeferNotifications;
|
||||
return IsValidating() || mPendingNotify;
|
||||
}
|
||||
virtual void SetNotificationsDeferred(bool aDeferNotifications) override
|
||||
virtual void MarkPendingNotify() override
|
||||
{
|
||||
mDeferNotifications = aDeferNotifications;
|
||||
mPendingNotify = true;
|
||||
}
|
||||
virtual void ClearPendingNotify() override
|
||||
{
|
||||
mPendingNotify = false;
|
||||
}
|
||||
bool IsValidating() const
|
||||
{
|
||||
return mValidating;
|
||||
}
|
||||
void MarkValidating();
|
||||
void ClearValidating();
|
||||
|
||||
bool IsOnEventTarget() const;
|
||||
already_AddRefed<nsIEventTarget> GetEventTarget() const override;
|
||||
@ -194,6 +205,7 @@ protected:
|
||||
already_AddRefed<Image> GetImage() const;
|
||||
bool HasImage() const;
|
||||
imgRequest* GetOwner() const;
|
||||
imgCacheValidator* GetValidator() const;
|
||||
|
||||
nsresult PerformClone(imgINotificationObserver* aObserver,
|
||||
nsIDocument* aLoadingDocument,
|
||||
@ -212,6 +224,7 @@ private:
|
||||
friend class imgCacheValidator;
|
||||
|
||||
void AddToOwner(nsIDocument* aLoadingDocument);
|
||||
void RemoveFromOwner(nsresult aStatus);
|
||||
|
||||
nsresult DispatchWithTargetIfAvailable(already_AddRefed<nsIRunnable> aEvent);
|
||||
void DispatchWithTarget(already_AddRefed<nsIRunnable> aEvent);
|
||||
@ -241,7 +254,8 @@ private:
|
||||
|
||||
// Whether we want to defer our notifications by the non-virtual Observer
|
||||
// interfaces as image loads proceed.
|
||||
bool mDeferNotifications : 1;
|
||||
bool mPendingNotify : 1;
|
||||
bool mValidating : 1;
|
||||
bool mHadListener : 1;
|
||||
bool mHadDispatch : 1;
|
||||
};
|
||||
|
@ -10,6 +10,9 @@ dumpStringRepresentation("");
|
||||
print("\nResult of coercion to string:");
|
||||
dumpStringRepresentation();
|
||||
|
||||
print("\nString with an index value:");
|
||||
dumpStringRepresentation((12345).toString());
|
||||
|
||||
print("\ns = Simple short atom:");
|
||||
var s = "xxxxxxxx";
|
||||
dumpStringRepresentation(s);
|
||||
|
@ -5505,7 +5505,8 @@ CodeGenerator::generateBody()
|
||||
TrackedOptimizations* last = nullptr;
|
||||
|
||||
#if defined(JS_ION_PERF)
|
||||
perfSpewer->startBasicBlock(current->mir(), masm);
|
||||
if (!perfSpewer->startBasicBlock(current->mir(), masm))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
for (LInstructionIterator iter = current->begin(); iter != current->end(); iter++) {
|
||||
@ -8653,24 +8654,14 @@ CodeGenerator::visitSpectreMaskIndex(LSpectreMaskIndex* lir)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
|
||||
const LAllocation* index = lir->index();
|
||||
const LAllocation* length = lir->length();
|
||||
Register index = ToRegister(lir->index());
|
||||
Register output = ToRegister(lir->output());
|
||||
|
||||
if (index->isConstant()) {
|
||||
int32_t idx = ToInt32(index);
|
||||
if (length->isRegister())
|
||||
masm.spectreMaskIndex(idx, ToRegister(length), output);
|
||||
else
|
||||
masm.spectreMaskIndex(idx, ToAddress(length), output);
|
||||
return;
|
||||
}
|
||||
|
||||
Register indexReg = ToRegister(index);
|
||||
if (length->isRegister())
|
||||
masm.spectreMaskIndex(indexReg, ToRegister(length), output);
|
||||
masm.spectreMaskIndex(index, ToRegister(length), output);
|
||||
else
|
||||
masm.spectreMaskIndex(indexReg, ToAddress(length), output);
|
||||
masm.spectreMaskIndex(index, ToAddress(length), output);
|
||||
}
|
||||
|
||||
class OutOfLineStoreElementHole : public OutOfLineCodeBase<CodeGenerator>
|
||||
|
@ -232,7 +232,7 @@ DefaultJitOptions::DefaultJitOptions()
|
||||
Warn(forcedRegisterAllocatorEnv, env);
|
||||
}
|
||||
|
||||
SET_DEFAULT(spectreIndexMasking, false);
|
||||
SET_DEFAULT(spectreIndexMasking, true);
|
||||
|
||||
// Toggles whether unboxed plain objects can be created by the VM.
|
||||
SET_DEFAULT(disableUnboxedObjects, false);
|
||||
|
@ -3163,16 +3163,8 @@ LIRGenerator::visitSpectreMaskIndex(MSpectreMaskIndex* ins)
|
||||
MOZ_ASSERT(ins->length()->type() == MIRType::Int32);
|
||||
MOZ_ASSERT(ins->type() == MIRType::Int32);
|
||||
|
||||
// On 64-bit platforms, the length must be in a register, so
|
||||
// MacroAssembler::maskIndex can emit more efficient code.
|
||||
#if JS_BITS_PER_WORD == 64
|
||||
LAllocation lengthUse = useRegister(ins->length());
|
||||
#else
|
||||
LAllocation lengthUse = useAny(ins->length());
|
||||
#endif
|
||||
|
||||
LSpectreMaskIndex* lir =
|
||||
new(alloc()) LSpectreMaskIndex(useRegisterOrConstant(ins->index()), lengthUse);
|
||||
new(alloc()) LSpectreMaskIndex(useRegister(ins->index()), useAny(ins->length()));
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
|
@ -3322,99 +3322,27 @@ MacroAssembler::debugAssertIsObject(const ValueOperand& val)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
MacroAssembler::computeSpectreIndexMaskGeneric(Register index, const T& length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
// mask := ((index - length) & ~index) >> 31
|
||||
mov(index, output);
|
||||
sub32(length, output);
|
||||
not32(index);
|
||||
and32(index, output);
|
||||
not32(index); // Restore index register to its original value.
|
||||
rshift32Arithmetic(Imm32(31), output);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
MacroAssembler::computeSpectreIndexMask(int32_t index, const T& length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
|
||||
// mask := ((index - length) & ~index) >> 31
|
||||
move32(Imm32(index), output);
|
||||
sub32(length, output);
|
||||
and32(Imm32(~index), output);
|
||||
rshift32Arithmetic(Imm32(31), output);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::computeSpectreIndexMask(Register index, Register length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(length != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
#if JS_BITS_PER_WORD == 64
|
||||
// On 64-bit platforms, we can use a faster algorithm:
|
||||
//
|
||||
// mask := (uint64_t(index) - uint64_t(length)) >> 32
|
||||
//
|
||||
// mask is 0x11…11 if index < length, 0 otherwise.
|
||||
move32(index, output);
|
||||
subPtr(length, output);
|
||||
rshiftPtr(Imm32(32), output);
|
||||
#else
|
||||
computeSpectreIndexMaskGeneric(index, length, output);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(int32_t index, Register length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(length != output);
|
||||
if (index == 0) {
|
||||
move32(Imm32(index), output);
|
||||
} else {
|
||||
computeSpectreIndexMask(index, length, output);
|
||||
and32(Imm32(index), output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(int32_t index, const Address& length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(length.base != output);
|
||||
if (index == 0) {
|
||||
move32(Imm32(index), output);
|
||||
} else {
|
||||
computeSpectreIndexMask(index, length, output);
|
||||
and32(Imm32(index), output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(Register index, Register length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(length != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
computeSpectreIndexMask(index, length, output);
|
||||
and32(index, output);
|
||||
move32(Imm32(0), output);
|
||||
cmp32Move32(Assembler::Below, index, length, index, output);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(Register index, const Address& length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(index != length.base);
|
||||
MOZ_ASSERT(length.base != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
computeSpectreIndexMaskGeneric(index, length, output);
|
||||
and32(index, output);
|
||||
move32(Imm32(0), output);
|
||||
cmp32Move32(Assembler::Below, index, length, index, output);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3429,38 +3357,6 @@ MacroAssembler::boundsCheck32PowerOfTwo(Register index, uint32_t length, Label*
|
||||
and32(Imm32(length - 1), index);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, Register length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length);
|
||||
MOZ_ASSERT(length != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
branch32(Assembler::AboveOrEqual, index, length, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking) {
|
||||
computeSpectreIndexMask(index, length, scratch);
|
||||
and32(scratch, index);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, const Address& length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length.base);
|
||||
MOZ_ASSERT(length.base != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
branch32(Assembler::BelowOrEqual, length, index, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking) {
|
||||
computeSpectreIndexMaskGeneric(index, length, scratch);
|
||||
and32(scratch, index);
|
||||
}
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
|
@ -1359,6 +1359,24 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
DEFINED_ON(arm, arm64, x86_shared);
|
||||
|
||||
public:
|
||||
|
||||
inline void cmp32Move32(Condition cond, Register lhs, Register rhs, Register src,
|
||||
Register dest)
|
||||
DEFINED_ON(arm, arm64, x86_shared);
|
||||
|
||||
inline void cmp32Move32(Condition cond, Register lhs, const Address& rhs, Register src,
|
||||
Register dest)
|
||||
DEFINED_ON(arm, arm64, x86_shared);
|
||||
|
||||
// Performs a bounds check and zeroes the index register if out-of-bounds
|
||||
// (to mitigate Spectre).
|
||||
inline void boundsCheck32ForLoad(Register index, Register length, Register scratch,
|
||||
Label* failure)
|
||||
DEFINED_ON(arm, arm64, x86_shared);
|
||||
inline void boundsCheck32ForLoad(Register index, const Address& length, Register scratch,
|
||||
Label* failure)
|
||||
DEFINED_ON(arm, arm64, x86_shared);
|
||||
|
||||
// ========================================================================
|
||||
// Canonicalization primitives.
|
||||
inline void canonicalizeDouble(FloatRegister reg);
|
||||
@ -2055,18 +2073,6 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
store32(Imm32(key.constant()), dest);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void computeSpectreIndexMaskGeneric(Register index, const T& length, Register output);
|
||||
|
||||
void computeSpectreIndexMask(Register index, Register length, Register output);
|
||||
|
||||
template <typename T>
|
||||
void computeSpectreIndexMask(int32_t index, const T& length, Register output);
|
||||
|
||||
public:
|
||||
void spectreMaskIndex(int32_t index, Register length, Register output);
|
||||
void spectreMaskIndex(int32_t index, const Address& length, Register output);
|
||||
void spectreMaskIndex(Register index, Register length, Register output);
|
||||
void spectreMaskIndex(Register index, const Address& length, Register output);
|
||||
|
||||
@ -2074,10 +2080,6 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
// masking.
|
||||
void boundsCheck32PowerOfTwo(Register index, uint32_t length, Label* failure);
|
||||
|
||||
// Performs a bounds check and Spectre index masking.
|
||||
void boundsCheck32ForLoad(Register index, Register length, Register scratch, Label* failure);
|
||||
void boundsCheck32ForLoad(Register index, const Address& length, Register scratch, Label* failure);
|
||||
|
||||
template <typename T>
|
||||
void guardedCallPreBarrier(const T& address, MIRType type) {
|
||||
Label done;
|
||||
|
@ -129,24 +129,21 @@ js::jit::PerfFuncEnabled() {
|
||||
return PerfMode == PERF_MODE_FUNC;
|
||||
}
|
||||
|
||||
static bool
|
||||
lockPerfMap(void)
|
||||
{
|
||||
if (!PerfEnabled())
|
||||
return false;
|
||||
|
||||
PerfMutex->lock();
|
||||
|
||||
MOZ_ASSERT(PerfFilePtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
unlockPerfMap()
|
||||
{
|
||||
MOZ_ASSERT(PerfFilePtr);
|
||||
fflush(PerfFilePtr);
|
||||
PerfMutex->unlock();
|
||||
namespace {
|
||||
struct MOZ_RAII AutoLockPerfMap
|
||||
{
|
||||
AutoLockPerfMap() {
|
||||
if (!PerfEnabled())
|
||||
return;
|
||||
PerfMutex->lock();
|
||||
MOZ_ASSERT(PerfFilePtr);
|
||||
}
|
||||
~AutoLockPerfMap() {
|
||||
MOZ_ASSERT(PerfFilePtr);
|
||||
fflush(PerfFilePtr);
|
||||
PerfMutex->unlock();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t PerfSpewer::nextFunctionIndex = 0;
|
||||
@ -173,24 +170,36 @@ PerfSpewer::startBasicBlock(MBasicBlock* blk,
|
||||
return basicBlocks_.append(r);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PerfSpewer::endBasicBlock(MacroAssembler& masm)
|
||||
{
|
||||
if (!PerfBlockEnabled())
|
||||
return true;
|
||||
|
||||
return;
|
||||
masm.bind(&basicBlocks_.back().end);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PerfSpewer::noteEndInlineCode(MacroAssembler& masm)
|
||||
{
|
||||
if (!PerfBlockEnabled())
|
||||
return true;
|
||||
|
||||
return;
|
||||
masm.bind(&endInlineCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PerfSpewer::WriteEntry(const AutoLockPerfMap&, uintptr_t address, size_t size,
|
||||
const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
auto result = mozilla::Vsmprintf<js::SystemAllocPolicy>(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %zx %s\n",
|
||||
address,
|
||||
size,
|
||||
result.get());
|
||||
}
|
||||
|
||||
void
|
||||
@ -198,29 +207,19 @@ PerfSpewer::writeProfile(JSScript* script,
|
||||
JitCode* code,
|
||||
MacroAssembler& masm)
|
||||
{
|
||||
AutoLockPerfMap lock;
|
||||
|
||||
if (PerfFuncEnabled()) {
|
||||
if (!lockPerfMap())
|
||||
return;
|
||||
|
||||
uint32_t thisFunctionIndex = nextFunctionIndex++;
|
||||
|
||||
size_t size = code->instructionsSize();
|
||||
if (size > 0) {
|
||||
fprintf(PerfFilePtr, "%p %zx %s:%zu: Func%02d\n",
|
||||
code->raw(),
|
||||
size,
|
||||
script->filename(),
|
||||
script->lineno(),
|
||||
thisFunctionIndex);
|
||||
WriteEntry(lock, reinterpret_cast<uintptr_t>(code->raw()), size, "%s:%zu: Func%02" PRIu32,
|
||||
script->filename(), script->lineno(), thisFunctionIndex);
|
||||
}
|
||||
unlockPerfMap();
|
||||
return;
|
||||
}
|
||||
|
||||
if (PerfBlockEnabled() && basicBlocks_.length() > 0) {
|
||||
if (!lockPerfMap())
|
||||
return;
|
||||
|
||||
uint32_t thisFunctionIndex = nextFunctionIndex++;
|
||||
uintptr_t funcStart = uintptr_t(code->raw());
|
||||
uintptr_t funcEndInlineCode = funcStart + endInlineCode.offset();
|
||||
@ -230,8 +229,8 @@ PerfSpewer::writeProfile(JSScript* script,
|
||||
size_t prologueSize = basicBlocks_[0].start.offset();
|
||||
|
||||
if (prologueSize > 0) {
|
||||
fprintf(PerfFilePtr, "%zx %zx %s:%zu: Func%02d-Prologue\n",
|
||||
funcStart, prologueSize, script->filename(), script->lineno(), thisFunctionIndex);
|
||||
WriteEntry(lock, funcStart, prologueSize, "%s:%zu: Func%02" PRIu32 "-Prologue",
|
||||
script->filename(), script->lineno(), thisFunctionIndex);
|
||||
}
|
||||
|
||||
uintptr_t cur = funcStart + prologueSize;
|
||||
@ -243,41 +242,31 @@ PerfSpewer::writeProfile(JSScript* script,
|
||||
|
||||
MOZ_ASSERT(cur <= blockStart);
|
||||
if (cur < blockStart) {
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %" PRIxPTR " %s:%zu: Func%02d-Block?\n",
|
||||
cur, blockStart - cur,
|
||||
script->filename(), script->lineno(),
|
||||
thisFunctionIndex);
|
||||
WriteEntry(lock, cur, blockStart - cur, "%s:%zu: Func%02" PRIu32 "-Block?",
|
||||
script->filename(), script->lineno(), thisFunctionIndex);
|
||||
}
|
||||
cur = blockEnd;
|
||||
|
||||
size_t size = blockEnd - blockStart;
|
||||
|
||||
if (size > 0) {
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %zx %s:%d:%d: Func%02d-Block%d\n",
|
||||
blockStart, size,
|
||||
r.filename, r.lineNumber, r.columnNumber,
|
||||
thisFunctionIndex, r.id);
|
||||
WriteEntry(lock, blockStart, size, "%s:%u:%u: Func%02" PRIu32 "d-Block%" PRIu32,
|
||||
r.filename, r.lineNumber, r.columnNumber, thisFunctionIndex, r.id);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(cur <= funcEndInlineCode);
|
||||
if (cur < funcEndInlineCode) {
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %" PRIxPTR " %s:%zu: Func%02d-Epilogue\n",
|
||||
cur, funcEndInlineCode - cur,
|
||||
script->filename(), script->lineno(),
|
||||
thisFunctionIndex);
|
||||
WriteEntry(lock, cur, funcEndInlineCode - cur, "%s:%zu: Func%02" PRIu32 "-Epilogue",
|
||||
script->filename(), script->lineno(), thisFunctionIndex);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(funcEndInlineCode <= funcEnd);
|
||||
if (funcEndInlineCode < funcEnd) {
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %" PRIxPTR " %s:%zu: Func%02d-OOL\n",
|
||||
funcEndInlineCode, funcEnd - funcEndInlineCode,
|
||||
script->filename(), script->lineno(),
|
||||
thisFunctionIndex);
|
||||
WriteEntry(lock, funcEndInlineCode, funcEnd - funcEndInlineCode,
|
||||
"%s:%zu: Func%02" PRIu32 "-OOL",
|
||||
script->filename(), script->lineno(), thisFunctionIndex);
|
||||
}
|
||||
|
||||
unlockPerfMap();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,17 +276,12 @@ js::jit::writePerfSpewerBaselineProfile(JSScript* script, JitCode* code)
|
||||
if (!PerfEnabled())
|
||||
return;
|
||||
|
||||
if (!lockPerfMap())
|
||||
return;
|
||||
|
||||
size_t size = code->instructionsSize();
|
||||
if (size > 0) {
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %zx %s:%zu: Baseline\n",
|
||||
reinterpret_cast<uintptr_t>(code->raw()),
|
||||
size, script->filename(), script->lineno());
|
||||
AutoLockPerfMap lock;
|
||||
PerfSpewer::WriteEntry(lock, reinterpret_cast<uintptr_t>(code->raw()), size,
|
||||
"%s:%zu: Baseline", script->filename(), script->lineno());
|
||||
}
|
||||
|
||||
unlockPerfMap();
|
||||
}
|
||||
|
||||
void
|
||||
@ -306,34 +290,35 @@ js::jit::writePerfSpewerJitCodeProfile(JitCode* code, const char* msg)
|
||||
if (!code || !PerfEnabled())
|
||||
return;
|
||||
|
||||
if (!lockPerfMap())
|
||||
return;
|
||||
|
||||
size_t size = code->instructionsSize();
|
||||
if (size > 0) {
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %zx %s (%p 0x%zx)\n",
|
||||
reinterpret_cast<uintptr_t>(code->raw()),
|
||||
size, msg, code->raw(), size);
|
||||
AutoLockPerfMap lock;
|
||||
PerfSpewer::WriteEntry(lock, reinterpret_cast<uintptr_t>(code->raw()), size,
|
||||
"%s (%p 0x%zx)", msg, code->raw(), size);
|
||||
}
|
||||
}
|
||||
|
||||
unlockPerfMap();
|
||||
void
|
||||
js::jit::writePerfSpewerWasmMap(uintptr_t base, uintptr_t size, const char* filename,
|
||||
const char* annotation)
|
||||
{
|
||||
if (!PerfFuncEnabled() || size == 0U)
|
||||
return;
|
||||
|
||||
AutoLockPerfMap lock;
|
||||
PerfSpewer::WriteEntry(lock, base, size, "%s: Function %s", filename, annotation);
|
||||
}
|
||||
|
||||
void
|
||||
js::jit::writePerfSpewerWasmFunctionMap(uintptr_t base, uintptr_t size,
|
||||
const char* filename, unsigned lineno, unsigned colIndex,
|
||||
const char* filename, unsigned lineno,
|
||||
const char* funcName)
|
||||
{
|
||||
if (!PerfFuncEnabled() || size == 0U)
|
||||
return;
|
||||
|
||||
if (!lockPerfMap())
|
||||
return;
|
||||
|
||||
fprintf(PerfFilePtr, "%" PRIxPTR " %" PRIxPTR " %s:%u:%u: Function %s\n",
|
||||
base, size, filename, lineno, colIndex, funcName);
|
||||
|
||||
unlockPerfMap();
|
||||
AutoLockPerfMap lock;
|
||||
PerfSpewer::WriteEntry(lock, base, size, "%s:%u: Function %s", filename, lineno, funcName);
|
||||
}
|
||||
|
||||
#endif // defined (JS_ION_PERF)
|
||||
|
@ -12,6 +12,10 @@
|
||||
# include "jit/MacroAssembler.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
struct AutoLockPerfMap;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
@ -67,10 +71,14 @@ class PerfSpewer
|
||||
|
||||
public:
|
||||
virtual MOZ_MUST_USE bool startBasicBlock(MBasicBlock* blk, MacroAssembler& masm);
|
||||
virtual MOZ_MUST_USE bool endBasicBlock(MacroAssembler& masm);
|
||||
MOZ_MUST_USE bool noteEndInlineCode(MacroAssembler& masm);
|
||||
virtual void endBasicBlock(MacroAssembler& masm);
|
||||
void noteEndInlineCode(MacroAssembler& masm);
|
||||
|
||||
void writeProfile(JSScript* script, JitCode* code, MacroAssembler& masm);
|
||||
|
||||
static void WriteEntry(const AutoLockPerfMap&, uintptr_t address, size_t size,
|
||||
const char* fmt, ...)
|
||||
MOZ_FORMAT_PRINTF(4, 5);
|
||||
};
|
||||
|
||||
void writePerfSpewerBaselineProfile(JSScript* script, JitCode* code);
|
||||
@ -81,11 +89,13 @@ class WasmPerfSpewer : public PerfSpewer
|
||||
{
|
||||
public:
|
||||
MOZ_MUST_USE bool startBasicBlock(MBasicBlock* blk, MacroAssembler& masm) { return true; }
|
||||
MOZ_MUST_USE bool endBasicBlock(MacroAssembler& masm) { return true; }
|
||||
void endBasicBlock(MacroAssembler& masm) { }
|
||||
};
|
||||
|
||||
void writePerfSpewerWasmMap(uintptr_t base, uintptr_t size, const char* filename,
|
||||
const char* annotation);
|
||||
void writePerfSpewerWasmFunctionMap(uintptr_t base, uintptr_t size, const char* filename,
|
||||
unsigned lineno, unsigned colIndex, const char* funcName);
|
||||
unsigned lineno, const char* funcName);
|
||||
|
||||
#endif // JS_ION_PERF
|
||||
|
||||
|
@ -2136,6 +2136,58 @@ MacroAssembler::branchToComputedAddress(const BaseIndex& addr)
|
||||
breakpoint();
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs, Register src,
|
||||
Register dest)
|
||||
{
|
||||
cmp32(lhs, rhs);
|
||||
ma_mov(src, dest, LeaveCC, cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::cmp32Move32(Condition cond, Register lhs, const Address& rhs, Register src,
|
||||
Register dest)
|
||||
{
|
||||
ScratchRegisterScope scratch(*this);
|
||||
SecondScratchRegisterScope scratch2(*this);
|
||||
ma_ldr(rhs, scratch, scratch2);
|
||||
cmp32Move32(cond, lhs, scratch, src, dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, Register length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length);
|
||||
MOZ_ASSERT(length != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
move32(Imm32(0), scratch);
|
||||
|
||||
branch32(Assembler::BelowOrEqual, length, index, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
ma_mov(scratch, index, LeaveCC, Assembler::BelowOrEqual);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, const Address& length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length.base);
|
||||
MOZ_ASSERT(length.base != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
move32(Imm32(0), scratch);
|
||||
|
||||
branch32(Assembler::BelowOrEqual, length, index, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
ma_mov(scratch, index, LeaveCC, Assembler::BelowOrEqual);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Memory access primitives.
|
||||
void
|
||||
|
@ -1710,6 +1710,50 @@ MacroAssembler::branchToComputedAddress(const BaseIndex& addr)
|
||||
MOZ_CRASH("branchToComputedAddress");
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs, Register src,
|
||||
Register dest)
|
||||
{
|
||||
cmp32(lhs, rhs);
|
||||
Csel(ARMRegister(dest, 32), ARMRegister(src, 32), ARMRegister(dest, 32), cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::cmp32Move32(Condition cond, Register lhs, const Address& rhs, Register src,
|
||||
Register dest)
|
||||
{
|
||||
cmp32(lhs, rhs);
|
||||
Csel(ARMRegister(dest, 32), ARMRegister(src, 32), ARMRegister(dest, 32), cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, Register length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length);
|
||||
MOZ_ASSERT(length != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
branch32(Assembler::BelowOrEqual, length, index, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
Csel(ARMRegister(index, 32), ARMRegister(index, 32), vixl::wzr, Assembler::Above);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, const Address& length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length.base);
|
||||
MOZ_ASSERT(length.base != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
branch32(Assembler::BelowOrEqual, length, index, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
Csel(ARMRegister(index, 32), ARMRegister(index, 32), vixl::wzr, Assembler::Above);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Memory access primitives.
|
||||
void
|
||||
|
@ -1022,6 +1022,9 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
|
||||
void cmp32(const Address& lhs, Register rhs) {
|
||||
cmp32(Operand(lhs.base, lhs.offset), rhs);
|
||||
}
|
||||
void cmp32(Register lhs, const Address& rhs) {
|
||||
cmp32(lhs, Operand(rhs.base, rhs.offset));
|
||||
}
|
||||
void cmp32(const Operand& lhs, Imm32 rhs) {
|
||||
vixl::UseScratchRegisterScope temps(this);
|
||||
const ARMRegister scratch32 = temps.AcquireW();
|
||||
@ -1034,6 +1037,12 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
|
||||
Mov(scratch32, lhs);
|
||||
Cmp(scratch32, Operand(ARMRegister(rhs, 32)));
|
||||
}
|
||||
void cmp32(Register lhs, const Operand& rhs) {
|
||||
vixl::UseScratchRegisterScope temps(this);
|
||||
const ARMRegister scratch32 = temps.AcquireW();
|
||||
Mov(scratch32, rhs);
|
||||
Cmp(scratch32, Operand(ARMRegister(lhs, 32)));
|
||||
}
|
||||
|
||||
void cmpPtr(Register lhs, Imm32 rhs) {
|
||||
Cmp(ARMRegister(lhs, 64), Operand(rhs.value));
|
||||
|
@ -469,6 +469,10 @@ class AssemblerX86Shared : public AssemblerShared
|
||||
MOZ_CRASH("unexpected operand kind");
|
||||
}
|
||||
}
|
||||
void cmovCCl(Condition cond, Register src, Register dest) {
|
||||
X86Encoding::Condition cc = static_cast<X86Encoding::Condition>(cond);
|
||||
masm.cmovCCl_rr(cc, src.encoding(), dest.encoding());
|
||||
}
|
||||
void cmovzl(const Operand& src, Register dest) {
|
||||
cmovCCl(Condition::Zero, src, dest);
|
||||
}
|
||||
|
@ -1094,6 +1094,58 @@ MacroAssembler::branchTestMagicImpl(Condition cond, const T& t, L label)
|
||||
j(cond, label);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs, Register src,
|
||||
Register dest)
|
||||
{
|
||||
cmp32(lhs, rhs);
|
||||
cmovCCl(cond, src, dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::cmp32Move32(Condition cond, Register lhs, const Address& rhs, Register src,
|
||||
Register dest)
|
||||
{
|
||||
cmp32(lhs, Operand(rhs));
|
||||
cmovCCl(cond, src, dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, Register length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length);
|
||||
MOZ_ASSERT(length != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
move32(Imm32(0), scratch);
|
||||
|
||||
cmp32(index, length);
|
||||
j(Assembler::AboveOrEqual, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
cmovCCl(Assembler::AboveOrEqual, scratch, index);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32ForLoad(Register index, const Address& length, Register scratch,
|
||||
Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(index != length.base);
|
||||
MOZ_ASSERT(length.base != scratch);
|
||||
MOZ_ASSERT(index != scratch);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
move32(Imm32(0), scratch);
|
||||
|
||||
cmp32(index, Operand(length));
|
||||
j(Assembler::AboveOrEqual, failure);
|
||||
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
cmovCCl(Assembler::AboveOrEqual, scratch, index);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Canonicalization primitives.
|
||||
void
|
||||
|
@ -5843,6 +5843,14 @@ JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length)
|
||||
return atom;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
JS_NewLatin1String(JSContext* cx, JS::Latin1Char* chars, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
return NewString<CanGC>(cx, chars, length);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
JS_NewUCString(JSContext* cx, char16_t* chars, size_t length)
|
||||
{
|
||||
|
@ -4722,6 +4722,9 @@ JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length);
|
||||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_AtomizeAndPinString(JSContext* cx, const char* s);
|
||||
|
||||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_NewLatin1String(JSContext* cx, JS::Latin1Char* chars, size_t length);
|
||||
|
||||
extern JS_PUBLIC_API(JSString*)
|
||||
JS_NewUCString(JSContext* cx, char16_t* chars, size_t length);
|
||||
|
||||
|
@ -211,7 +211,7 @@ JSString::dumpRepresentationHeader(js::GenericPrinter& out, int indent, const ch
|
||||
if (flags & ATOM_BIT) out.put(" ATOM");
|
||||
if (isPermanentAtom()) out.put(" PERMANENT");
|
||||
if (flags & LATIN1_CHARS_BIT) out.put(" LATIN1");
|
||||
if (flags & INDEX_VALUE_BIT) out.put(" INDEX_VALUE(%u)", getIndexValue());
|
||||
if (flags & INDEX_VALUE_BIT) out.printf(" INDEX_VALUE(%u)", getIndexValue());
|
||||
out.putChar('\n');
|
||||
}
|
||||
|
||||
|
@ -587,7 +587,8 @@ static const unsigned MaxParams = 1000;
|
||||
static const unsigned MaxBrTableElems = 1000000;
|
||||
static const unsigned MaxMemoryInitialPages = 16384;
|
||||
static const unsigned MaxMemoryMaximumPages = 65536;
|
||||
static const unsigned MaxModuleBytes = 1024 * 1024 * 1024;
|
||||
static const unsigned MaxCodeSectionBytes = 1024 * 1024 * 1024;
|
||||
static const unsigned MaxModuleBytes = MaxCodeSectionBytes;
|
||||
static const unsigned MaxFunctionBytes = 7654321;
|
||||
|
||||
// A magic value of the FramePointer to indicate after a return to the entry
|
||||
|
@ -139,6 +139,14 @@ StaticallyUnlink(uint8_t* base, const LinkDataTier& linkData)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
static bool
|
||||
AppendToString(const char* str, UTF8Bytes* bytes)
|
||||
{
|
||||
return bytes->append(str, strlen(str)) && bytes->append('\0');
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
SendCodeRangesToProfiler(const CodeSegment& cs, const Bytes& bytecode, const Metadata& metadata)
|
||||
{
|
||||
@ -153,18 +161,15 @@ SendCodeRangesToProfiler(const CodeSegment& cs, const Bytes& bytecode, const Met
|
||||
return;
|
||||
|
||||
for (const CodeRange& codeRange : metadata.metadata(cs.tier()).codeRanges) {
|
||||
if (!codeRange.isFunction())
|
||||
if (!codeRange.hasFuncIndex())
|
||||
continue;
|
||||
|
||||
uintptr_t start = uintptr_t(cs.base() + codeRange.begin());
|
||||
uintptr_t end = uintptr_t(cs.base() + codeRange.end());
|
||||
uintptr_t size = end - start;
|
||||
uintptr_t size = codeRange.end() - codeRange.begin();
|
||||
|
||||
UTF8Bytes name;
|
||||
if (!metadata.getFuncName(&bytecode, codeRange.funcIndex(), &name))
|
||||
return;
|
||||
if (!name.append('\0'))
|
||||
return;
|
||||
|
||||
// Avoid "unused" warnings
|
||||
(void)start;
|
||||
@ -173,14 +178,36 @@ SendCodeRangesToProfiler(const CodeSegment& cs, const Bytes& bytecode, const Met
|
||||
#ifdef JS_ION_PERF
|
||||
if (PerfFuncEnabled()) {
|
||||
const char* file = metadata.filename.get();
|
||||
unsigned line = codeRange.funcLineOrBytecode();
|
||||
unsigned column = 0;
|
||||
writePerfSpewerWasmFunctionMap(start, size, file, line, column, name.begin());
|
||||
if (codeRange.isFunction()) {
|
||||
if (!name.append('\0'))
|
||||
return;
|
||||
unsigned line = codeRange.funcLineOrBytecode();
|
||||
writePerfSpewerWasmFunctionMap(start, size, file, line, name.begin());
|
||||
} else if (codeRange.isInterpEntry()) {
|
||||
if (!AppendToString(" slow entry", &name))
|
||||
return;
|
||||
writePerfSpewerWasmMap(start, size, file, name.begin());
|
||||
} else if (codeRange.isImportInterpExit()) {
|
||||
if (!AppendToString(" slow exit", &name))
|
||||
return;
|
||||
writePerfSpewerWasmMap(start, size, file, name.begin());
|
||||
} else if (codeRange.isImportJitExit()) {
|
||||
if (!AppendToString(" fast exit", &name))
|
||||
return;
|
||||
writePerfSpewerWasmMap(start, size, file, name.begin());
|
||||
} else {
|
||||
MOZ_CRASH("unhandled perf hasFuncIndex type");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_VTUNE
|
||||
if (vtune::IsProfilingActive())
|
||||
vtune::MarkWasm(vtune::GenerateUniqueMethodID(), name.begin(), (void*)start, size);
|
||||
if (!vtune::IsProfilingActive())
|
||||
continue;
|
||||
if (!codeRange.isFunction())
|
||||
continue;
|
||||
if (!name.append('\0'))
|
||||
return;
|
||||
vtune::MarkWasm(vtune::GenerateUniqueMethodID(), name.begin(), (void*)start, size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -211,9 +211,9 @@ ModuleGenerator::init(Metadata* maybeAsmJSMetadata)
|
||||
// extra conservative. Note, podResizeToFit calls at the end will trim off
|
||||
// unneeded capacity.
|
||||
|
||||
uint32_t codeSectionSize = env_->codeSection ? env_->codeSection->size : 0;
|
||||
|
||||
if (!masm_.reserve(size_t(1.2 * EstimateCompiledCodeSize(tier(), codeSectionSize))))
|
||||
size_t codeSectionSize = env_->codeSection ? env_->codeSection->size : 0;
|
||||
size_t estimatedCodeSize = 1.2 * EstimateCompiledCodeSize(tier(), codeSectionSize);
|
||||
if (!masm_.reserve(Min(estimatedCodeSize, MaxCodeBytesPerProcess)))
|
||||
return false;
|
||||
|
||||
if (!metadataTier_->codeRanges.reserve(2 * env_->numFuncDefs()))
|
||||
@ -782,7 +782,7 @@ ModuleGenerator::compileFuncDef(uint32_t funcIndex, uint32_t lineOrBytecode,
|
||||
}
|
||||
|
||||
batchedBytecode_ += funcBytecodeLength;
|
||||
MOZ_ASSERT(batchedBytecode_ <= MaxModuleBytes);
|
||||
MOZ_ASSERT(batchedBytecode_ <= MaxCodeSectionBytes);
|
||||
return batchedBytecode_ <= threshold || launchBatchCompile();
|
||||
}
|
||||
|
||||
|
@ -2518,7 +2518,7 @@ class CompileStreamTask : public PromiseHelperTask, public JS::StreamConsumer
|
||||
if (extraBytes)
|
||||
envBytes_.shrinkTo(codeSection_.start);
|
||||
|
||||
if (codeSection_.size > MaxModuleBytes)
|
||||
if (codeSection_.size > MaxCodeSectionBytes)
|
||||
return rejectAndDestroyBeforeHelperThreadStarted(JSMSG_OUT_OF_MEMORY);
|
||||
|
||||
if (!codeBytes_.resize(codeSection_.size))
|
||||
|
@ -1126,9 +1126,15 @@ class CodeRange
|
||||
bool isFunction() const {
|
||||
return kind() == Function;
|
||||
}
|
||||
bool isInterpEntry() const {
|
||||
return kind() == InterpEntry;
|
||||
}
|
||||
bool isImportExit() const {
|
||||
return kind() == ImportJitExit || kind() == ImportInterpExit || kind() == BuiltinThunk;
|
||||
}
|
||||
bool isImportInterpExit() const {
|
||||
return kind() == ImportInterpExit;
|
||||
}
|
||||
bool isImportJitExit() const {
|
||||
return kind() == ImportJitExit;
|
||||
}
|
||||
|
@ -1722,6 +1722,9 @@ wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env)
|
||||
if (!d.startSection(SectionId::Code, env, &env->codeSection, "code"))
|
||||
return false;
|
||||
|
||||
if (env->codeSection && env->codeSection->size > MaxCodeSectionBytes)
|
||||
return d.fail("code section too big");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<title>Testcase for invalid path</title>
|
||||
|
||||
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=601699 -->
|
||||
|
||||
<marker id="marker" markerWidth="10" markerHeight="10">
|
||||
<circle cx="5" cy="5" r="5"/>
|
||||
</marker>
|
||||
|
||||
<rect width="100%" height="100%" fill="lime"/>
|
||||
|
||||
<path id="path" fill="red" marker-mid="url(#marker)"/>
|
||||
|
||||
<script><![CDATA[
|
||||
|
||||
// Parser will throw out path without an initial moveto command, so we use
|
||||
// script to inject one and see what happens.
|
||||
|
||||
var path = document.getElementById("path");
|
||||
var curve = path.createSVGPathSegCurvetoCubicAbs(0, 400, 400, 400, 400, 0);
|
||||
path.pathSegList.appendItem(curve);
|
||||
|
||||
]]></script>
|
||||
</svg>
|
Before Width: | Height: | Size: 808 B |
@ -340,7 +340,6 @@ pref(svg.paint-order.enabled,true) == paint-order-03.svg paint-order-03-ref.svg
|
||||
|
||||
#fuzzy(23,60) fails-if(d2d) == path-01.svg path-01-ref.svg
|
||||
== path-02.svg pass.svg
|
||||
== path-03.svg pass.svg
|
||||
== path-04.svg pass.svg
|
||||
== path-05.svg pass.svg
|
||||
fuzzy-if(skiaContent,1,400) == path-06.svg path-06-ref.svg
|
||||
|
@ -1,17 +0,0 @@
|
||||
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=327709 -->
|
||||
<!-- Just checking for absence of assertion, nothing more -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<script>
|
||||
function init()
|
||||
{
|
||||
var apsl = document.getElementById("n126").animatedPathSegList;
|
||||
apsl.appendItem(apsl.__proto__);
|
||||
}
|
||||
window.addEventListener("load", init, false);
|
||||
</script>
|
||||
|
||||
<path id="n126" d="M 270 60 L 320 60 L 320 110 Z"/>
|
||||
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 418 B |
@ -15,7 +15,6 @@ load 325427-1.svg
|
||||
load 326495-1.svg
|
||||
load 326974-1.svg
|
||||
load 327706-1.svg
|
||||
load 327709-1.svg
|
||||
load 327711-1.svg
|
||||
load 328137-1.svg
|
||||
load 329848-1.svg
|
||||
|
@ -1549,7 +1549,7 @@ pref("javascript.options.throw_on_debuggee_would_run", false);
|
||||
pref("javascript.options.dump_stack_on_debuggee_would_run", false);
|
||||
|
||||
// Spectre security vulnerability mitigations.
|
||||
pref("javascript.options.spectre.index_masking", false);
|
||||
pref("javascript.options.spectre.index_masking", true);
|
||||
|
||||
// Streams API
|
||||
pref("javascript.options.streams", false);
|
||||
|
@ -1,7 +1,4 @@
|
||||
[historical.html]
|
||||
[SVGPathSeg interface must be removed]
|
||||
expected: FAIL
|
||||
|
||||
[SVGUnitTypes mixin interface must not be exposed]
|
||||
expected: FAIL
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user