зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound
--HG-- rename : mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/gfx/ISurfaceAllocator.aidl => mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/gfx/SyncConfig.aidl extra : rebase_source : a7f6628299f30b300a02932debe0cc92810f901d
This commit is contained in:
Коммит
e14d71a660
|
@ -215,7 +215,6 @@ dom/security/test/csp/**
|
|||
dom/security/test/general/**
|
||||
dom/security/test/mixedcontentblocker/**
|
||||
dom/security/test/sri/**
|
||||
dom/security/test/unit/**
|
||||
dom/serviceworkers/**
|
||||
dom/smil/**
|
||||
dom/svg/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<blocklist lastupdate="1544544484935" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||
<blocklist lastupdate="1544811398633" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||
<emItems>
|
||||
<emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
|
||||
<prefs/>
|
||||
|
|
|
@ -5084,6 +5084,9 @@ class TabProgressListener {
|
|||
|
||||
if (topLevel) {
|
||||
let isSameDocument = !!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT);
|
||||
let isReload = !!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_RELOAD);
|
||||
let isErrorPage = !!(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE);
|
||||
|
||||
// We need to clear the typed value
|
||||
// if the document failed to load, to make sure the urlbar reflects the
|
||||
// failed URI (particularly for SSL errors). However, don't clear the value
|
||||
|
@ -5094,8 +5097,7 @@ class TabProgressListener {
|
|||
// Finally, we do insert the URL if this is a same-document navigation
|
||||
// and the user cleared the URL manually.
|
||||
if (this.mBrowser.didStartLoadSinceLastUserTyping() ||
|
||||
((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
|
||||
aLocation.spec != "about:blank") ||
|
||||
(isErrorPage && aLocation.spec != "about:blank") ||
|
||||
(isSameDocument && this.mBrowser.inLoadURI) ||
|
||||
(isSameDocument && !this.mBrowser.userTypedValue)) {
|
||||
this.mBrowser.userTypedValue = null;
|
||||
|
@ -5107,8 +5109,7 @@ class TabProgressListener {
|
|||
// isn't any (STATE_IS_NETWORK & STATE_STOP) state to cause busy
|
||||
// attribute being removed. In this case we should remove the
|
||||
// attribute here.
|
||||
if ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
|
||||
this.mTab.hasAttribute("busy")) {
|
||||
if (isErrorPage && this.mTab.hasAttribute("busy")) {
|
||||
this.mTab.removeAttribute("busy");
|
||||
gBrowser._tabAttrModified(this.mTab, ["busy"]);
|
||||
}
|
||||
|
@ -5135,7 +5136,9 @@ class TabProgressListener {
|
|||
}
|
||||
}
|
||||
|
||||
gBrowser.setTabTitle(this.mTab);
|
||||
if (!isReload) {
|
||||
gBrowser.setTabTitle(this.mTab);
|
||||
}
|
||||
|
||||
// Don't clear the favicon if this tab is in the pending
|
||||
// state, as SessionStore will have set the icon for us even
|
||||
|
|
|
@ -68,6 +68,7 @@ skip-if = (verify && (os == 'win' || os == 'mac'))
|
|||
[browser_preloadedBrowser_zoom.js]
|
||||
[browser_reload_deleted_file.js]
|
||||
skip-if = (debug && os == 'mac') || (debug && os == 'linux' && bits == 64) #Bug 1421183, disabled on Linux/OSX for leaked windows
|
||||
[browser_tab_label_during_reload.js]
|
||||
[browser_tabCloseProbes.js]
|
||||
[browser_tabContextMenu_keyboard.js]
|
||||
[browser_tabReorder_overflow.js]
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function() {
|
||||
let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:preferences");
|
||||
let browser = tab.linkedBrowser;
|
||||
let labelChanges = 0;
|
||||
let attrModifiedListener = event => {
|
||||
if (event.detail.changed.includes("label")) {
|
||||
labelChanges++;
|
||||
}
|
||||
};
|
||||
tab.addEventListener("TabAttrModified", attrModifiedListener);
|
||||
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
is(labelChanges, 1, "number of label changes during initial load");
|
||||
isnot(tab.label, "", "about:preferences tab label isn't empty");
|
||||
isnot(tab.label, "about:preferences", "about:preferences tab label isn't the URI");
|
||||
is(tab.label, browser.contentTitle, "about:preferences tab label matches browser.contentTitle");
|
||||
|
||||
labelChanges = 0;
|
||||
browser.reload();
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
is(labelChanges, 0, "number of label changes during reload");
|
||||
|
||||
tab.removeEventListener("TabAttrModified", attrModifiedListener);
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
|
@ -617,7 +617,7 @@ class UrlbarInput {
|
|||
} else {
|
||||
where = this.window.whereToOpenLink(event, false, false);
|
||||
}
|
||||
if (this.openInTab) {
|
||||
if (UrlbarPrefs.get("openintab")) {
|
||||
if (where == "current") {
|
||||
where = "tab";
|
||||
} else if (where == "tab") {
|
||||
|
|
|
@ -87,6 +87,10 @@ const PREF_URLBAR_DEFAULTS = new Map([
|
|||
// The maximum number of results in the urlbar popup.
|
||||
["maxRichResults", 10],
|
||||
|
||||
// Whether addresses and search results typed into the address bar
|
||||
// should be opened in new tabs by default.
|
||||
["openintab", false],
|
||||
|
||||
// Results will include the user's bookmarks when this is true.
|
||||
["suggest.bookmark", true],
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ class FlexItemSizingOutline extends PureComponent {
|
|||
flexItemSizing,
|
||||
} = this.props.flexItem;
|
||||
const {
|
||||
mainAxisDirection,
|
||||
mainBaseSize,
|
||||
mainDeltaSize,
|
||||
mainMaxSize,
|
||||
|
@ -60,8 +61,6 @@ class FlexItemSizingOutline extends PureComponent {
|
|||
clampState,
|
||||
} = flexItemSizing;
|
||||
|
||||
const isRow = this.props.flexDirection.startsWith("row");
|
||||
|
||||
// Calculate the final size. This is base + delta, then clamped by min or max.
|
||||
let mainFinalSize = mainBaseSize + mainDeltaSize;
|
||||
mainFinalSize = Math.max(mainFinalSize, mainMinSize);
|
||||
|
@ -142,9 +141,8 @@ class FlexItemSizingOutline extends PureComponent {
|
|||
dom.div({ className: "flex-outline-container" },
|
||||
dom.div(
|
||||
{
|
||||
className: "flex-outline" +
|
||||
(isRow ? " row" : " column") +
|
||||
(mainDeltaSize > 0 ? " growing" : " shrinking"),
|
||||
className: `flex-outline ${mainAxisDirection}` +
|
||||
(mainDeltaSize > 0 ? " growing" : " shrinking"),
|
||||
style: {
|
||||
gridTemplateColumns,
|
||||
},
|
||||
|
|
|
@ -37,6 +37,7 @@ support-files =
|
|||
[browser_flexbox_item_outline_hidden_when_useless.js]
|
||||
[browser_flexbox_item_outline_renders_basisfinal_points_correctly.js]
|
||||
[browser_flexbox_item_outline_rotates_for_column.js]
|
||||
[browser_flexbox_item_outline_rotates_for_different_writing_modes.js]
|
||||
[browser_flexbox_non_flex_item_is_not_shown.js]
|
||||
[browser_flexbox_pseudo_elements_are_listed.js]
|
||||
[browser_flexbox_sizing_flexibility_not_displayed_when_useless.js]
|
||||
|
|
|
@ -19,7 +19,8 @@ add_task(async function() {
|
|||
await selectNode(".container .item", inspector);
|
||||
let [flexOutline] = await onFlexItemOutlineRendered;
|
||||
|
||||
ok(flexOutline.classList.contains("row"), "The flex outline has the row class");
|
||||
ok(flexOutline.classList.contains("horizontal-lr"),
|
||||
"The flex outline has the horizontal-lr class");
|
||||
|
||||
// Check that the outline is wider than it is tall in the configuration.
|
||||
let bounds = flexOutline.getBoxQuads()[0].getBounds();
|
||||
|
@ -30,10 +31,10 @@ add_task(async function() {
|
|||
".flex-outline-container .flex-outline");
|
||||
await selectNode(".container.column .item", inspector);
|
||||
await waitUntil(() => {
|
||||
flexOutline = doc.querySelector(".flex-outline-container .flex-outline.column");
|
||||
flexOutline = doc.querySelector(".flex-outline-container .flex-outline.vertical-tb");
|
||||
return flexOutline;
|
||||
});
|
||||
ok(true, "The flex outline has the column class");
|
||||
ok(true, "The flex outline has the vertical-tb class");
|
||||
|
||||
// Check that the outline is taller than it is wide in the configuration.
|
||||
bounds = flexOutline.getBoxQuads()[0].getBounds();
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the flex item outline is rotated to match its main axis direction.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_flexbox_writing_modes.html";
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(TEST_URI);
|
||||
const { inspector, flexboxInspector } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
info("Check that a vertical row flex item rotates to vertical-tb.");
|
||||
let onFlexItemOutlineRendered = waitForDOM(doc,
|
||||
".flex-outline-container .flex-outline");
|
||||
await selectNode(".row.vertical.item", inspector);
|
||||
let [flexOutline] = await onFlexItemOutlineRendered;
|
||||
|
||||
ok(flexOutline.classList.contains("vertical-tb"),
|
||||
"Horizontal item outline orientation has been rotated to vertical-tb.");
|
||||
|
||||
info("Check that a vertical-rl column flex item rotates to horizontal-rl.");
|
||||
onFlexItemOutlineRendered = waitForDOM(doc,
|
||||
".flex-outline-container .flex-outline");
|
||||
await selectNode(".column.vertical.item", inspector);
|
||||
await waitUntil(() => {
|
||||
flexOutline =
|
||||
doc.querySelector(".flex-outline-container .flex-outline.horizontal-rl");
|
||||
return flexOutline;
|
||||
});
|
||||
|
||||
ok(true, "Vertical-rl item outline orientation has been rotated to horizontal-rl.");
|
||||
});
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
|
||||
.flex-container.vertical-writing-mode {
|
||||
writing-mode: vertical-lr;
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
.column {
|
||||
|
|
|
@ -135,6 +135,7 @@ skip-if = (verify && debug && os == 'win')
|
|||
[browser_rules_edit-property_07.js]
|
||||
[browser_rules_edit-property_08.js]
|
||||
[browser_rules_edit-property_09.js]
|
||||
[browser_rules_edit-property_10.js]
|
||||
[browser_rules_edit-selector-click.js]
|
||||
[browser_rules_edit-selector-click-on-scrollbar.js]
|
||||
skip-if = os == "mac" # Bug 1245996 : click on scrollbar not working on OSX
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that CSS property names are case insensitive when validating.
|
||||
|
||||
const TEST_URI = `
|
||||
<style type='text/css'>
|
||||
div {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
<div></div>
|
||||
`;
|
||||
|
||||
add_task(async function() {
|
||||
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
const { inspector, view: ruleView } = await openRuleView();
|
||||
|
||||
await selectNode("div", inspector);
|
||||
const rule = getRuleViewRuleEditor(ruleView, 1).rule;
|
||||
const prop = rule.textProps[0];
|
||||
let onRuleViewChanged;
|
||||
|
||||
info(`Rename the CSS property name to "Color"`);
|
||||
onRuleViewChanged = ruleView.once("ruleview-changed");
|
||||
await renameProperty(ruleView, prop, "Color");
|
||||
info("Wait for Rule view to update");
|
||||
await onRuleViewChanged;
|
||||
|
||||
is(prop.overridden, false, "Titlecase property is not overriden");
|
||||
is(prop.enabled, true, "Titlecase property is enabled");
|
||||
is(prop.isNameValid(), true, "Titlecase property is valid");
|
||||
|
||||
info(`Rename the CSS property name to "COLOR"`);
|
||||
onRuleViewChanged = ruleView.once("ruleview-changed");
|
||||
await renameProperty(ruleView, prop, "COLOR");
|
||||
info("Wait for Rule view to update");
|
||||
await onRuleViewChanged;
|
||||
|
||||
is(prop.overridden, false, "Uppercase property is not overriden");
|
||||
is(prop.enabled, true, "Uppercase property is enabled");
|
||||
is(prop.isNameValid(), true, "Uppercase property is valid");
|
||||
});
|
|
@ -661,7 +661,7 @@ const ObjectWithURL = __webpack_require__(1853);
|
|||
const GripArray = __webpack_require__(1797);
|
||||
const GripMap = __webpack_require__(1799);
|
||||
const GripMapEntry = __webpack_require__(1800);
|
||||
const Grip = __webpack_require__(1784);
|
||||
const Grip = __webpack_require__(1783);
|
||||
|
||||
// List of all registered template.
|
||||
// XXX there should be a way for extensions to register a new
|
||||
|
@ -796,7 +796,8 @@ StringRep.propTypes = {
|
|||
member: PropTypes.object,
|
||||
object: PropTypes.object.isRequired,
|
||||
openLink: PropTypes.func,
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
title: PropTypes.string
|
||||
};
|
||||
|
||||
function StringRep(props) {
|
||||
|
@ -808,7 +809,8 @@ function StringRep(props) {
|
|||
useQuotes = true,
|
||||
escapeWhitespace = true,
|
||||
member,
|
||||
openLink
|
||||
openLink,
|
||||
title
|
||||
} = props;
|
||||
|
||||
let text = object;
|
||||
|
@ -837,7 +839,8 @@ function StringRep(props) {
|
|||
const config = getElementConfig({
|
||||
className,
|
||||
style,
|
||||
actor: object.actor
|
||||
actor: object.actor,
|
||||
title
|
||||
});
|
||||
|
||||
if (!isLong) {
|
||||
|
@ -877,7 +880,7 @@ function formatText(opts, text) {
|
|||
}
|
||||
|
||||
function getElementConfig(opts) {
|
||||
const { className, style, actor } = opts;
|
||||
const { className, style, actor, title } = opts;
|
||||
|
||||
const config = {};
|
||||
|
||||
|
@ -885,6 +888,10 @@ function getElementConfig(opts) {
|
|||
config["data-link-actor-id"] = actor;
|
||||
}
|
||||
|
||||
if (title) {
|
||||
config.title = title;
|
||||
}
|
||||
|
||||
const classNames = ["objectBox", "objectBox-string"];
|
||||
if (className) {
|
||||
classNames.push(className);
|
||||
|
@ -1036,8 +1043,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -1107,13 +1112,17 @@ function arrayIterator(props, array, max) {
|
|||
let item;
|
||||
|
||||
try {
|
||||
item = ItemRep(_extends({}, props, config, {
|
||||
item = ItemRep({
|
||||
...props,
|
||||
...config,
|
||||
object: array[i]
|
||||
}));
|
||||
});
|
||||
} catch (exc) {
|
||||
item = ItemRep(_extends({}, props, config, {
|
||||
item = ItemRep({
|
||||
...props,
|
||||
...config,
|
||||
object: exc
|
||||
}));
|
||||
});
|
||||
}
|
||||
items.push(item);
|
||||
}
|
||||
|
@ -1141,10 +1150,11 @@ function ItemRep(props) {
|
|||
const { Rep } = __webpack_require__(1767);
|
||||
|
||||
const { object, delim, mode } = props;
|
||||
return span({}, Rep(_extends({}, props, {
|
||||
return span({}, Rep({
|
||||
...props,
|
||||
object: object,
|
||||
mode: mode
|
||||
})), delim);
|
||||
}), delim);
|
||||
}
|
||||
|
||||
function getLength(object) {
|
||||
|
@ -1176,8 +1186,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -1218,7 +1226,7 @@ PropRep.propTypes = {
|
|||
* @return {Array} Array of React elements.
|
||||
*/
|
||||
function PropRep(props) {
|
||||
const Grip = __webpack_require__(1784);
|
||||
const Grip = __webpack_require__(1783);
|
||||
const { Rep } = __webpack_require__(1767);
|
||||
|
||||
let { name, mode, equal, suppressQuotes } = props;
|
||||
|
@ -1232,17 +1240,18 @@ function PropRep(props) {
|
|||
}
|
||||
key = span({ className: "nodeName" }, name);
|
||||
} else {
|
||||
key = Rep(_extends({}, props, {
|
||||
key = Rep({
|
||||
...props,
|
||||
className: "nodeName",
|
||||
object: name,
|
||||
mode: mode || MODE.TINY,
|
||||
defaultRep: Grip
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
return [key, span({
|
||||
className: "objectEqual"
|
||||
}, equal), Rep(_extends({}, props))];
|
||||
}, equal), Rep({ ...props })];
|
||||
}
|
||||
|
||||
// Exports from this module
|
||||
|
@ -1284,14 +1293,12 @@ module.exports = {
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1784:
|
||||
/***/ 1783:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -1419,7 +1426,7 @@ function propIterator(props, object, max) {
|
|||
const propertiesLength = getPropertiesLength(object);
|
||||
|
||||
if (object.preview && object.preview.safeGetterValues) {
|
||||
properties = _extends({}, properties, object.preview.safeGetterValues);
|
||||
properties = { ...properties, ...object.preview.safeGetterValues };
|
||||
}
|
||||
|
||||
let indexes = getPropIndexes(properties, max, isInterestingProp);
|
||||
|
@ -1444,7 +1451,8 @@ function propIterator(props, object, max) {
|
|||
const length = max - indexes.length;
|
||||
|
||||
const symbolsProps = ownSymbols.slice(0, length).map(symbolItem => {
|
||||
return PropRep(_extends({}, props, {
|
||||
return PropRep({
|
||||
...props,
|
||||
mode: MODE.TINY,
|
||||
name: symbolItem,
|
||||
object: symbolItem.descriptor.value,
|
||||
|
@ -1452,7 +1460,7 @@ function propIterator(props, object, max) {
|
|||
defaultRep: Grip,
|
||||
title: null,
|
||||
suppressQuotes
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
propsArray.push(...symbolsProps);
|
||||
|
@ -1494,7 +1502,8 @@ function getProps(componentProps, properties, indexes, suppressQuotes) {
|
|||
const name = propertiesKeys[i];
|
||||
const value = getPropValue(properties[name]);
|
||||
|
||||
return PropRep(_extends({}, componentProps, {
|
||||
return PropRep({
|
||||
...componentProps,
|
||||
mode: MODE.TINY,
|
||||
name,
|
||||
object: value,
|
||||
|
@ -1502,7 +1511,7 @@ function getProps(componentProps, properties, indexes, suppressQuotes) {
|
|||
defaultRep: Grip,
|
||||
title: null,
|
||||
suppressQuotes
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1589,14 +1598,12 @@ module.exports = Grip;
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1785:
|
||||
/***/ 1784:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -2079,7 +2086,7 @@ function makeNodesForProperties(objProps, parent) {
|
|||
|
||||
const parentValue = getValue(parent);
|
||||
|
||||
const allProperties = _extends({}, ownProperties, safeGetterValues);
|
||||
const allProperties = { ...ownProperties, ...safeGetterValues };
|
||||
|
||||
// Ignore properties that are neither non-concrete nor getters/setters.
|
||||
const propertiesNames = sortProperties(Object.keys(allProperties)).filter(name => {
|
||||
|
@ -2230,9 +2237,10 @@ function getEvaluatedItem(item, evaluations) {
|
|||
return item;
|
||||
}
|
||||
|
||||
return _extends({}, item, {
|
||||
return {
|
||||
...item,
|
||||
contents: evaluations.get(item.path)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function getChildrenWithEvaluations(options) {
|
||||
|
@ -2394,20 +2402,6 @@ function getNonPrototypeParentGripValue(item) {
|
|||
return getValue(parentGripNode);
|
||||
}
|
||||
|
||||
function getParentGripValue(item) {
|
||||
const parentNode = getParent(item);
|
||||
if (!parentNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parentGripNode = getClosestGripNode(parentNode);
|
||||
if (!parentGripNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getValue(parentGripNode);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createNode,
|
||||
createGetterNode,
|
||||
|
@ -2418,7 +2412,6 @@ module.exports = {
|
|||
getClosestGripNode,
|
||||
getClosestNonBucketNode,
|
||||
getParent,
|
||||
getParentGripValue,
|
||||
getNonPrototypeParentGripValue,
|
||||
getNumericalPropertiesCount,
|
||||
getValue,
|
||||
|
@ -2464,14 +2457,12 @@ module.exports = {
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1786:
|
||||
/***/ 1785:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
function initialState() {
|
||||
return {
|
||||
expandedPaths: new Set(),
|
||||
|
@ -2487,7 +2478,7 @@ function initialState() {
|
|||
function reducer(state = initialState(), action = {}) {
|
||||
const { type, data } = action;
|
||||
|
||||
const cloneState = overrides => _extends({}, state, overrides);
|
||||
const cloneState = overrides => ({ ...state, ...overrides });
|
||||
|
||||
if (type === "NODE_EXPAND") {
|
||||
return cloneState({
|
||||
|
@ -2576,21 +2567,19 @@ module.exports.default = reducer;
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1787:
|
||||
/***/ 1786:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const client = __webpack_require__(1804);
|
||||
const loadProperties = __webpack_require__(1803);
|
||||
const node = __webpack_require__(1785);
|
||||
const node = __webpack_require__(1784);
|
||||
const { nodeIsError, nodeIsPrimitive } = node;
|
||||
const selection = __webpack_require__(1859);
|
||||
|
||||
|
@ -2611,11 +2600,12 @@ function shouldRenderRootsInReps(roots) {
|
|||
}
|
||||
|
||||
function renderRep(item, props) {
|
||||
return Rep(_extends({}, props, {
|
||||
return Rep({
|
||||
...props,
|
||||
object: node.getValue(item),
|
||||
mode: props.mode || MODE.TINY,
|
||||
defaultRep: Grip
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
@ -3082,8 +3072,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -3257,12 +3245,13 @@ function arrayIterator(props, grip, max) {
|
|||
}
|
||||
|
||||
if (res.length < max) {
|
||||
res.push(Rep(_extends({}, props, {
|
||||
res.push(Rep({
|
||||
...props,
|
||||
object,
|
||||
mode: MODE.TINY,
|
||||
// Do not propagate title to array items reps
|
||||
title: undefined
|
||||
})));
|
||||
}));
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -3565,8 +3554,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -3599,13 +3586,14 @@ function GripMapEntry(props) {
|
|||
|
||||
return span({
|
||||
className: "objectBox objectBox-map-entry"
|
||||
}, PropRep(_extends({}, props, {
|
||||
}, PropRep({
|
||||
...props,
|
||||
name: key,
|
||||
object: value,
|
||||
equal: " \u2192 ",
|
||||
title: null,
|
||||
suppressQuotes: false
|
||||
})));
|
||||
}));
|
||||
}
|
||||
|
||||
function supportsObject(grip, noGrip = false) {
|
||||
|
@ -4473,8 +4461,6 @@ exports.default = Tree;
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -4503,7 +4489,7 @@ const {
|
|||
nodeIsProxy,
|
||||
nodeNeedsNumericalBuckets,
|
||||
nodeIsLongString
|
||||
} = __webpack_require__(1785);
|
||||
} = __webpack_require__(1784);
|
||||
|
||||
function loadItemProperties(item, createObjectClient, createLongStringClient, loadedProperties) {
|
||||
const gripItem = getClosestGripNode(item);
|
||||
|
@ -4547,7 +4533,7 @@ function mergeResponses(responses) {
|
|||
|
||||
for (const response of responses) {
|
||||
if (response.hasOwnProperty("ownProperties")) {
|
||||
data.ownProperties = _extends({}, data.ownProperties, response.ownProperties);
|
||||
data.ownProperties = { ...data.ownProperties, ...response.ownProperties };
|
||||
}
|
||||
|
||||
if (response.ownSymbols && response.ownSymbols.length > 0) {
|
||||
|
@ -4626,7 +4612,7 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
const { getValue, nodeHasFullText } = __webpack_require__(1785); /* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
const { getValue, nodeHasFullText } = __webpack_require__(1784); /* 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/>. */
|
||||
|
||||
|
@ -4877,8 +4863,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -4961,13 +4945,14 @@ function propIterator(props, object, max) {
|
|||
const propertiesNames = Object.keys(object);
|
||||
|
||||
const pushPropRep = (name, value) => {
|
||||
elements.push(PropRep(_extends({}, props, {
|
||||
elements.push(PropRep({
|
||||
...props,
|
||||
key: name,
|
||||
mode: MODE.TINY,
|
||||
name,
|
||||
object: value,
|
||||
equal: ": "
|
||||
})));
|
||||
}));
|
||||
propertiesNumber++;
|
||||
|
||||
if (propertiesNumber < propertiesNames.length) {
|
||||
|
@ -5175,8 +5160,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -5204,11 +5187,12 @@ function Accessor(props) {
|
|||
const { Rep, Grip } = __webpack_require__(1767);
|
||||
return span({
|
||||
className: "objectBox objectBox-accessor objectTitle"
|
||||
}, Rep(_extends({}, props, {
|
||||
}, Rep({
|
||||
...props,
|
||||
object: evaluation.getterValue,
|
||||
mode: props.mode || MODE.TINY,
|
||||
defaultRep: Grip
|
||||
})));
|
||||
}));
|
||||
}
|
||||
|
||||
if (hasGetter(object) && onInvokeGetterButtonClick) {
|
||||
|
@ -5414,7 +5398,7 @@ function Attribute(props) {
|
|||
return span({
|
||||
"data-link-actor-id": object.actor,
|
||||
className: "objectBox-Attr"
|
||||
}, span({ className: "attrName" }, getTitle(object)), span({ className: "attrEqual" }, "="), StringRep({ className: "attrValue", object: value }));
|
||||
}, span({ className: "attrName" }, getTitle(object)), span({ className: "attrEqual" }, "="), StringRep({ className: "attrValue", object: value, title: value }));
|
||||
}
|
||||
|
||||
function getTitle(grip) {
|
||||
|
@ -5628,8 +5612,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -5641,7 +5623,7 @@ const PropTypes = __webpack_require__(1758);
|
|||
const { isGrip, wrapRender } = __webpack_require__(1760);
|
||||
|
||||
const { MODE } = __webpack_require__(1762);
|
||||
const { rep } = __webpack_require__(1784);
|
||||
const { rep } = __webpack_require__(1783);
|
||||
|
||||
/**
|
||||
* Renders DOM event objects.
|
||||
|
@ -5656,14 +5638,17 @@ Event.propTypes = {
|
|||
};
|
||||
|
||||
function Event(props) {
|
||||
const gripProps = _extends({}, props, {
|
||||
const gripProps = {
|
||||
...props,
|
||||
title: getTitle(props),
|
||||
object: _extends({}, props.object, {
|
||||
preview: _extends({}, props.object.preview, {
|
||||
object: {
|
||||
...props.object,
|
||||
preview: {
|
||||
...props.object.preview,
|
||||
ownProperties: {}
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (gripProps.object.preview.target) {
|
||||
Object.assign(gripProps.object.preview.ownProperties, {
|
||||
|
@ -5734,8 +5719,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
/* 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/>. */
|
||||
|
@ -5804,13 +5787,14 @@ function getProps(props, promiseState) {
|
|||
|
||||
return keys.reduce((res, key, i) => {
|
||||
const object = promiseState[key];
|
||||
res = res.concat(PropRep(_extends({}, props, {
|
||||
res = res.concat(PropRep({
|
||||
...props,
|
||||
mode: MODE.TINY,
|
||||
name: `<${key}>`,
|
||||
object,
|
||||
equal: ": ",
|
||||
suppressQuotes: true
|
||||
})));
|
||||
}));
|
||||
|
||||
// Interleave commas between elements
|
||||
if (i !== keys.length - 1) {
|
||||
|
@ -6041,13 +6025,15 @@ const PropTypes = __webpack_require__(1758);
|
|||
|
||||
// Utils
|
||||
const { isGrip, wrapRender } = __webpack_require__(1760);
|
||||
const { rep: StringRep } = __webpack_require__(1770);
|
||||
const { rep: StringRep, isLongString } = __webpack_require__(1770);
|
||||
const { MODE } = __webpack_require__(1762);
|
||||
const nodeConstants = __webpack_require__(1795);
|
||||
|
||||
const dom = __webpack_require__(1759);
|
||||
const { span } = dom;
|
||||
|
||||
const MAX_ATTRIBUTE_LENGTH = 50;
|
||||
|
||||
/**
|
||||
* Renders DOM element node.
|
||||
*/
|
||||
|
@ -6157,7 +6143,18 @@ function getElements(grip, mode) {
|
|||
}
|
||||
const attributeElements = attributeKeys.reduce((arr, name, i, keys) => {
|
||||
const value = attributes[name];
|
||||
const attribute = span({}, span({ className: "attrName" }, name), span({ className: "attrEqual" }, "="), StringRep({ className: "attrValue", object: value }));
|
||||
|
||||
let title = isLongString(value) ? value.initial : value;
|
||||
if (title.length < MAX_ATTRIBUTE_LENGTH) {
|
||||
title = null;
|
||||
}
|
||||
|
||||
const attribute = span({}, span({ className: "attrName" }, name), span({ className: "attrEqual" }, "="), StringRep({
|
||||
className: "attrValue",
|
||||
object: value,
|
||||
cropLimit: MAX_ATTRIBUTE_LENGTH,
|
||||
title
|
||||
}));
|
||||
|
||||
return arr.concat([" ", attribute]);
|
||||
}, []);
|
||||
|
@ -6176,7 +6173,8 @@ function supportsObject(object, noGrip = false) {
|
|||
// Exports from this module
|
||||
module.exports = {
|
||||
rep: wrapRender(ElementNode),
|
||||
supportsObject
|
||||
supportsObject,
|
||||
MAX_ATTRIBUTE_LENGTH
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
@ -6502,8 +6500,8 @@ module.exports = {
|
|||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const ObjectInspector = __webpack_require__(1855);
|
||||
const utils = __webpack_require__(1787);
|
||||
const reducer = __webpack_require__(1786);
|
||||
const utils = __webpack_require__(1786);
|
||||
const reducer = __webpack_require__(1785);
|
||||
|
||||
module.exports = { ObjectInspector, utils, reducer };
|
||||
|
||||
|
@ -6515,8 +6513,6 @@ module.exports = { ObjectInspector, utils, reducer };
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
var _devtoolsComponents = __webpack_require__(1791);
|
||||
|
||||
var _devtoolsComponents2 = _interopRequireDefault(_devtoolsComponents);
|
||||
|
@ -6531,7 +6527,7 @@ const { Component, createFactory, createElement } = __webpack_require__(0);
|
|||
const { connect } = __webpack_require__(1763);
|
||||
const actions = __webpack_require__(1856);
|
||||
|
||||
const selectors = __webpack_require__(1786);
|
||||
const selectors = __webpack_require__(1785);
|
||||
|
||||
const Tree = createFactory(_devtoolsComponents2.default.Tree);
|
||||
__webpack_require__(1857);
|
||||
|
@ -6540,7 +6536,7 @@ const ObjectInspectorItem = createFactory(__webpack_require__(1858));
|
|||
|
||||
const classnames = __webpack_require__(175);
|
||||
|
||||
const Utils = __webpack_require__(1787);
|
||||
const Utils = __webpack_require__(1786);
|
||||
const { renderRep, shouldRenderRootsInReps } = Utils;
|
||||
const {
|
||||
getChildrenWithEvaluations,
|
||||
|
@ -6750,14 +6746,15 @@ class ObjectInspector extends Component {
|
|||
onCollapse: item => this.setExpanded(item, false),
|
||||
onFocus: focusable ? this.focusItem : null,
|
||||
|
||||
renderItem: (item, depth, focused, arrow, expanded) => ObjectInspectorItem(_extends({}, this.props, {
|
||||
renderItem: (item, depth, focused, arrow, expanded) => ObjectInspectorItem({
|
||||
...this.props,
|
||||
item,
|
||||
depth,
|
||||
focused,
|
||||
arrow,
|
||||
expanded,
|
||||
setExpanded: this.setExpanded
|
||||
}))
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -6793,7 +6790,7 @@ const { loadItemProperties } = __webpack_require__(1803); /* This Source Code Fo
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const { getLoadedProperties, getActors } = __webpack_require__(1786);
|
||||
const { getLoadedProperties, getActors } = __webpack_require__(1785);
|
||||
|
||||
/**
|
||||
* This action is responsible for expanding a given node, which also means that
|
||||
|
@ -6917,8 +6914,6 @@ module.exports = {
|
|||
"use strict";
|
||||
|
||||
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
var _devtoolsServices = __webpack_require__(22);
|
||||
|
||||
var _devtoolsServices2 = _interopRequireDefault(_devtoolsServices);
|
||||
|
@ -6938,7 +6933,7 @@ const isMacOS = appinfo.OS === "Darwin";
|
|||
const classnames = __webpack_require__(175);
|
||||
const { MODE } = __webpack_require__(1762);
|
||||
|
||||
const Utils = __webpack_require__(1787);
|
||||
const Utils = __webpack_require__(1786);
|
||||
|
||||
const {
|
||||
getValue,
|
||||
|
@ -7012,14 +7007,15 @@ class ObjectInspectorItem extends Component {
|
|||
|
||||
if (nodeIsFunction(item) && !nodeIsGetter(item) && !nodeIsSetter(item) && (mode === MODE.TINY || !mode)) {
|
||||
return {
|
||||
label: Utils.renderRep(item, _extends({}, this.props, {
|
||||
label: Utils.renderRep(item, {
|
||||
...this.props,
|
||||
functionName: label
|
||||
}))
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
if (nodeHasProperties(item) || nodeHasAccessors(item) || nodeIsMapEntry(item) || nodeIsLongString(item) || isPrimitive) {
|
||||
const repProps = _extends({}, this.props);
|
||||
const repProps = { ...this.props };
|
||||
if (depth > 0) {
|
||||
repProps.mode = mode === MODE.LONG ? MODE.SHORT : MODE.TINY;
|
||||
}
|
||||
|
@ -7119,10 +7115,10 @@ class ObjectInspectorItem extends Component {
|
|||
onClick: onLabelClick ? event => {
|
||||
event.stopPropagation();
|
||||
|
||||
const objectProperty = /([\w\d\$]+)$/;
|
||||
const arrayProperty = /\[(.*?)\]$/;
|
||||
const functionProperty = /([\w\d]+)[\/\.<]*?$/;
|
||||
const annonymousProperty = /([\w\d]+)\(\^\)$/;
|
||||
// If the user selected text, bail out.
|
||||
if (Utils.selection.documentHasSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
onLabelClick(item, {
|
||||
depth,
|
||||
|
@ -7190,4 +7186,4 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_22__;
|
|||
/***/ })
|
||||
|
||||
/******/ });
|
||||
});
|
||||
});
|
|
@ -280,7 +280,7 @@ html[dir="rtl"] .flex-item-list .devtools-button::after {
|
|||
min-width: 10px;
|
||||
}
|
||||
|
||||
.flex-outline.column {
|
||||
.flex-outline.vertical-tb {
|
||||
transform: translate(50%, -2em) rotate(.25turn);
|
||||
transform-origin: center left;
|
||||
flex-basis: 150px;
|
||||
|
@ -321,7 +321,7 @@ html[dir="rtl"] .flex-item-list .devtools-button::after {
|
|||
drop-shadow(0px -1px 0px var(--theme-body-background));
|
||||
}
|
||||
|
||||
.flex-outline.column .flex-outline-final.clamped::after {
|
||||
.flex-outline.vertical-tb .flex-outline-final.clamped::after {
|
||||
transform: rotate(-.25turn);
|
||||
}
|
||||
|
||||
|
@ -404,8 +404,14 @@ html[dir="rtl"] .flex-item-list .devtools-button::after {
|
|||
display: grid;
|
||||
}
|
||||
|
||||
.flex-outline.horizontal-rl .flex-outline-point {
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
.flex-outline-point.basis,
|
||||
.flex-outline-point.basisfinal {
|
||||
.flex-outline-point.basisfinal,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.basis,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.basisfinal {
|
||||
grid-column-end: basis-end;
|
||||
justify-self: end;
|
||||
color: var(--theme-highlight-blue);
|
||||
|
@ -416,6 +422,11 @@ html[dir="rtl"] .flex-item-list .devtools-button::after {
|
|||
justify-self: start;
|
||||
}
|
||||
|
||||
.flex-outline.horizontal-rl.shrinking .flex-outline-point.basis {
|
||||
grid-column-start: basis-start;
|
||||
justify-self: unset;
|
||||
}
|
||||
|
||||
.flex-outline-point.final {
|
||||
grid-column-start: final-end;
|
||||
left: -1px;
|
||||
|
@ -453,7 +464,7 @@ html[dir="rtl"] .flex-item-list .devtools-button::after {
|
|||
border-width: 0;
|
||||
}
|
||||
|
||||
.flex-outline.column .flex-outline-point::before {
|
||||
.flex-outline.vertical-tb .flex-outline-point::before {
|
||||
padding: 0;
|
||||
writing-mode: sideways-lr;
|
||||
}
|
||||
|
@ -469,25 +480,42 @@ html[dir="rtl"] .flex-item-list .devtools-button::after {
|
|||
bottom: -12px;
|
||||
}
|
||||
|
||||
.flex-outline.column .flex-outline-point.max::before,
|
||||
.flex-outline.column .flex-outline-point.min::before {
|
||||
.flex-outline.horizontal-rl .flex-outline-point.min::before,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.max::before {
|
||||
bottom: -37px;
|
||||
}
|
||||
|
||||
.flex-outline.vertical-tb .flex-outline-point.max::before,
|
||||
.flex-outline.vertical-tb .flex-outline-point.min::before {
|
||||
text-indent: -12px;
|
||||
}
|
||||
|
||||
.flex-outline-point.final::before,
|
||||
.flex-outline.shrinking .flex-outline-point.min::before,
|
||||
.flex-outline-point.max::before,
|
||||
.flex-outline.shrinking .flex-outline-point.basis::before {
|
||||
.flex-outline.shrinking .flex-outline-point.basis::before,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.basis::before,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.basisfinal::before,
|
||||
.flex-outline.horizontal-rl.shrinking .flex-outline-point.final::before {
|
||||
border-width: 0 0 0 1px;
|
||||
}
|
||||
|
||||
.flex-outline-point.basis::before,
|
||||
.flex-outline-point.min::before,
|
||||
.flex-outline.shrinking .flex-outline-point.final::before,
|
||||
.flex-outline-point.basisfinal::before {
|
||||
.flex-outline-point.basisfinal::before,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.final::before,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.min::before,
|
||||
.flex-outline.horizontal-rl .flex-outline-point.max::before {
|
||||
border-width: 0 1px 0 0;
|
||||
}
|
||||
|
||||
.flex-outline.horizontal-rl,
|
||||
.flex-outline.horizontal-rl .flex-outline-point,
|
||||
.flex-outline.horizontal-rl .flex-outline-final.clamped::after {
|
||||
transform: rotate(.5turn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flex Item Sizing Properties
|
||||
*/
|
||||
|
|
|
@ -344,6 +344,7 @@ skip-if = true # Bug 1438979
|
|||
[browser_webconsole_object_ctrl_click.js]
|
||||
[browser_webconsole_object_in_sidebar_keyboard_nav.js]
|
||||
[browser_webconsole_object_inspector.js]
|
||||
[browser_webconsole_object_inspector__proto__.js]
|
||||
[browser_webconsole_object_inspector_entries.js]
|
||||
[browser_webconsole_object_inspector_getters.js]
|
||||
[browser_webconsole_object_inspector_getters_prototype.js]
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Check displaying object with __proto__ in the console.
|
||||
const TEST_URI = "data:text/html;charset=utf8,<h1>test Object Inspector __proto__</h1>";
|
||||
|
||||
add_task(async function() {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
logAllStoreChanges(hud);
|
||||
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
|
||||
const obj = Object.create(null);
|
||||
// eslint-disable-next-line no-proto
|
||||
obj.__proto__ = [];
|
||||
content.wrappedJSObject.console.log("oi-test", obj);
|
||||
});
|
||||
|
||||
const node = await waitFor(() => findMessage(hud, "oi-test"));
|
||||
const objectInspector = node.querySelector(".tree");
|
||||
ok(objectInspector, "Object is printed in the console");
|
||||
|
||||
is(objectInspector.textContent.trim(), "Object { __proto__: [] }",
|
||||
"Object is displayed as expected");
|
||||
|
||||
objectInspector.querySelector(".arrow").click();
|
||||
await waitFor(() => node.querySelectorAll(".tree-node").length === 2);
|
||||
|
||||
const __proto__Node = node.querySelector(".tree-node:last-of-type");
|
||||
ok(__proto__Node.textContent.includes("__proto__: Array []"),
|
||||
"__proto__ node is displayed as expected");
|
||||
});
|
|
@ -103,6 +103,7 @@ CssProperties.prototype = {
|
|||
* @return {Boolean}
|
||||
*/
|
||||
isKnown(property) {
|
||||
property = property.toLowerCase();
|
||||
return !!this.properties[property] || isCssVariable(property);
|
||||
},
|
||||
|
||||
|
@ -197,6 +198,7 @@ CssProperties.prototype = {
|
|||
* @return {Array} An array of subproperty names.
|
||||
*/
|
||||
getSubproperties(name) {
|
||||
name = name.toLowerCase();
|
||||
if (this.isKnown(name)) {
|
||||
if (this.properties[name] && this.properties[name].subproperties) {
|
||||
return this.properties[name].subproperties;
|
||||
|
|
|
@ -665,9 +665,13 @@ nsDocShell::LoadURI(nsDocShellLoadState* aLoadState) {
|
|||
"Should not have these flags set");
|
||||
MOZ_ASSERT(aLoadState->URI(), "Should have a valid URI to load");
|
||||
|
||||
if (mUseStrictSecurityChecks && !aLoadState->TriggeringPrincipal()) {
|
||||
if (!aLoadState->TriggeringPrincipal()) {
|
||||
#ifndef ANDROID
|
||||
MOZ_ASSERT(false, "LoadURI must have a triggering principal");
|
||||
return NS_ERROR_FAILURE;
|
||||
#endif
|
||||
if (mUseStrictSecurityChecks) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: we allow loads to get through here even if mFiredUnloadEvent is
|
||||
|
@ -3863,9 +3867,6 @@ nsDocShell::LoadURI(const nsAString& aURI, uint32_t aLoadFlags,
|
|||
nsIURI* aReferringURI, nsIInputStream* aPostStream,
|
||||
nsIInputStream* aHeaderStream,
|
||||
nsIPrincipal* aTriggeringPrincipal) {
|
||||
#ifndef ANDROID
|
||||
MOZ_ASSERT(aTriggeringPrincipal, "LoadURI: Need a valid triggeringPrincipal");
|
||||
#endif
|
||||
if (mUseStrictSecurityChecks && !aTriggeringPrincipal) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -3901,11 +3902,6 @@ nsDocShell::LoadURIWithOptions(const nsAString& aURI, uint32_t aLoadFlags,
|
|||
uriString.StripCRLF();
|
||||
NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
|
||||
|
||||
#ifndef ANDROID
|
||||
MOZ_ASSERT(aTriggeringPrincipal,
|
||||
"LoadURIWithOptions: Need a valid triggeringPrincipal");
|
||||
#endif
|
||||
|
||||
if (mUseStrictSecurityChecks && !aTriggeringPrincipal) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -8310,7 +8306,9 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType,
|
|||
FireOnLocationChange(this, failedChannel, failedURI,
|
||||
LOCATION_CHANGE_ERROR_PAGE);
|
||||
} else if (onLocationChangeNeeded) {
|
||||
FireOnLocationChange(this, aRequest, mCurrentURI, 0);
|
||||
uint32_t locationFlags =
|
||||
(mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
|
||||
FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -333,9 +333,6 @@ nsresult nsDocShellLoadState::SetupTriggeringPrincipal(
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
#ifndef ANDROID
|
||||
MOZ_ASSERT(false, "LoadURI: System principal required.");
|
||||
#endif
|
||||
mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,6 +185,7 @@ namespace dom {
|
|||
|
||||
JS::Rooted<JS::IdVector> ids(cx, JS::IdVector(cx));
|
||||
JS::AutoValueVector values(cx);
|
||||
JS::AutoIdVector valuesIds(cx);
|
||||
|
||||
{
|
||||
JS::RootedObject obj(cx, js::CheckedUnwrap(aObj));
|
||||
|
@ -200,7 +201,8 @@ namespace dom {
|
|||
|
||||
JSAutoRealm ar(cx, obj);
|
||||
|
||||
if (!JS_Enumerate(cx, obj, &ids) || !values.reserve(ids.length())) {
|
||||
if (!JS_Enumerate(cx, obj, &ids) || !values.reserve(ids.length()) ||
|
||||
!valuesIds.reserve(ids.length())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -214,6 +216,7 @@ namespace dom {
|
|||
if (desc.setter() || desc.getter()) {
|
||||
continue;
|
||||
}
|
||||
valuesIds.infallibleAppend(id);
|
||||
values.infallibleAppend(desc.value());
|
||||
}
|
||||
}
|
||||
|
@ -237,8 +240,8 @@ namespace dom {
|
|||
|
||||
JS::RootedValue value(cx);
|
||||
JS::RootedId id(cx);
|
||||
for (uint32_t i = 0; i < ids.length(); i++) {
|
||||
id = ids[i];
|
||||
for (uint32_t i = 0; i < valuesIds.length(); i++) {
|
||||
id = valuesIds[i];
|
||||
value = values[i];
|
||||
|
||||
JS_MarkCrossZoneId(cx, id);
|
||||
|
|
|
@ -332,7 +332,6 @@ nsAtom* nsIContent::GetLang() const {
|
|||
already_AddRefed<nsIURI> nsIContent::GetBaseURI(
|
||||
bool aTryUseXHRDocBaseURI) const {
|
||||
if (SVGUseElement* use = GetContainingSVGUseShadowHost()) {
|
||||
// XXX Ignore xml:base as we are removing it.
|
||||
if (URLExtraData* data = use->GetContentURLData()) {
|
||||
return do_AddRef(data->BaseURI());
|
||||
}
|
||||
|
@ -342,60 +341,6 @@ already_AddRefed<nsIURI> nsIContent::GetBaseURI(
|
|||
// Start with document base
|
||||
nsCOMPtr<nsIURI> base = doc->GetBaseURI(aTryUseXHRDocBaseURI);
|
||||
|
||||
// Collect array of xml:base attribute values up the parent chain. This
|
||||
// is slightly slower for the case when there are xml:base attributes, but
|
||||
// faster for the far more common case of there not being any such
|
||||
// attributes.
|
||||
// Also check for SVG elements which require special handling
|
||||
AutoTArray<nsString, 5> baseAttrs;
|
||||
nsString attr;
|
||||
const nsIContent* elem = this;
|
||||
do {
|
||||
// First check for SVG specialness (why is this SVG specific?)
|
||||
if (elem->IsSVGElement()) {
|
||||
nsIContent* bindingParent = elem->GetBindingParent();
|
||||
if (bindingParent) {
|
||||
nsXBLBinding* binding = bindingParent->GetXBLBinding();
|
||||
if (binding) {
|
||||
// XXX sXBL/XBL2 issue
|
||||
// If this is an anonymous XBL element use the binding
|
||||
// document for the base URI.
|
||||
// XXX Will fail with xml:base
|
||||
base = binding->PrototypeBinding()->DocURI();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise check for xml:base attribute
|
||||
if (elem->IsElement()) {
|
||||
elem->AsElement()->GetAttr(kNameSpaceID_XML, nsGkAtoms::base, attr);
|
||||
if (!attr.IsEmpty()) {
|
||||
baseAttrs.AppendElement(attr);
|
||||
}
|
||||
}
|
||||
elem = elem->GetParent();
|
||||
} while (elem);
|
||||
|
||||
if (!baseAttrs.IsEmpty()) {
|
||||
doc->WarnOnceAbout(nsIDocument::eXMLBaseAttribute);
|
||||
// Now resolve against all xml:base attrs
|
||||
for (uint32_t i = baseAttrs.Length() - 1; i != uint32_t(-1); --i) {
|
||||
nsCOMPtr<nsIURI> newBase;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(newBase), baseAttrs[i],
|
||||
doc->GetDocumentCharacterSet(), base);
|
||||
// Do a security check, almost the same as nsDocument::SetBaseURL()
|
||||
// Only need to do this on the final uri
|
||||
if (NS_SUCCEEDED(rv) && i == 0) {
|
||||
rv = nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
|
||||
NodePrincipal(), newBase, nsIScriptSecurityManager::STANDARD);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
base.swap(newBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return base.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ DEPRECATED_OPERATION(AppCacheInsecure)
|
|||
DEPRECATED_OPERATION(PrefixedImageSmoothingEnabled)
|
||||
DEPRECATED_OPERATION(LenientSetter)
|
||||
DEPRECATED_OPERATION(ImageBitmapRenderingContext_TransferImageBitmap)
|
||||
DEPRECATED_OPERATION(XMLBaseAttribute)
|
||||
DEPRECATED_OPERATION(WindowContentUntrusted)
|
||||
DEPRECATED_OPERATION(RegisterProtocolHandlerInsecure)
|
||||
DEPRECATED_OPERATION(MixedDisplayObjectSubrequest)
|
||||
|
|
|
@ -5069,7 +5069,17 @@ void nsGlobalWindowOuter::NotifyContentBlockingState(unsigned aState,
|
|||
state &= ~aState;
|
||||
}
|
||||
|
||||
if (state == oldState) {
|
||||
if (state == oldState
|
||||
#ifdef ANDROID
|
||||
// GeckoView always needs to notify about blocked trackers, since the
|
||||
// GeckoView API always needs to report the URI and type of any blocked
|
||||
// tracker.
|
||||
// We use a platform-dependent code path here because reporting this
|
||||
// notification on desktop platforms isn't necessary and doing so can have
|
||||
// a big performance cost.
|
||||
&& aState != nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT
|
||||
#endif
|
||||
) {
|
||||
// Avoid dispatching repeated notifications when nothing has changed
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1231,15 +1231,6 @@ void nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
|
|||
}
|
||||
// else not allowed
|
||||
} else if (kNameSpaceID_XML == attrNs) {
|
||||
if (nsGkAtoms::base == attrLocal) {
|
||||
if (SanitizeURL(aElement, attrNs, attrLocal)) {
|
||||
// in case the attribute removal shuffled the attribute order, start
|
||||
// the loop again.
|
||||
--ac;
|
||||
i = ac; // i will be decremented immediately thanks to the for loop
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -437,8 +437,6 @@ support-files = file_bug503473-frame.sjs
|
|||
skip-if = toolkit == 'android' #TIMED_OUT
|
||||
[test_bug503481b.html]
|
||||
skip-if = toolkit == 'android' #TIMED_OUT
|
||||
[test_bug505783.html]
|
||||
skip-if = toolkit == 'android' #TIMED_OUT
|
||||
[test_bug513194.html]
|
||||
[test_bug514487.html]
|
||||
[test_bug515401.html]
|
||||
|
|
|
@ -21,12 +21,12 @@ addLoadEvent(function() {
|
|||
"body base");
|
||||
|
||||
var expected =
|
||||
["http://mochi.test:8888/tests/dom/base/supercalifragilisticexpialidocious",
|
||||
"http://mochi.test:8888/tests/dom/base/supercalifragilisticexpialidocious",
|
||||
"http://mochi.test:8888/tests/dom/base/hello/",
|
||||
"http://mochi.test:8888/tests/dom/base/hello/world",
|
||||
"http://mochi.test:8888/tests/dom/base/hello/world#iamtheverymodelofamodernmajorgeneral",
|
||||
"http://mochi.test:8888/tests/dom/base/hello/world#iamtheverymodelofamodernmajorgeneral",
|
||||
["http://mochi.test:8888/tests/dom/base/",
|
||||
"http://mochi.test:8888/tests/dom/base/",
|
||||
"http://mochi.test:8888/tests/dom/base/",
|
||||
"http://mochi.test:8888/tests/dom/base/",
|
||||
"http://mochi.test:8888/tests/dom/base/",
|
||||
"http://mochi.test:8888/tests/dom/base/",
|
||||
];
|
||||
var node = document.getElementById("1");
|
||||
while(node) {
|
||||
|
@ -36,9 +36,9 @@ addLoadEvent(function() {
|
|||
is(expected.length, 0, "found all expected nodes");
|
||||
|
||||
var svgExpected =
|
||||
["http://mochi.test:8888/tests/dom/base/test/file_base_xbl.xml",
|
||||
"http://mochi.test:8888/tests/dom/base/test/file_base_xbl.xml",
|
||||
"http://mochi.test:8888/tests/dom/base/test/file_base_xbl.xml#shesellsseashellsbytheseashore",
|
||||
["http://mochi.test:8888/tests/dom/base/",
|
||||
"http://mochi.test:8888/tests/dom/base/",
|
||||
"http://mochi.test:8888/tests/dom/base/",
|
||||
];
|
||||
node = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById("bound"))[0];
|
||||
while(node) {
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=505783
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 505783</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<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=505783">Mozilla Bug 505783</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 505783 **/
|
||||
|
||||
var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
|
||||
a.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:base", "http://example.org/");
|
||||
a.href = "page";
|
||||
is(a.href, "http://example.org/page", "xml:base not used when not in doc");
|
||||
document.getElementById("content").appendChild(a);
|
||||
is(a.href, "http://example.org/page", "xml:base not used when in doc");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
|
||||
add_task(function test_shallowclone() {
|
||||
// Check that shallow cloning an object with regular properties,
|
||||
// results into a new object with all properties from the source object.
|
||||
const fullyCloneableObject = {
|
||||
numProp: 123,
|
||||
strProp: "str",
|
||||
boolProp: true,
|
||||
arrayProp: [{item1: "1", item2: "2"}],
|
||||
fnProp() { return "fn result"; },
|
||||
promise: Promise.resolve("promised-value"),
|
||||
weakmap: new WeakMap(),
|
||||
proxy: new Proxy({}, {}),
|
||||
};
|
||||
|
||||
let clonedObject = ChromeUtils.shallowClone(fullyCloneableObject);
|
||||
|
||||
Assert.deepEqual(clonedObject, fullyCloneableObject,
|
||||
"Got the expected cloned object for an object with regular properties");
|
||||
|
||||
// Check that shallow cloning an object with getters and setters properties,
|
||||
// results into a new object without all the properties from the source object excluded
|
||||
// its getters and setters.
|
||||
const objectWithGetterAndSetter = {
|
||||
get myGetter() { return "getter result"; },
|
||||
set mySetter(v) {},
|
||||
myFunction() { return "myFunction result"; },
|
||||
};
|
||||
|
||||
clonedObject = ChromeUtils.shallowClone(objectWithGetterAndSetter);
|
||||
|
||||
Assert.deepEqual(clonedObject, {
|
||||
myFunction: objectWithGetterAndSetter.myFunction,
|
||||
}, "Got the expected cloned object for an object with getters and setters");
|
||||
|
||||
|
||||
// Check that shallow cloning a proxy object raises the expected exception..
|
||||
const proxyObject = new Proxy(fullyCloneableObject, {});
|
||||
|
||||
Assert.throws(
|
||||
() => { ChromeUtils.shallowClone(proxyObject); },
|
||||
/Shallow cloning a proxy object is not allowed/,
|
||||
"Got the expected error on ChromeUtils.shallowClone called on a proxy object");
|
||||
});
|
|
@ -54,6 +54,7 @@ head = head_xml.js
|
|||
[test_xmlserializer.js]
|
||||
[test_cancelPrefetch.js]
|
||||
[test_chromeutils_base64.js]
|
||||
[test_chromeutils_shallowclone.js]
|
||||
[test_generate_xpath.js]
|
||||
head = head_xml.js
|
||||
[test_js_dev_error_interceptor.js]
|
||||
|
|
|
@ -120,8 +120,8 @@ void HTMLAnchorElement::UnbindFromTree(bool aDeep, bool aNullParent) {
|
|||
CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
|
||||
HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
// Without removing the link state we risk a dangling pointer
|
||||
// in the mStyledLinks hashtable
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
|
|
@ -82,8 +82,8 @@ nsresult HTMLAreaElement::BindToTree(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
void HTMLAreaElement::UnbindFromTree(bool aDeep, bool aNullParent) {
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
// Without removing the link state we risk a dangling pointer
|
||||
// in the mStyledLinks hashtable
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
|
|
@ -154,8 +154,8 @@ void HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent) {
|
|||
HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
CancelPrefetchOrPreload();
|
||||
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
// Without removing the link state we risk a dangling pointer
|
||||
// in the mStyledLinks hashtable
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
|
||||
// If this is reinserted back into the document it will not be
|
||||
|
|
|
@ -10,6 +10,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=481335
|
|||
a { color:blue; }
|
||||
a:visited { color:red; }
|
||||
</style>
|
||||
<base href="http://www.example.com/" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481335">Mozilla Bug 481335</a>
|
||||
|
@ -17,7 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=481335
|
|||
<a id="t">A link</a>
|
||||
<iframe id="i"></iframe>
|
||||
</p>
|
||||
<p id="newparent" xml:base="http://www.example.com/"></p>
|
||||
<p id="newparent"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
@ -33,11 +34,9 @@ is($("t").href, "",
|
|||
"Unexpected cached href before set");
|
||||
|
||||
$("t").setAttribute("href", rand);
|
||||
is($("t").href,
|
||||
window.location.href.replace(/test_bug481335.xhtml([\?].*)?/, rand),
|
||||
is($("t").href, "http://www.example.com/" + rand,
|
||||
"Unexpected href after set");
|
||||
is($("t").href,
|
||||
window.location.href.replace(/test_bug481335.xhtml([\?].*)?/, rand),
|
||||
is($("t").href, "http://www.example.com/" + rand,
|
||||
"Unexpected cached href after set");
|
||||
const unvisitedColor = "rgb(0, 0, 255)";
|
||||
const visitedColor = "rgb(255, 0, 0)";
|
||||
|
|
|
@ -317,8 +317,6 @@ LargeAllocationNonE10S=A Large-Allocation header was ignored due to the document
|
|||
GeolocationInsecureRequestIsForbidden=A Geolocation request can only be fulfilled in a secure context.
|
||||
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name.
|
||||
LargeAllocationNonWin32=This page would be loaded in a new process due to a Large-Allocation header, however Large-Allocation process creation is disabled on non-Win32 platforms.
|
||||
# LOCALIZATION NOTE: Do not translate xml:base.
|
||||
XMLBaseAttributeWarning=Use of xml:base attribute is deprecated and will be removed soon. Please remove any use of it.
|
||||
# LOCALIZATION NOTE: Do not translate "content", "Window", and "window.top"
|
||||
WindowContentUntrustedWarning=The ‘content’ attribute of Window objects is deprecated. Please use ‘window.top’ instead.
|
||||
# LOCALIZATION NOTE: The first %S is the tag name of the element that starts the loop, the second %S is the element's ID.
|
||||
|
|
|
@ -96,8 +96,8 @@ nsresult nsMathMLElement::BindToTree(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
void nsMathMLElement::UnbindFromTree(bool aDeep, bool aNullParent) {
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
// Without removing the link state we risk a dangling pointer
|
||||
// in the mStyledLinks hashtable
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
|
||||
nsMathMLElementBase::UnbindFromTree(aDeep, aNullParent);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
|
||||
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://testing-common/httpd.js");
|
||||
|
||||
|
@ -33,7 +33,7 @@ function makeReportHandler(testpath, message, expectedJSON) {
|
|||
? request.getHeader("Content-Type") : undefined;
|
||||
if (contentType !== "application/csp-report") {
|
||||
do_throw("violation report should have the 'application/csp-report' " +
|
||||
"content-type, when in fact it is " + contentType.toString())
|
||||
"content-type, when in fact it is " + contentType.toString());
|
||||
}
|
||||
|
||||
// obtain violation report
|
||||
|
@ -47,7 +47,7 @@ function makeReportHandler(testpath, message, expectedJSON) {
|
|||
// dump("EXPECTED: \n" + JSON.stringify(expectedJSON) + "\n\n");
|
||||
|
||||
for (var i in expectedJSON)
|
||||
Assert.equal(expectedJSON[i], reportObj['csp-report'][i]);
|
||||
Assert.equal(expectedJSON[i], reportObj["csp-report"][i]);
|
||||
|
||||
testsToFinish--;
|
||||
httpServer.registerPathHandler(testpath, null);
|
||||
|
@ -80,9 +80,7 @@ function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
|
|||
|
||||
dump("Created test " + id + " : " + policy + "\n\n");
|
||||
|
||||
let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
principal = ssm.createCodebasePrincipal(selfuri, {});
|
||||
principal = Services.scriptSecurityManager.createCodebasePrincipal(selfuri, {});
|
||||
csp.setRequestContext(null, principal);
|
||||
|
||||
// Load up the policy
|
||||
|
@ -93,7 +91,7 @@ function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
|
|||
var handler = makeReportHandler("/test" + id, "Test " + id, expectedJSON);
|
||||
httpServer.registerPathHandler("/test" + id, handler);
|
||||
|
||||
//trigger the violation
|
||||
// trigger the violation
|
||||
callback(csp);
|
||||
}
|
||||
|
||||
|
@ -122,11 +120,11 @@ function run_test() {
|
|||
// test that eval violations cause a report.
|
||||
makeTest(1, {"blocked-uri": "eval",
|
||||
// JSON script-sample is UTF8 encoded
|
||||
"script-sample" : "\xc2\xa3\xc2\xa5\xc2\xb5\xe5\x8c\x97\xf0\xa0\x9d\xb9",
|
||||
"script-sample": "\xc2\xa3\xc2\xa5\xc2\xb5\xe5\x8c\x97\xf0\xa0\x9d\xb9",
|
||||
"line-number": 1,
|
||||
"column-number": 2}, false,
|
||||
function(csp) {
|
||||
let evalOK = true, oReportViolation = {'value': false};
|
||||
let evalOK = true, oReportViolation = {"value": false};
|
||||
evalOK = csp.getAllowsEval(oReportViolation);
|
||||
|
||||
// this is not a report only policy, so it better block eval
|
||||
|
@ -178,7 +176,7 @@ function run_test() {
|
|||
// test that eval violations cause a report in report-only policy
|
||||
makeTest(4, {"blocked-uri": "inline"}, true,
|
||||
function(csp) {
|
||||
let evalOK = true, oReportViolation = {'value': false};
|
||||
let evalOK = true, oReportViolation = {"value": false};
|
||||
evalOK = csp.getAllowsEval(oReportViolation);
|
||||
|
||||
// this is a report only policy, so it better allow eval
|
||||
|
@ -225,7 +223,6 @@ function run_test() {
|
|||
var selfSpec = REPORT_SERVER_URI + ":" + REPORT_SERVER_PORT + "/foo/self/foo.js";
|
||||
makeTest(7, {"blocked-uri": selfSpec}, false,
|
||||
function(csp) {
|
||||
var uri = NetUtil
|
||||
// shouldLoad creates and sends out the report here.
|
||||
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
|
||||
null, // nsICSPEventListener
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
ChromeUtils.import("resource://testing-common/httpd.js");
|
||||
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
||||
// Since this test creates a TYPE_DOCUMENT channel via javascript, it will
|
||||
// end up using the wrong LoadInfo constructor. Setting this pref will disable
|
||||
// the ContentPolicyType assertion in the constructor.
|
||||
prefs.setBoolPref("network.loadinfo.skip_type_assertion", true);
|
||||
Services.prefs.setBoolPref("network.loadinfo.skip_type_assertion", true);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
||||
return "http://localhost:" + httpserver.identity.primaryPort;
|
||||
|
@ -23,22 +22,22 @@ var tests = [
|
|||
{
|
||||
description: "should not set request header for TYPE_OTHER",
|
||||
expectingHeader: false,
|
||||
contentType: Ci.nsIContentPolicy.TYPE_OTHER
|
||||
contentType: Ci.nsIContentPolicy.TYPE_OTHER,
|
||||
},
|
||||
{
|
||||
description: "should set request header for TYPE_DOCUMENT",
|
||||
expectingHeader: true,
|
||||
contentType: Ci.nsIContentPolicy.TYPE_DOCUMENT
|
||||
contentType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
|
||||
},
|
||||
{
|
||||
description: "should set request header for TYPE_SUBDOCUMENT",
|
||||
expectingHeader: true,
|
||||
contentType: Ci.nsIContentPolicy.TYPE_SUBDOCUMENT
|
||||
contentType: Ci.nsIContentPolicy.TYPE_SUBDOCUMENT,
|
||||
},
|
||||
{
|
||||
description: "should not set request header for TYPE_IMG",
|
||||
expectingHeader: false,
|
||||
contentType: Ci.nsIContentPolicy.TYPE_IMG
|
||||
contentType: Ci.nsIContentPolicy.TYPE_IMG,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -46,23 +45,22 @@ function ChannelListener() {
|
|||
}
|
||||
|
||||
ChannelListener.prototype = {
|
||||
onStartRequest: function(request, context) { },
|
||||
onDataAvailable: function(request, context, stream, offset, count) {
|
||||
onStartRequest(request, context) { },
|
||||
onDataAvailable(request, context, stream, offset, count) {
|
||||
do_throw("Should not get any data!");
|
||||
},
|
||||
onStopRequest: function(request, context, status) {
|
||||
onStopRequest(request, context, status) {
|
||||
var upgrade_insecure_header = false;
|
||||
try {
|
||||
if (request.getRequestHeader("Upgrade-Insecure-Requests")) {
|
||||
upgrade_insecure_header = true;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
// exception is thrown if header is not available on the request
|
||||
}
|
||||
// debug
|
||||
// dump("executing test: " + curTest.description);
|
||||
Assert.equal(upgrade_insecure_header, curTest.expectingHeader)
|
||||
Assert.equal(upgrade_insecure_header, curTest.expectingHeader);
|
||||
run_next_test();
|
||||
},
|
||||
};
|
||||
|
@ -71,7 +69,7 @@ function setupChannel(aContentType) {
|
|||
var chan = NetUtil.newChannel({
|
||||
uri: URL + testpath,
|
||||
loadUsingSystemPrincipal: true,
|
||||
contentPolicyType: aContentType
|
||||
contentPolicyType: aContentType,
|
||||
});
|
||||
chan.QueryInterface(Ci.nsIHttpChannel);
|
||||
chan.requestMethod = "GET";
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gScriptSecurityManager",
|
||||
"@mozilla.org/scriptsecuritymanager;1",
|
||||
|
@ -17,8 +18,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gContentSecurityManager",
|
|||
"@mozilla.org/contentsecuritymanager;1",
|
||||
"nsIContentSecurityManager");
|
||||
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
prefs.setCharPref("dom.securecontext.whitelist", "example.net,example.org");
|
||||
Services.prefs.setCharPref("dom.securecontext.whitelist", "example.net,example.org");
|
||||
|
||||
add_task(async function test_isOriginPotentiallyTrustworthy() {
|
||||
for (let [uriSpec, expectedResult] of [
|
||||
|
@ -43,7 +43,7 @@ add_task(async function test_isOriginPotentiallyTrustworthy() {
|
|||
}
|
||||
// And now let's test whether .onion sites are properly treated when
|
||||
// whitelisted, see bug 1382359.
|
||||
prefs.setBoolPref("dom.securecontext.whitelist_onions", true);
|
||||
Services.prefs.setBoolPref("dom.securecontext.whitelist_onions", true);
|
||||
let uri = NetUtil.newURI("http://1234567890abcdef.onion/");
|
||||
let principal = gScriptSecurityManager.createCodebasePrincipal(uri, {});
|
||||
Assert.equal(gContentSecurityManager.isOriginPotentiallyTrustworthy(principal),
|
||||
|
|
|
@ -172,8 +172,8 @@ nsresult SVGAElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||
}
|
||||
|
||||
void SVGAElement::UnbindFromTree(bool aDeep, bool aNullParent) {
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
// Without removing the link state we risk a dangling pointer
|
||||
// in the mStyledLinks hashtable
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
|
||||
SVGAElementBase::UnbindFromTree(aDeep, aNullParent);
|
||||
|
|
|
@ -42,7 +42,7 @@ is(+contentBuildID, LEGACY_BUILD_ID,
|
|||
let chromeScript = SpecialPowers.loadChromeScript(() => {
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
addMessageListener("test:getBuildID", nav => {
|
||||
let browser = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
const browser = Services.wm.getMostRecentBrowserWindow();
|
||||
return browser.navigator.buildID;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -38,8 +38,6 @@ function startTest() {
|
|||
function testXMLDocURI(aDoc, aExpects) {
|
||||
is(aDoc.documentURI, aExpects.documentURI, "wrong url");
|
||||
is(aDoc.baseURI, aExpects.baseURI, "wrong base");
|
||||
is(aDoc.documentElement.baseURI, aExpects.elementBaseURI,
|
||||
"wrong base (xml:base)");
|
||||
}
|
||||
|
||||
function testChromeXMLDocURI(aDoc, aExpects) {
|
||||
|
@ -49,10 +47,6 @@ function testChromeXMLDocURI(aDoc, aExpects) {
|
|||
is(aDoc.baseURI, aExpects.baseURI, "wrong base");
|
||||
is(aDoc.baseURIObject.spec, aExpects.baseURI,
|
||||
"wrong base (.baseURIObject)");
|
||||
is(aDoc.documentElement.baseURI, aExpects.elementBaseURI,
|
||||
"wrong base (xml:base)");
|
||||
is(aDoc.documentElement.baseURIObject.spec, aExpects.elementBaseURI,
|
||||
"wrong base (.baseURIObject, xml:base)");
|
||||
}
|
||||
|
||||
function testHTMLDocURI(aDoc, aExpects) {
|
||||
|
@ -74,18 +68,6 @@ function testChromeHTMLDocURI(aDoc, aNonChromeBaseURI, aExpects) {
|
|||
is(aDoc.baseURIObject.spec, aExpects.baseURI,
|
||||
"wrong url (.baseURIObject)");
|
||||
|
||||
aDoc.body.setAttributeNS("http://www.w3.org/XML/1998/namespace", "base",
|
||||
aNonChromeBaseURI);
|
||||
is(aDoc.body.baseURI, aNonChromeBaseURI,
|
||||
"wrong base (doc base and xml:base are same)");
|
||||
is(aDoc.body.baseURIObject.spec, aNonChromeBaseURI,
|
||||
"wrong base (.baseURIObject, doc base and xml:base are same)")
|
||||
var attr = aDoc.getElementById("data").getAttributeNode("id");
|
||||
is(attr.baseURI, aNonChromeBaseURI,
|
||||
"wrong attr base (doc base and xml:base are same)")
|
||||
is(attr.baseURIObject.spec, aNonChromeBaseURI,
|
||||
"wrong attr base (.baseURIObject, doc base and xml:base are same)")
|
||||
|
||||
var base = aDoc.createElement("base");
|
||||
var newBaseURI = "http://www.example.com/";
|
||||
base.href = newBaseURI;
|
||||
|
@ -113,8 +95,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml"
|
||||
};
|
||||
testXMLDocURI(xhr.responseXML, expects);
|
||||
if (xhr.readyState == 4) {
|
||||
|
@ -162,8 +143,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml"
|
||||
};
|
||||
testXMLDocURI(xhr.responseXML, expects);
|
||||
if (xhr.readyState == 4) {
|
||||
|
@ -200,8 +180,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml"
|
||||
};
|
||||
testXMLDocURI(xhr.responseXML, expects);
|
||||
if (xhr.readyState == 4) {
|
||||
|
@ -252,8 +231,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml"
|
||||
};
|
||||
var xml = SpecialPowers.wrap(xhr.responseXML);
|
||||
testChromeXMLDocURI(xml, expects);
|
||||
|
@ -294,8 +272,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: document.documentURI,
|
||||
baseURI: document.baseURI,
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: document.baseURI
|
||||
};
|
||||
var xml = SpecialPowers.wrap(xhr.responseXML);
|
||||
testChromeXMLDocURI(xml, expects);
|
||||
|
@ -336,8 +313,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: document.documentURI,
|
||||
baseURI: document.baseURI,
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: document.baseURI
|
||||
};
|
||||
var xml = SpecialPowers.wrap(xhr.responseXML);
|
||||
testChromeXMLDocURI(xml, expects);
|
||||
|
@ -381,8 +357,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: "http://mochi.test:8888/tests/dom/xhr/tests/file_XHRDocURI.xml"
|
||||
};
|
||||
testXMLDocURI(xhr.responseXML, expects);
|
||||
if (xhr.readyState == 4) {
|
||||
|
@ -419,8 +394,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml"
|
||||
};
|
||||
testXMLDocURI(xhr.responseXML, expects);
|
||||
if (xhr.readyState == 4) {
|
||||
|
@ -457,8 +431,7 @@ function* runTest() {
|
|||
}
|
||||
var expects = {
|
||||
documentURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml",
|
||||
elementBaseURI: "http://www.example.com/"
|
||||
baseURI: "http://example.com/tests/dom/xhr/tests/file_XHRDocURI.xml"
|
||||
};
|
||||
testXMLDocURI(xhr.responseXML, expects);
|
||||
if (xhr.readyState == 4) {
|
||||
|
|
|
@ -191,17 +191,6 @@ nsresult txStylesheetCompiler::startElementInternal(
|
|||
}
|
||||
}
|
||||
|
||||
// xml:base
|
||||
if (attr->mNamespaceID == kNameSpaceID_XML &&
|
||||
attr->mLocalName == nsGkAtoms::base && !attr->mValue.IsEmpty()) {
|
||||
rv = ensureNewElementContext();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString uri;
|
||||
URIUtils::resolveHref(attr->mValue, mElementContext->mBaseURI, uri);
|
||||
mElementContext->mBaseURI = uri;
|
||||
}
|
||||
|
||||
// extension-element-prefixes
|
||||
if ((attr->mNamespaceID == kNameSpaceID_XSLT &&
|
||||
attr->mLocalName == nsGkAtoms::extensionElementPrefixes &&
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
|
||||
#include "AndroidNativeWindow.h"
|
||||
#include "GLContextEGL.h"
|
||||
#include "GLBlitHelper.h"
|
||||
#include "GLImages.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -28,6 +35,149 @@ void AndroidSurfaceTexture::GetTransformMatrix(
|
|||
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
|
||||
}
|
||||
|
||||
class SharedGL {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedGL);
|
||||
|
||||
SharedGL(AndroidNativeWindow& window) {
|
||||
MutexAutoLock lock(sMutex);
|
||||
|
||||
if (!sContext) {
|
||||
MOZ_ASSERT(sInstanceCount == 0);
|
||||
sContext = CreateContext();
|
||||
if (!sContext) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
InitSurface(window);
|
||||
++sInstanceCount;
|
||||
}
|
||||
|
||||
void Blit(const AndroidSurfaceTextureHandle& sourceTextureHandle,
|
||||
const gfx::IntSize& imageSize) {
|
||||
MutexAutoLock lock(sMutex);
|
||||
MOZ_ASSERT(sContext);
|
||||
|
||||
// Setting overide also makes conext and surface current.
|
||||
sContext->SetEGLSurfaceOverride(mTargetSurface);
|
||||
RefPtr<layers::SurfaceTextureImage> img = new layers::SurfaceTextureImage(
|
||||
sourceTextureHandle, imageSize, false, OriginPos::TopLeft);
|
||||
sContext->BlitHelper()->BlitImage(img, imageSize, OriginPos::BottomLeft);
|
||||
sContext->SwapBuffers();
|
||||
// This method is called through binder IPC and could run on any thread in
|
||||
// the pool. Release the context and surface from this thread after use so
|
||||
// they can be bound to another thread later.
|
||||
UnmakeCurrent(sContext);
|
||||
}
|
||||
|
||||
private:
|
||||
~SharedGL() {
|
||||
MutexAutoLock lock(sMutex);
|
||||
|
||||
if (mTargetSurface != EGL_NO_SURFACE) {
|
||||
GLLibraryEGL::Get()->fDestroySurface(EGL_DISPLAY(), mTargetSurface);
|
||||
}
|
||||
|
||||
// Destroy shared GL context when no one uses it.
|
||||
if (--sInstanceCount == 0) {
|
||||
sContext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static already_AddRefed<GLContextEGL> CreateContext() {
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(!sContext);
|
||||
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
EGLDisplay eglDisplay = egl->fGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
EGLConfig eglConfig;
|
||||
CreateConfig(&eglConfig, /* bpp */ 24, /* depth buffer? */ false);
|
||||
EGLint attributes[] = {LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2, LOCAL_EGL_NONE};
|
||||
EGLContext eglContext =
|
||||
egl->fCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attributes);
|
||||
RefPtr<GLContextEGL> gl = new GLContextEGL(
|
||||
CreateContextFlags::NONE, SurfaceCaps::Any(),
|
||||
/* offscreen? */ false, eglConfig, EGL_NO_SURFACE, eglContext);
|
||||
if (!gl->Init()) {
|
||||
NS_WARNING("Fail to create GL context for native blitter.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Yield the current state made in constructor.
|
||||
UnmakeCurrent(gl);
|
||||
return gl.forget();
|
||||
}
|
||||
|
||||
void InitSurface(AndroidNativeWindow& window) {
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(sContext);
|
||||
|
||||
mTargetSurface = gl::GLLibraryEGL::Get()->fCreateWindowSurface(
|
||||
sContext->GetEGLDisplay(), sContext->mConfig, window.NativeWindow(), 0);
|
||||
}
|
||||
|
||||
static bool UnmakeCurrent(RefPtr<GLContextEGL>& gl) {
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(gl);
|
||||
|
||||
if (!gl->IsCurrent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return gl::GLLibraryEGL::Get()->fMakeCurrent(
|
||||
EGL_DISPLAY(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
static Mutex sMutex;
|
||||
static RefPtr<GLContextEGL> sContext;
|
||||
static size_t sInstanceCount;
|
||||
|
||||
EGLSurface mTargetSurface;
|
||||
};
|
||||
|
||||
Mutex SharedGL::sMutex("SharedGLContext::sMutex");
|
||||
RefPtr<GLContextEGL> SharedGL::sContext(nullptr);
|
||||
size_t SharedGL::sInstanceCount = 0;
|
||||
|
||||
class GLBlitterSupport final
|
||||
: public java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<
|
||||
GLBlitterSupport> {
|
||||
public:
|
||||
using Base =
|
||||
java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<GLBlitterSupport>;
|
||||
using Base::AttachNative;
|
||||
using Base::DisposeNative;
|
||||
using Base::GetNative;
|
||||
|
||||
static java::GeckoSurfaceTexture::NativeGLBlitHelper::LocalRef Create(
|
||||
jint sourceTextureHandle, jni::Object::Param targetSurface, jint width,
|
||||
jint height) {
|
||||
AndroidNativeWindow win(java::GeckoSurface::Ref::From(targetSurface));
|
||||
auto helper = java::GeckoSurfaceTexture::NativeGLBlitHelper::New();
|
||||
RefPtr<SharedGL> gl = new SharedGL(win);
|
||||
GLBlitterSupport::AttachNative(
|
||||
helper, MakeUnique<GLBlitterSupport>(std::move(gl), sourceTextureHandle,
|
||||
width, height));
|
||||
return helper;
|
||||
}
|
||||
|
||||
GLBlitterSupport(RefPtr<SharedGL>&& gl, jint sourceTextureHandle, jint width,
|
||||
jint height)
|
||||
: mGl(gl),
|
||||
mSourceTextureHandle(sourceTextureHandle),
|
||||
mSize(width, height) {}
|
||||
|
||||
void Blit() { mGl->Blit(mSourceTextureHandle, mSize); }
|
||||
|
||||
private:
|
||||
const RefPtr<SharedGL> mGl;
|
||||
const AndroidSurfaceTextureHandle mSourceTextureHandle;
|
||||
const gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
void AndroidSurfaceTexture::Init() { GLBlitterSupport::Init(); }
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace gl {
|
|||
|
||||
class AndroidSurfaceTexture {
|
||||
public:
|
||||
static void Init();
|
||||
static void GetTransformMatrix(
|
||||
java::sdk::SurfaceTexture::Param surfaceTexture,
|
||||
mozilla::gfx::Matrix4x4* outMatrix);
|
||||
|
|
|
@ -422,7 +422,6 @@ bool ClipManager::ItemClips::HasSameInputs(const ItemClips& aOther) {
|
|||
void ClipManager::ItemClips::CopyOutputsFrom(const ItemClips& aOther) {
|
||||
mScrollId = aOther.mScrollId;
|
||||
mClipChainId = aOther.mClipChainId;
|
||||
mSeparateLeaf = aOther.mSeparateLeaf;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -1 +1 @@
|
|||
fab59ceef070c11aba2a86c4ddf6ddc3c4e8f97d
|
||||
3a4ce4b66a7bc9bd10773744d20530c609a61e90
|
||||
|
|
|
@ -450,7 +450,7 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1229,12 +1229,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "servo-freetype-sys"
|
||||
version = "4.0.3"
|
||||
version = "4.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1901,7 +1901,7 @@ dependencies = [
|
|||
"checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1"
|
||||
"checksum servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9"
|
||||
"checksum servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "38b494f03009ee81914b0e7d387ad7c145cafcd69747c2ec89b0e17bb94f303a"
|
||||
"checksum servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b"
|
||||
"checksum servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4ccb6d0d32d277d3ef7dea86203d8210945eb7a45fba89dd445b3595dd0dfc"
|
||||
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
|
||||
"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
|
||||
"checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
before_test:
|
||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/set-screenresolution.ps1'))
|
||||
- ps: iex (Get-Content -Raw ci-scripts\set-screenresolution.ps1)
|
||||
- ps: Set-ScreenResolution 1920 1080
|
||||
|
||||
environment:
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
# http://blogs.technet.com/b/heyscriptingguy/archive/2010/07/07/hey-scripting-guy-how-can-i-change-my-desktop-monitor-resolution-via-windows-powershell.aspx
|
||||
|
||||
Function Set-ScreenResolution {
|
||||
param (
|
||||
[Parameter(Mandatory=$true,
|
||||
Position = 0)]
|
||||
[int]
|
||||
$Width,
|
||||
[Parameter(Mandatory=$true,
|
||||
Position = 1)]
|
||||
[int]
|
||||
$Height
|
||||
)
|
||||
$pinvokeCode = @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace Resolution
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DEVMODE1
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string dmDeviceName;
|
||||
public short dmSpecVersion;
|
||||
public short dmDriverVersion;
|
||||
public short dmSize;
|
||||
public short dmDriverExtra;
|
||||
public int dmFields;
|
||||
public short dmOrientation;
|
||||
public short dmPaperSize;
|
||||
public short dmPaperLength;
|
||||
public short dmPaperWidth;
|
||||
public short dmScale;
|
||||
public short dmCopies;
|
||||
public short dmDefaultSource;
|
||||
public short dmPrintQuality;
|
||||
public short dmColor;
|
||||
public short dmDuplex;
|
||||
public short dmYResolution;
|
||||
public short dmTTOption;
|
||||
public short dmCollate;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string dmFormName;
|
||||
public short dmLogPixels;
|
||||
public short dmBitsPerPel;
|
||||
public int dmPelsWidth;
|
||||
public int dmPelsHeight;
|
||||
public int dmDisplayFlags;
|
||||
public int dmDisplayFrequency;
|
||||
public int dmICMMethod;
|
||||
public int dmICMIntent;
|
||||
public int dmMediaType;
|
||||
public int dmDitherType;
|
||||
public int dmReserved1;
|
||||
public int dmReserved2;
|
||||
public int dmPanningWidth;
|
||||
public int dmPanningHeight;
|
||||
};
|
||||
class User_32
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE1 devMode);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int ChangeDisplaySettings(ref DEVMODE1 devMode, int flags);
|
||||
public const int ENUM_CURRENT_SETTINGS = -1;
|
||||
public const int CDS_UPDATEREGISTRY = 0x01;
|
||||
public const int CDS_TEST = 0x02;
|
||||
public const int DISP_CHANGE_SUCCESSFUL = 0;
|
||||
public const int DISP_CHANGE_RESTART = 1;
|
||||
public const int DISP_CHANGE_FAILED = -1;
|
||||
}
|
||||
public class PrmaryScreenResolution
|
||||
{
|
||||
static public string ChangeResolution(int width, int height)
|
||||
{
|
||||
DEVMODE1 dm = GetDevMode1();
|
||||
if (0 != User_32.EnumDisplaySettings(null, User_32.ENUM_CURRENT_SETTINGS, ref dm))
|
||||
{
|
||||
dm.dmPelsWidth = width;
|
||||
dm.dmPelsHeight = height;
|
||||
int iRet = User_32.ChangeDisplaySettings(ref dm, User_32.CDS_TEST);
|
||||
if (iRet == User_32.DISP_CHANGE_FAILED)
|
||||
{
|
||||
return "Unable To Process Your Request. Sorry For This Inconvenience.";
|
||||
}
|
||||
else
|
||||
{
|
||||
iRet = User_32.ChangeDisplaySettings(ref dm, User_32.CDS_UPDATEREGISTRY);
|
||||
switch (iRet)
|
||||
{
|
||||
case User_32.DISP_CHANGE_SUCCESSFUL:
|
||||
{
|
||||
return "Success";
|
||||
}
|
||||
case User_32.DISP_CHANGE_RESTART:
|
||||
{
|
||||
return "You Need To Reboot For The Change To Happen.\n If You Feel Any Problem After Rebooting Your Machine\nThen Try To Change Resolution In Safe Mode.";
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "Failed To Change The Resolution";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Failed To Change The Resolution.";
|
||||
}
|
||||
}
|
||||
private static DEVMODE1 GetDevMode1()
|
||||
{
|
||||
DEVMODE1 dm = new DEVMODE1();
|
||||
dm.dmDeviceName = new String(new char[32]);
|
||||
dm.dmFormName = new String(new char[32]);
|
||||
dm.dmSize = (short)Marshal.SizeOf(dm);
|
||||
return dm;
|
||||
}
|
||||
}
|
||||
}
|
||||
"@
|
||||
Add-Type $pinvokeCode -ErrorAction SilentlyContinue
|
||||
[Resolution.PrmaryScreenResolution]::ChangeResolution($width,$height)
|
||||
}
|
|
@ -10,36 +10,26 @@
|
|||
// for the various YUV modes. To save on the number of shaders we
|
||||
// need to compile, it might be worth just doing this as an
|
||||
// uber-shader instead.
|
||||
// TODO(gw): Regardless of the above, we should remove the separate shader
|
||||
// compilations for the different color space matrix below. That
|
||||
// can be provided by a branch in the VS and pushed through the
|
||||
// interpolators, or even as a uniform that breaks batches, rather
|
||||
// that needing to compile to / select a different shader when
|
||||
// there is a different color space.
|
||||
|
||||
#define YUV_COLOR_SPACE_REC601 0
|
||||
#define YUV_COLOR_SPACE_REC709 1
|
||||
|
||||
#define YUV_FORMAT_NV12 0
|
||||
#define YUV_FORMAT_PLANAR 1
|
||||
#define YUV_FORMAT_INTERLEAVED 2
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
varying vec2 vLocalPos;
|
||||
#endif
|
||||
|
||||
#if defined (WR_FEATURE_YUV_PLANAR)
|
||||
varying vec3 vUv_Y;
|
||||
flat varying vec4 vUvBounds_Y;
|
||||
varying vec3 vUv_Y;
|
||||
flat varying vec4 vUvBounds_Y;
|
||||
|
||||
varying vec3 vUv_U;
|
||||
flat varying vec4 vUvBounds_U;
|
||||
varying vec3 vUv_U;
|
||||
flat varying vec4 vUvBounds_U;
|
||||
|
||||
varying vec3 vUv_V;
|
||||
flat varying vec4 vUvBounds_V;
|
||||
#elif defined (WR_FEATURE_YUV_NV12)
|
||||
varying vec3 vUv_Y;
|
||||
flat varying vec4 vUvBounds_Y;
|
||||
|
||||
varying vec3 vUv_UV;
|
||||
flat varying vec4 vUvBounds_UV;
|
||||
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
||||
varying vec3 vUv_YUV;
|
||||
flat varying vec4 vUvBounds_YUV;
|
||||
#endif
|
||||
varying vec3 vUv_V;
|
||||
flat varying vec4 vUvBounds_V;
|
||||
|
||||
#ifdef WR_FEATURE_TEXTURE_RECT
|
||||
#define TEX_SIZE(sampler) vec2(1.0)
|
||||
|
@ -48,8 +38,40 @@ varying vec2 vLocalPos;
|
|||
#endif
|
||||
|
||||
flat varying float vCoefficient;
|
||||
flat varying mat3 vYuvColorMatrix;
|
||||
flat varying int vFormat;
|
||||
|
||||
#ifdef WR_VERTEX_SHADER
|
||||
// The constants added to the Y, U and V components are applied in the fragment shader.
|
||||
|
||||
// From Rec601:
|
||||
// [R] [1.1643835616438356, 0.0, 1.5960267857142858 ] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255].
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrixRec601 = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0, -0.39176, 2.01723,
|
||||
1.59603, -0.81297, 0.0
|
||||
);
|
||||
|
||||
// From Rec709:
|
||||
// [R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.1124017857142854, 0.0 ] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255]:
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrixRec709 = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0 , -0.21325, 2.11240,
|
||||
1.79274, -0.53291, 0.0
|
||||
);
|
||||
|
||||
void write_uv_rect(
|
||||
int resource_id,
|
||||
vec2 f,
|
||||
|
@ -74,11 +96,13 @@ void write_uv_rect(
|
|||
|
||||
struct YuvPrimitive {
|
||||
float coefficient;
|
||||
int color_space;
|
||||
int yuv_format;
|
||||
};
|
||||
|
||||
YuvPrimitive fetch_yuv_primitive(int address) {
|
||||
vec4 data = fetch_from_gpu_cache_1(address);
|
||||
return YuvPrimitive(data.x);
|
||||
return YuvPrimitive(data.x, int(data.y), int(data.z));
|
||||
}
|
||||
|
||||
void brush_vs(
|
||||
|
@ -97,88 +121,60 @@ void brush_vs(
|
|||
YuvPrimitive prim = fetch_yuv_primitive(prim_address);
|
||||
vCoefficient = prim.coefficient;
|
||||
|
||||
if (prim.color_space == YUV_COLOR_SPACE_REC601) {
|
||||
vYuvColorMatrix = YuvColorMatrixRec601;
|
||||
} else {
|
||||
vYuvColorMatrix = YuvColorMatrixRec709;
|
||||
}
|
||||
vFormat = prim.yuv_format;
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
vLocalPos = vi.local_pos;
|
||||
#endif
|
||||
|
||||
#if defined (WR_FEATURE_YUV_PLANAR)
|
||||
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
|
||||
write_uv_rect(user_data.z, f, TEX_SIZE(sColor2), vUv_V, vUvBounds_V);
|
||||
#elif defined (WR_FEATURE_YUV_NV12)
|
||||
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_UV, vUvBounds_UV);
|
||||
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
||||
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_YUV, vUvBounds_YUV);
|
||||
#endif //WR_FEATURE_YUV_*
|
||||
if (vFormat == YUV_FORMAT_PLANAR) {
|
||||
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
|
||||
write_uv_rect(user_data.z, f, TEX_SIZE(sColor2), vUv_V, vUvBounds_V);
|
||||
} else if (vFormat == YUV_FORMAT_NV12) {
|
||||
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||
write_uv_rect(user_data.y, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
|
||||
} else if (vFormat == YUV_FORMAT_INTERLEAVED) {
|
||||
write_uv_rect(user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WR_FRAGMENT_SHADER
|
||||
|
||||
#if !defined(WR_FEATURE_YUV_REC601) && !defined(WR_FEATURE_YUV_REC709)
|
||||
#define WR_FEATURE_YUV_REC601
|
||||
#endif
|
||||
|
||||
// The constants added to the Y, U and V components are applied in the fragment shader.
|
||||
#if defined(WR_FEATURE_YUV_REC601)
|
||||
// From Rec601:
|
||||
// [R] [1.1643835616438356, 0.0, 1.5960267857142858 ] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255].
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrix = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0, -0.39176, 2.01723,
|
||||
1.59603, -0.81297, 0.0
|
||||
);
|
||||
#elif defined(WR_FEATURE_YUV_REC709)
|
||||
// From Rec709:
|
||||
// [R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [Y - 16]
|
||||
// [G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444 ] x [U - 128]
|
||||
// [B] [1.1643835616438356, 2.1124017857142854, 0.0 ] [V - 128]
|
||||
//
|
||||
// For the range [0,1] instead of [0,255]:
|
||||
//
|
||||
// The matrix is stored in column-major.
|
||||
const mat3 YuvColorMatrix = mat3(
|
||||
1.16438, 1.16438, 1.16438,
|
||||
0.0 , -0.21325, 2.11240,
|
||||
1.79274, -0.53291, 0.0
|
||||
);
|
||||
#endif
|
||||
|
||||
Fragment brush_fs() {
|
||||
vec3 yuv_value;
|
||||
|
||||
#if defined (WR_FEATURE_YUV_PLANAR)
|
||||
// The yuv_planar format should have this third texture coordinate.
|
||||
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
|
||||
vec2 uv_u = clamp(vUv_U.xy, vUvBounds_U.xy, vUvBounds_U.zw);
|
||||
vec2 uv_v = clamp(vUv_V.xy, vUvBounds_V.xy, vUvBounds_V.zw);
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
|
||||
yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, vUv_U.z)).r;
|
||||
yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, vUv_V.z)).r;
|
||||
#elif defined (WR_FEATURE_YUV_NV12)
|
||||
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
|
||||
vec2 uv_uv = clamp(vUv_UV.xy, vUvBounds_UV.xy, vUvBounds_UV.zw);
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
|
||||
yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, vUv_UV.z)).rg;
|
||||
#elif defined (WR_FEATURE_YUV_INTERLEAVED)
|
||||
// "The Y, Cb and Cr color channels within the 422 data are mapped into
|
||||
// the existing green, blue and red color channels."
|
||||
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
|
||||
vec2 uv_y = clamp(vUv_YUV.xy, vUvBounds_YUV.xy, vUvBounds_YUV.zw);
|
||||
yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_YUV.z)).gbr;
|
||||
#else
|
||||
yuv_value = vec3(0.0);
|
||||
#endif
|
||||
if (vFormat == YUV_FORMAT_PLANAR) {
|
||||
// The yuv_planar format should have this third texture coordinate.
|
||||
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
|
||||
vec2 uv_u = clamp(vUv_U.xy, vUvBounds_U.xy, vUvBounds_U.zw);
|
||||
vec2 uv_v = clamp(vUv_V.xy, vUvBounds_V.xy, vUvBounds_V.zw);
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
|
||||
yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, vUv_U.z)).r;
|
||||
yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, vUv_V.z)).r;
|
||||
} else if (vFormat == YUV_FORMAT_NV12) {
|
||||
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
|
||||
vec2 uv_uv = clamp(vUv_U.xy, vUvBounds_U.xy, vUvBounds_U.zw);
|
||||
yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
|
||||
yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, vUv_U.z)).rg;
|
||||
} else if (vFormat == YUV_FORMAT_INTERLEAVED) {
|
||||
// "The Y, Cb and Cr color channels within the 422 data are mapped into
|
||||
// the existing green, blue and red color channels."
|
||||
// https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
|
||||
vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
|
||||
yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).gbr;
|
||||
} else {
|
||||
yuv_value = vec3(0.0);
|
||||
}
|
||||
|
||||
// See the YuvColorMatrix definition for an explanation of where the constants come from.
|
||||
vec3 rgb = YuvColorMatrix * (yuv_value * vCoefficient - vec3(0.06275, 0.50196, 0.50196));
|
||||
vec3 rgb = vYuvColorMatrix * (yuv_value * vCoefficient - vec3(0.06275, 0.50196, 0.50196));
|
||||
vec4 color = vec4(rgb, 1.0);
|
||||
|
||||
#ifdef WR_FEATURE_ALPHA_PASS
|
||||
|
|
|
@ -1155,12 +1155,10 @@ impl AlphaBatchBuilder {
|
|||
get_shader_opacity(1.0),
|
||||
]);
|
||||
|
||||
let shadow_rect = picture.local_rect.translate(&offset);
|
||||
let shadow_clip_rect = picture.local_clip_rect.translate(&offset);
|
||||
let shadow_rect = prim_header.local_rect.translate(&offset);
|
||||
|
||||
let shadow_prim_header = PrimitiveHeader {
|
||||
local_rect: shadow_rect,
|
||||
local_clip_rect: shadow_clip_rect,
|
||||
specific_prim_address: shadow_prim_address,
|
||||
..prim_header
|
||||
};
|
||||
|
|
|
@ -527,7 +527,7 @@ impl ClipStore {
|
|||
resource_cache: &mut ResourceCache,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
world_rect: &WorldRect,
|
||||
clip_node_collector: &Option<ClipNodeCollector>,
|
||||
clip_node_collector: Option<&ClipNodeCollector>,
|
||||
clip_data_store: &mut ClipDataStore,
|
||||
) -> Option<ClipChainInstance> {
|
||||
let mut local_clip_rect = local_prim_clip_rect;
|
||||
|
@ -898,6 +898,8 @@ impl ClipItemKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl intern::InternDebug for ClipItemKey {}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
|
|
@ -184,8 +184,8 @@ fn get_shader_version(gl: &gl::Gl) -> &'static str {
|
|||
|
||||
// Get a shader string by name, from the built in resources or
|
||||
// an override path, if supplied.
|
||||
fn get_shader_source(shader_name: &str, base_path: &Option<PathBuf>) -> Option<Cow<'static, str>> {
|
||||
if let Some(ref base) = *base_path {
|
||||
fn get_shader_source(shader_name: &str, base_path: Option<&PathBuf>) -> Option<Cow<'static, str>> {
|
||||
if let Some(ref base) = base_path {
|
||||
let shader_path = base.join(&format!("{}.glsl", shader_name));
|
||||
if shader_path.exists() {
|
||||
let mut source = String::new();
|
||||
|
@ -204,7 +204,7 @@ fn get_shader_source(shader_name: &str, base_path: &Option<PathBuf>) -> Option<C
|
|||
|
||||
// Parse a shader string for imports. Imports are recursively processed, and
|
||||
// prepended to the output stream.
|
||||
fn parse_shader_source<F: FnMut(&str)>(source: Cow<'static, str>, base_path: &Option<PathBuf>, output: &mut F) {
|
||||
fn parse_shader_source<F: FnMut(&str)>(source: Cow<'static, str>, base_path: Option<&PathBuf>, output: &mut F) {
|
||||
for line in source.lines() {
|
||||
if line.starts_with(SHADER_IMPORT) {
|
||||
let imports = line[SHADER_IMPORT.len() ..].split(',');
|
||||
|
@ -228,7 +228,7 @@ pub fn build_shader_strings(
|
|||
gl_version_string: &str,
|
||||
features: &str,
|
||||
base_filename: &str,
|
||||
override_path: &Option<PathBuf>,
|
||||
override_path: Option<&PathBuf>,
|
||||
) -> (String, String) {
|
||||
let mut vs_source = String::new();
|
||||
do_build_shader_string(
|
||||
|
@ -261,7 +261,7 @@ fn do_build_shader_string<F: FnMut(&str)>(
|
|||
features: &str,
|
||||
kind: &str,
|
||||
base_filename: &str,
|
||||
override_path: &Option<PathBuf>,
|
||||
override_path: Option<&PathBuf>,
|
||||
mut output: F,
|
||||
) {
|
||||
// GLSL requires that the version number comes first.
|
||||
|
@ -2052,7 +2052,7 @@ impl Device {
|
|||
features,
|
||||
kind,
|
||||
base_filename,
|
||||
&self.resource_override_path,
|
||||
self.resource_override_path.as_ref(),
|
||||
output,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use frame_builder::{ChasePrimitive, FrameBuilder, FrameBuilderConfig};
|
|||
use glyph_rasterizer::FontInstance;
|
||||
use hit_test::{HitTestingItem, HitTestingRun};
|
||||
use image::simplify_repeated_primitive;
|
||||
use intern::{Handle, Internable};
|
||||
use intern::{Handle, Internable, InternDebug};
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PrimitiveList};
|
||||
use prim_store::{PrimitiveInstance, PrimitiveKeyKind};
|
||||
|
@ -273,7 +273,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
main_scroll_root = Some(scroll_root);
|
||||
true
|
||||
}
|
||||
}).unwrap_or(primitives.len());
|
||||
});
|
||||
|
||||
let main_scroll_root = match main_scroll_root {
|
||||
Some(main_scroll_root) => main_scroll_root,
|
||||
|
@ -286,20 +286,38 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
Vec::new(),
|
||||
);
|
||||
|
||||
// Split off the preceding primtives.
|
||||
let mut remaining_prims = old_prim_list.split_off(first_index);
|
||||
// In the simple case, there are no preceding or trailing primitives,
|
||||
// because everything is anchored to the root scroll node. Handle
|
||||
// this case specially to avoid underflow error in the Some(..)
|
||||
// path below.
|
||||
|
||||
// Find the first primitive in reverse order that is not the root scroll node.
|
||||
let last_index = remaining_prims.iter().rposition(|instance| {
|
||||
let scroll_root = self.find_scroll_root(
|
||||
instance.spatial_node_index,
|
||||
);
|
||||
let preceding_prims;
|
||||
let mut remaining_prims;
|
||||
let trailing_prims;
|
||||
|
||||
scroll_root != ROOT_SPATIAL_NODE_INDEX
|
||||
}).unwrap_or(remaining_prims.len() - 1);
|
||||
match first_index {
|
||||
Some(first_index) => {
|
||||
// Split off the preceding primtives.
|
||||
remaining_prims = old_prim_list.split_off(first_index);
|
||||
|
||||
let preceding_prims = old_prim_list;
|
||||
let trailing_prims = remaining_prims.split_off(last_index + 1);
|
||||
// Find the first primitive in reverse order that is not the root scroll node.
|
||||
let last_index = remaining_prims.iter().rposition(|instance| {
|
||||
let scroll_root = self.find_scroll_root(
|
||||
instance.spatial_node_index,
|
||||
);
|
||||
|
||||
scroll_root != ROOT_SPATIAL_NODE_INDEX
|
||||
}).unwrap_or(remaining_prims.len() - 1);
|
||||
|
||||
preceding_prims = old_prim_list;
|
||||
trailing_prims = remaining_prims.split_off(last_index + 1);
|
||||
}
|
||||
None => {
|
||||
preceding_prims = Vec::new();
|
||||
remaining_prims = old_prim_list;
|
||||
trailing_prims = Vec::new();
|
||||
}
|
||||
}
|
||||
|
||||
let prim_list = PrimitiveList::new(
|
||||
remaining_prims,
|
||||
|
@ -1027,7 +1045,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
) -> PrimitiveInstance
|
||||
where
|
||||
P: Internable<InternData=PrimitiveSceneData>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
{
|
||||
let offset = info.rect.origin.to_vector();
|
||||
|
@ -1107,7 +1125,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
)
|
||||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
{
|
||||
if prim.is_visible() {
|
||||
|
@ -1134,7 +1152,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
)
|
||||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
ShadowItem: From<PendingPrimitive<P>>
|
||||
{
|
||||
|
@ -1164,7 +1182,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
)
|
||||
where
|
||||
P: Internable<InternData = PrimitiveSceneData>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
{
|
||||
let prim_instance = self.create_primitive(
|
||||
|
@ -1899,7 +1917,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
)
|
||||
where
|
||||
P: Internable<InternData=PrimitiveSceneData> + CreateShadow,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
{
|
||||
// Offset the local rect and clip rect by the shadow offset.
|
||||
|
@ -1924,7 +1942,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
fn add_shadow_prim_to_draw_list<P>(&mut self, pending_primitive: PendingPrimitive<P>)
|
||||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
{
|
||||
// For a normal primitive, if it has alpha > 0, then we add this
|
||||
|
@ -2558,7 +2576,7 @@ impl FlattenedStackingContext {
|
|||
return false;
|
||||
}
|
||||
|
||||
// If different clipp chains
|
||||
// If different clip chains
|
||||
if self.clip_chain_id != parent.clip_chain_id {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -490,8 +490,9 @@ impl FrameBuilder {
|
|||
&mut z_generator,
|
||||
);
|
||||
|
||||
if let RenderPassKind::OffScreen { ref texture_cache, .. } = pass.kind {
|
||||
if let RenderPassKind::OffScreen { ref texture_cache, ref color, .. } = pass.kind {
|
||||
has_texture_cache_tasks |= !texture_cache.is_empty();
|
||||
has_texture_cache_tasks |= color.must_be_drawn();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -352,11 +352,10 @@ impl SubpixelOffset {
|
|||
let apos = ((pos - pos.floor()) * 8.0) as i32;
|
||||
|
||||
match apos {
|
||||
0 | 7 => SubpixelOffset::Zero,
|
||||
1...2 => SubpixelOffset::Quarter,
|
||||
3...4 => SubpixelOffset::Half,
|
||||
5...6 => SubpixelOffset::ThreeQuarters,
|
||||
_ => unreachable!("bug: unexpected quantized result"),
|
||||
_ => SubpixelOffset::Zero,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,6 +126,10 @@ struct Item<T> {
|
|||
data: T,
|
||||
}
|
||||
|
||||
pub trait InternDebug {
|
||||
fn on_interned(&self, _uid: ItemUid) {}
|
||||
}
|
||||
|
||||
/// The data store lives in the frame builder thread. It
|
||||
/// contains a free-list of items for fast access.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -252,7 +256,7 @@ where
|
|||
|
||||
impl<S, D, M> Interner<S, D, M>
|
||||
where
|
||||
S: Eq + Hash + Clone + Debug,
|
||||
S: Eq + Hash + Clone + Debug + InternDebug,
|
||||
M: Copy + Debug
|
||||
{
|
||||
/// Intern a data structure, and return a handle to
|
||||
|
@ -309,6 +313,9 @@ where
|
|||
_marker: PhantomData,
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
data.on_interned(handle.uid);
|
||||
|
||||
// Store this handle so the next time it is
|
||||
// interned, it gets re-used.
|
||||
self.map.insert(data.clone(), handle);
|
||||
|
|
|
@ -22,6 +22,7 @@ use plane_split::{Clipper, Polygon, Splitter};
|
|||
use prim_store::{PictureIndex, PrimitiveInstance, SpaceMapper, VisibleFace, PrimitiveInstanceKind};
|
||||
use prim_store::{get_raster_rects, CoordinateSpaceMapping, PointKey};
|
||||
use prim_store::{OpacityBindingStorage, PrimitiveTemplateKind, ImageInstanceStorage, OpacityBindingIndex, SizeKey};
|
||||
use print_tree::PrintTreePrinter;
|
||||
use render_backend::FrameResources;
|
||||
use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle, TileBlit};
|
||||
use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
|
||||
|
@ -81,6 +82,9 @@ pub type TileRect = TypedRect<i32, TileCoordinate>;
|
|||
pub const TILE_SIZE_WIDTH: i32 = 1024;
|
||||
pub const TILE_SIZE_HEIGHT: i32 = 256;
|
||||
|
||||
/// The maximum size of a picture before we disable tile caching.
|
||||
const MAX_PICTURE_SIZE: f32 = 65536.0;
|
||||
|
||||
/// Information about the state of a transform dependency.
|
||||
#[derive(Debug)]
|
||||
pub struct TileTransformInfo {
|
||||
|
@ -407,6 +411,13 @@ impl TileCache {
|
|||
frame_context: &FrameBuildingContext,
|
||||
pic_rect: LayoutRect,
|
||||
) {
|
||||
// If we previously disabled the tile cache due to an invalid
|
||||
// picture rect, and then we re-enable it, force an update
|
||||
// of all primitive dependencies.
|
||||
if self.tile_rect.size.is_empty_or_negative() {
|
||||
self.needs_update = true;
|
||||
}
|
||||
|
||||
// Initialize the space mapper with current bounds,
|
||||
// which is used during primitive dependency updates.
|
||||
let world_mapper = SpaceMapper::new_with_target(
|
||||
|
@ -674,6 +685,7 @@ impl TileCache {
|
|||
pub fn update_prim_dependencies(
|
||||
&mut self,
|
||||
prim_instance: &PrimitiveInstance,
|
||||
prim_list: &PrimitiveList,
|
||||
surface_spatial_node_index: SpatialNodeIndex,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
resources: &FrameResources,
|
||||
|
@ -687,6 +699,32 @@ impl TileCache {
|
|||
return;
|
||||
}
|
||||
|
||||
// We need to ensure that if a primitive belongs to a cluster that has
|
||||
// been marked invisible, we exclude it here. Otherwise, we may end up
|
||||
// with a primitive that is outside the bounding rect of the calculated
|
||||
// picture rect (which takes the cluster visibility into account).
|
||||
// TODO(gw): It turns out that we have ended up having only a single
|
||||
// cluster per primitive rather than a range. In future,
|
||||
// we should tidy this up to take advantage of this!
|
||||
let mut in_visible_cluster = false;
|
||||
for ci in prim_instance.cluster_range.start .. prim_instance.cluster_range.end {
|
||||
// Map from the cluster range index to a cluster index
|
||||
let cluster_index = prim_list.prim_cluster_map[ci as usize];
|
||||
|
||||
// Get the cluster and see if is visible
|
||||
let cluster = &prim_list.clusters[cluster_index.0 as usize];
|
||||
in_visible_cluster |= cluster.is_visible;
|
||||
|
||||
// As soon as a primitive is in a visible cluster, it's considered
|
||||
// visible and we don't need to consult other clusters.
|
||||
if cluster.is_visible {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !in_visible_cluster {
|
||||
return;
|
||||
}
|
||||
|
||||
self.space_mapper.set_target_spatial_node(
|
||||
prim_instance.spatial_node_index,
|
||||
clip_scroll_tree,
|
||||
|
@ -694,13 +732,23 @@ impl TileCache {
|
|||
|
||||
let prim_data = &resources.as_common_data(&prim_instance);
|
||||
|
||||
let prim_rect = LayoutRect::new(
|
||||
prim_instance.prim_origin,
|
||||
prim_data.prim_size,
|
||||
);
|
||||
let clip_rect = prim_data
|
||||
.prim_relative_clip_rect
|
||||
.translate(&prim_instance.prim_origin.to_vector());
|
||||
let (prim_rect, clip_rect) = match prim_instance.kind {
|
||||
PrimitiveInstanceKind::Picture { pic_index, .. } => {
|
||||
let pic = &pictures[pic_index.0];
|
||||
(pic.local_rect, LayoutRect::max_rect())
|
||||
}
|
||||
_ => {
|
||||
let prim_rect = LayoutRect::new(
|
||||
prim_instance.prim_origin,
|
||||
prim_data.prim_size,
|
||||
);
|
||||
let clip_rect = prim_data
|
||||
.prim_relative_clip_rect
|
||||
.translate(&prim_instance.prim_origin.to_vector());
|
||||
|
||||
(prim_rect, clip_rect)
|
||||
}
|
||||
};
|
||||
|
||||
// Map the primitive local rect into the picture space.
|
||||
// TODO(gw): We should maybe store this in the primitive template
|
||||
|
@ -812,7 +860,7 @@ impl TileCache {
|
|||
// We only care about clip nodes that have transforms that are children
|
||||
// of the surface, since clips that are positioned by parents will be
|
||||
// handled by the clip collector when these tiles are composited.
|
||||
if clip_chain_node.spatial_node_index > surface_spatial_node_index {
|
||||
if clip_chain_node.spatial_node_index >= surface_spatial_node_index {
|
||||
clip_chain_spatial_nodes.push(clip_chain_node.spatial_node_index);
|
||||
clip_chain_uids.push(clip_chain_node.handle.uid());
|
||||
}
|
||||
|
@ -1502,6 +1550,29 @@ pub struct PicturePrimitive {
|
|||
}
|
||||
|
||||
impl PicturePrimitive {
|
||||
pub fn print<T: PrintTreePrinter>(
|
||||
&self,
|
||||
pictures: &[Self],
|
||||
self_index: PictureIndex,
|
||||
pt: &mut T,
|
||||
) {
|
||||
pt.new_level(format!("{:?}", self_index));
|
||||
pt.add_item(format!("prim_count: {:?}", self.prim_list.prim_instances.len()));
|
||||
pt.add_item(format!("local_rect: {:?}", self.local_rect));
|
||||
if self.apply_local_clip_rect {
|
||||
pt.add_item(format!("local_clip_rect: {:?}", self.local_clip_rect));
|
||||
}
|
||||
pt.add_item(format!("spatial_node_index: {:?}", self.spatial_node_index));
|
||||
pt.add_item(format!("raster_config: {:?}", self.raster_config));
|
||||
pt.add_item(format!("requested_composite_mode: {:?}", self.requested_composite_mode));
|
||||
|
||||
for index in &self.prim_list.pictures {
|
||||
pictures[index.0].print(pictures, *index, pt);
|
||||
}
|
||||
|
||||
pt.end_level();
|
||||
}
|
||||
|
||||
fn resolve_scene_properties(&mut self, properties: &SceneProperties) -> bool {
|
||||
match self.requested_composite_mode {
|
||||
Some(PictureCompositeMode::Filter(ref mut filter)) => {
|
||||
|
@ -1993,6 +2064,7 @@ impl PicturePrimitive {
|
|||
for prim_instance in &self.prim_list.prim_instances {
|
||||
tile_cache.update_prim_dependencies(
|
||||
prim_instance,
|
||||
&self.prim_list,
|
||||
surface_spatial_node_index,
|
||||
&frame_context.clip_scroll_tree,
|
||||
resources,
|
||||
|
@ -2094,9 +2166,28 @@ impl PicturePrimitive {
|
|||
// If this picture establishes a surface, then map the surface bounding
|
||||
// rect into the parent surface coordinate space, and propagate that up
|
||||
// to the parent.
|
||||
if let Some(ref raster_config) = self.raster_config {
|
||||
if let Some(ref mut raster_config) = self.raster_config {
|
||||
let surface_rect = state.current_surface().rect;
|
||||
|
||||
// Sometimes, Gecko supplies a huge picture rect. This is typically
|
||||
// due to some weird startup condition, or a reftest that has an
|
||||
// extreme scale in it. In these cases, disable the tile cache and
|
||||
// just use the normal Blit composite mode for this picture. This
|
||||
// is not ideal (we could skip the surface altogether in the future)
|
||||
// but it's simple and works around this edge case for now.
|
||||
if let Some(ref mut tile_cache) = self.tile_cache {
|
||||
if surface_rect.size.width > MAX_PICTURE_SIZE ||
|
||||
surface_rect.size.height > MAX_PICTURE_SIZE ||
|
||||
surface_rect.size.width <= 0.0 ||
|
||||
surface_rect.size.height <= 0.0
|
||||
{
|
||||
tile_cache.needs_update = false;
|
||||
tile_cache.tiles.clear();
|
||||
tile_cache.tile_rect = TileRect::zero();
|
||||
raster_config.composite_mode = PictureCompositeMode::Blit;
|
||||
}
|
||||
}
|
||||
|
||||
let mut surface_rect = TypedRect::from_untyped(&surface_rect.to_untyped());
|
||||
|
||||
// Pop this surface from the stack
|
||||
|
|
|
@ -9,7 +9,7 @@ use api::{
|
|||
use display_list_flattener::{AsInstanceKind, IsVisible};
|
||||
use frame_builder::FrameBuildingState;
|
||||
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||
use intern::{DataStore, Handle, Internable, Interner, UpdateList};
|
||||
use intern::{DataStore, Handle, Internable, InternDebug, Interner, UpdateList};
|
||||
use prim_store::{BrushSegment, GradientTileRange};
|
||||
use prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData};
|
||||
use prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
|
||||
|
@ -76,6 +76,8 @@ impl LinearGradientKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl InternDebug for LinearGradientKey {}
|
||||
|
||||
impl AsInstanceKind<LinearGradientDataHandle> for LinearGradientKey {
|
||||
/// Construct a primitive instance that matches the type
|
||||
/// of primitive key.
|
||||
|
@ -333,6 +335,8 @@ impl RadialGradientKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl InternDebug for RadialGradientKey {}
|
||||
|
||||
impl AsInstanceKind<RadialGradientDataHandle> for RadialGradientKey {
|
||||
/// Construct a primitive instance that matches the type
|
||||
/// of primitive key.
|
||||
|
|
|
@ -26,7 +26,7 @@ use gpu_types::BrushFlags;
|
|||
use image::{self, Repetition};
|
||||
use intern;
|
||||
use picture::{PictureCompositeMode, PicturePrimitive, PictureUpdateState, TileCacheUpdateState};
|
||||
use picture::{ClusterRange, PrimitiveList, SurfaceIndex, SurfaceInfo, RetainedTiles};
|
||||
use picture::{ClusterRange, PrimitiveList, SurfaceIndex, SurfaceInfo, RetainedTiles, RasterConfig};
|
||||
use prim_store::gradient::{LinearGradientDataHandle, RadialGradientDataHandle};
|
||||
use prim_store::text_run::{TextRunDataHandle, TextRunPrimitive};
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -645,6 +645,8 @@ impl PrimitiveKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl intern::InternDebug for PrimitiveKey {}
|
||||
|
||||
impl AsInstanceKind<PrimitiveDataHandle> for PrimitiveKey {
|
||||
/// Construct a primitive instance that matches the type
|
||||
/// of primitive key.
|
||||
|
@ -962,11 +964,11 @@ impl PrimitiveTemplateKind {
|
|||
}
|
||||
}
|
||||
}
|
||||
PrimitiveTemplateKind::YuvImage { color_depth, .. } => {
|
||||
PrimitiveTemplateKind::YuvImage { color_depth, format, color_space, .. } => {
|
||||
request.push([
|
||||
color_depth.rescaling_factor(),
|
||||
0.0,
|
||||
0.0,
|
||||
pack_as_float(color_space as u32),
|
||||
pack_as_float(format as u32),
|
||||
0.0
|
||||
]);
|
||||
}
|
||||
|
@ -2120,6 +2122,13 @@ impl PrimitiveStore {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn print_picture_tree(&self, root: PictureIndex) {
|
||||
use print_tree::PrintTree;
|
||||
let mut pt = PrintTree::new("picture tree");
|
||||
self.pictures[root.0].print(&self.pictures, root, &mut pt);
|
||||
}
|
||||
|
||||
/// Destroy an existing primitive store. This is called just before
|
||||
/// a primitive store is replaced with a newly built scene.
|
||||
pub fn destroy(
|
||||
|
@ -2194,7 +2203,12 @@ impl PrimitiveStore {
|
|||
) {
|
||||
let children = {
|
||||
let pic = &mut self.pictures[pic_index.0];
|
||||
if let Some(PictureCompositeMode::TileCache { .. }) = pic.requested_composite_mode {
|
||||
// Only update the tile cache if we ended up selecting tile caching for the
|
||||
// composite mode of this picture. In some cases, even if the requested
|
||||
// composite mode was tile caching, WR may choose not to draw this picture
|
||||
// with tile cache enabled. For now, this is only in the case of very large
|
||||
// picture rects, but in future we may do it for performance reasons too.
|
||||
if let Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) = pic.raster_config {
|
||||
debug_assert!(state.tile_cache.is_none());
|
||||
let mut tile_cache = pic.tile_cache.take().unwrap();
|
||||
|
||||
|
@ -2246,7 +2260,7 @@ impl PrimitiveStore {
|
|||
}
|
||||
|
||||
let pic = &mut self.pictures[pic_index.0];
|
||||
if let Some(PictureCompositeMode::TileCache { .. }) = pic.requested_composite_mode {
|
||||
if let Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) = pic.raster_config {
|
||||
let mut tile_cache = state.tile_cache.take().unwrap().0;
|
||||
|
||||
// Build the dirty region(s) for this tile cache.
|
||||
|
@ -2561,7 +2575,7 @@ impl PrimitiveStore {
|
|||
frame_state.resource_cache,
|
||||
frame_context.device_pixel_scale,
|
||||
&pic_context.dirty_world_rect,
|
||||
&clip_node_collector,
|
||||
clip_node_collector.as_ref(),
|
||||
&mut resources.clip_data_store,
|
||||
);
|
||||
|
||||
|
@ -2621,7 +2635,7 @@ impl PrimitiveStore {
|
|||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
&clip_node_collector,
|
||||
clip_node_collector.as_ref(),
|
||||
self,
|
||||
resources,
|
||||
scratch,
|
||||
|
@ -3580,7 +3594,7 @@ impl PrimitiveInstance {
|
|||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
clip_node_collector: &Option<ClipNodeCollector>,
|
||||
clip_node_collector: Option<&ClipNodeCollector>,
|
||||
prim_store: &PrimitiveStore,
|
||||
resources: &mut FrameResources,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
|
@ -3748,7 +3762,7 @@ impl PrimitiveInstance {
|
|||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
clip_node_collector: &Option<ClipNodeCollector>,
|
||||
clip_node_collector: Option<&ClipNodeCollector>,
|
||||
prim_store: &mut PrimitiveStore,
|
||||
resources: &mut FrameResources,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
|
|
|
@ -52,6 +52,8 @@ impl TextRunKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl intern::InternDebug for TextRunKey {}
|
||||
|
||||
impl AsInstanceKind<TextRunDataHandle> for TextRunKey {
|
||||
/// Construct a primitive instance that matches the type
|
||||
/// of primitive key.
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
* 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/. */
|
||||
|
||||
use api::{
|
||||
YUV_COLOR_SPACES, YUV_FORMATS,
|
||||
YuvColorSpace, YuvFormat,
|
||||
};
|
||||
use batch::{BatchKey, BatchKind, BrushBatchKind};
|
||||
use device::{Device, Program, ShaderError};
|
||||
use euclid::{Transform3D};
|
||||
|
@ -635,7 +631,7 @@ impl Shaders {
|
|||
|
||||
// All yuv_image configuration.
|
||||
let mut yuv_features = Vec::new();
|
||||
let yuv_shader_num = IMAGE_BUFFER_KINDS.len() * YUV_FORMATS.len() * YUV_COLOR_SPACES.len();
|
||||
let yuv_shader_num = IMAGE_BUFFER_KINDS.len();
|
||||
let mut brush_yuv_image = Vec::new();
|
||||
// PrimitiveShader is not clonable. Use push() to initialize the vec.
|
||||
for _ in 0 .. yuv_shader_num {
|
||||
|
@ -643,37 +639,23 @@ impl Shaders {
|
|||
}
|
||||
for image_buffer_kind in &IMAGE_BUFFER_KINDS {
|
||||
if image_buffer_kind.has_platform_support(&gl_type) {
|
||||
for format_kind in &YUV_FORMATS {
|
||||
for color_space_kind in &YUV_COLOR_SPACES {
|
||||
let feature_string = image_buffer_kind.get_feature_string();
|
||||
if feature_string != "" {
|
||||
yuv_features.push(feature_string);
|
||||
}
|
||||
let feature_string = format_kind.get_feature_string();
|
||||
if feature_string != "" {
|
||||
yuv_features.push(feature_string);
|
||||
}
|
||||
let feature_string = color_space_kind.get_feature_string();
|
||||
if feature_string != "" {
|
||||
yuv_features.push(feature_string);
|
||||
}
|
||||
|
||||
let shader = BrushShader::new(
|
||||
"brush_yuv_image",
|
||||
device,
|
||||
&yuv_features,
|
||||
options.precache_flags,
|
||||
false,
|
||||
)?;
|
||||
let index = Self::get_yuv_shader_index(
|
||||
*image_buffer_kind,
|
||||
*format_kind,
|
||||
*color_space_kind,
|
||||
);
|
||||
brush_yuv_image[index] = Some(shader);
|
||||
yuv_features.clear();
|
||||
}
|
||||
let feature_string = image_buffer_kind.get_feature_string();
|
||||
if feature_string != "" {
|
||||
yuv_features.push(feature_string);
|
||||
}
|
||||
|
||||
let shader = BrushShader::new(
|
||||
"brush_yuv_image",
|
||||
device,
|
||||
&yuv_features,
|
||||
options.precache_flags,
|
||||
false,
|
||||
)?;
|
||||
let index = Self::get_yuv_shader_index(
|
||||
*image_buffer_kind,
|
||||
);
|
||||
brush_yuv_image[index] = Some(shader);
|
||||
yuv_features.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -733,13 +715,8 @@ impl Shaders {
|
|||
})
|
||||
}
|
||||
|
||||
fn get_yuv_shader_index(
|
||||
buffer_kind: ImageBufferKind,
|
||||
format: YuvFormat,
|
||||
color_space: YuvColorSpace,
|
||||
) -> usize {
|
||||
((buffer_kind as usize) * YUV_FORMATS.len() + (format as usize)) * YUV_COLOR_SPACES.len() +
|
||||
(color_space as usize)
|
||||
fn get_yuv_shader_index(buffer_kind: ImageBufferKind) -> usize {
|
||||
(buffer_kind as usize)
|
||||
}
|
||||
|
||||
pub fn get(&mut self, key: &BatchKey, debug_flags: DebugFlags) -> &mut LazilyCompiledShader {
|
||||
|
@ -769,9 +746,9 @@ impl Shaders {
|
|||
BrushBatchKind::LinearGradient => {
|
||||
&mut self.brush_linear_gradient
|
||||
}
|
||||
BrushBatchKind::YuvImage(image_buffer_kind, format, _color_depth, color_space) => {
|
||||
BrushBatchKind::YuvImage(image_buffer_kind, ..) => {
|
||||
let shader_index =
|
||||
Self::get_yuv_shader_index(image_buffer_kind, format, color_space);
|
||||
Self::get_yuv_shader_index(image_buffer_kind);
|
||||
self.brush_yuv_image[shader_index]
|
||||
.as_mut()
|
||||
.expect("Unsupported YUV shader kind")
|
||||
|
|
|
@ -110,6 +110,7 @@ pub trait RenderTarget {
|
|||
);
|
||||
|
||||
fn needs_depth(&self) -> bool;
|
||||
fn must_be_drawn(&self) -> bool;
|
||||
|
||||
fn used_rect(&self) -> DeviceIntRect;
|
||||
fn add_used(&mut self, rect: DeviceIntRect);
|
||||
|
@ -258,6 +259,10 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
self.targets.iter().any(|target| target.needs_depth())
|
||||
}
|
||||
|
||||
pub fn must_be_drawn(&self) -> bool {
|
||||
self.targets.iter().any(|target| target.must_be_drawn())
|
||||
}
|
||||
|
||||
pub fn check_ready(&self, t: &Texture) {
|
||||
let dimensions = t.get_dimensions();
|
||||
assert!(dimensions.width >= self.max_dynamic_size.width);
|
||||
|
@ -544,6 +549,10 @@ impl RenderTarget for ColorRenderTarget {
|
|||
}
|
||||
}
|
||||
|
||||
fn must_be_drawn(&self) -> bool {
|
||||
!self.tile_blits.is_empty()
|
||||
}
|
||||
|
||||
fn needs_depth(&self) -> bool {
|
||||
self.alpha_batch_containers.iter().any(|ab| {
|
||||
!ab.opaque_batches.is_empty()
|
||||
|
@ -674,6 +683,10 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
false
|
||||
}
|
||||
|
||||
fn must_be_drawn(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn used_rect(&self) -> DeviceIntRect {
|
||||
self.used_rect
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ fn validate_shaders() {
|
|||
}
|
||||
|
||||
let (vs, fs) =
|
||||
webrender::build_shader_strings(VERSION_STRING, &features, shader.name, &None);
|
||||
webrender::build_shader_strings(VERSION_STRING, &features, shader.name, None);
|
||||
|
||||
validate(&vs_validator, shader.name, vs);
|
||||
validate(&fs_validator, shader.name, fs);
|
||||
|
|
|
@ -689,16 +689,6 @@ pub enum YuvColorSpace {
|
|||
Rec601 = 0,
|
||||
Rec709 = 1,
|
||||
}
|
||||
pub const YUV_COLOR_SPACES: [YuvColorSpace; 2] = [YuvColorSpace::Rec601, YuvColorSpace::Rec709];
|
||||
|
||||
impl YuvColorSpace {
|
||||
pub fn get_feature_string(&self) -> &'static str {
|
||||
match *self {
|
||||
YuvColorSpace::Rec601 => "YUV_REC601",
|
||||
YuvColorSpace::Rec709 => "YUV_REC709",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum YuvData {
|
||||
|
@ -723,11 +713,6 @@ pub enum YuvFormat {
|
|||
PlanarYCbCr = 1,
|
||||
InterleavedYCbCr = 2,
|
||||
}
|
||||
pub const YUV_FORMATS: [YuvFormat; 3] = [
|
||||
YuvFormat::NV12,
|
||||
YuvFormat::PlanarYCbCr,
|
||||
YuvFormat::InterleavedYCbCr,
|
||||
];
|
||||
|
||||
impl YuvFormat {
|
||||
pub fn get_plane_num(&self) -> usize {
|
||||
|
@ -737,14 +722,6 @@ impl YuvFormat {
|
|||
YuvFormat::InterleavedYCbCr => 1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_feature_string(&self) -> &'static str {
|
||||
match *self {
|
||||
YuvFormat::NV12 => "YUV_NV12",
|
||||
YuvFormat::PlanarYCbCr => "YUV_PLANAR",
|
||||
YuvFormat::InterleavedYCbCr => "YUV_INTERLEAVED",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 9.8 KiB |
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: clip
|
||||
id: 2
|
||||
bounds: [100, 100, 2000, 2000]
|
||||
clip-rect: [100, 100, 2000, 2000]
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [10, 10, 0, 0]
|
||||
filters: drop-shadow([10, 10], 20, red)
|
||||
clip-node: 2
|
||||
items:
|
||||
- type: clip
|
||||
bounds: [0, 0, 256, 256]
|
||||
complex:
|
||||
- rect: [0, 0, 256, 256]
|
||||
radius: 16
|
||||
items:
|
||||
- type: rect
|
||||
bounds: 0 0 256 256
|
||||
color: green
|
|
@ -33,6 +33,7 @@ fuzzy(1,14) == filter-long-chain.yaml filter-long-chain.png
|
|||
platform(linux,mac) == filter-drop-shadow.yaml filter-drop-shadow.png
|
||||
platform(linux,mac) == filter-drop-shadow-on-viewport-edge.yaml filter-drop-shadow-on-viewport-edge.png
|
||||
platform(linux,mac) == blend-clipped.yaml blend-clipped.png
|
||||
platform(linux,mac) == filter-drop-shadow-clip.yaml filter-drop-shadow-clip.png
|
||||
== filter-segments.yaml filter-segments-ref.yaml
|
||||
== iframe-dropshadow.yaml iframe-dropshadow-ref.yaml
|
||||
== filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.yaml
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
#include "nsStreamUtils.h"
|
||||
#include "gfxColor.h"
|
||||
|
||||
extern "C" {
|
||||
#include "jpeglib.h"
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
#include "jerror.h"
|
||||
|
||||
|
@ -17,6 +21,45 @@ using namespace mozilla;
|
|||
NS_IMPL_ISUPPORTS(nsJPEGEncoder, imgIEncoder, nsIInputStream,
|
||||
nsIAsyncInputStream)
|
||||
|
||||
class nsJPEGEncoderInternal {
|
||||
friend class nsJPEGEncoder;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initialize destination. This is called by jpeg_start_compress() before
|
||||
* any data is actually written. It must initialize next_output_byte and
|
||||
* free_in_buffer. free_in_buffer must be initialized to a positive value.
|
||||
*/
|
||||
static void initDestination(jpeg_compress_struct* cinfo);
|
||||
|
||||
/**
|
||||
* This is called whenever the buffer has filled (free_in_buffer reaches
|
||||
* zero). In typical applications, it should write out the *entire* buffer
|
||||
* (use the saved start address and buffer length; ignore the current state
|
||||
* of next_output_byte and free_in_buffer). Then reset the pointer & count
|
||||
* to the start of the buffer, and return TRUE indicating that the buffer
|
||||
* has been dumped. free_in_buffer must be set to a positive value when
|
||||
* TRUE is returned. A FALSE return should only be used when I/O suspension
|
||||
* is desired (this operating mode is discussed in the next section).
|
||||
*/
|
||||
static boolean emptyOutputBuffer(jpeg_compress_struct* cinfo);
|
||||
|
||||
|
||||
/**
|
||||
* Terminate destination --- called by jpeg_finish_compress() after all data
|
||||
* has been written. In most applications, this must flush any data
|
||||
* remaining in the buffer. Use either next_output_byte or free_in_buffer
|
||||
* to determine how much data is in the buffer.
|
||||
*/
|
||||
static void termDestination(jpeg_compress_struct* cinfo);
|
||||
|
||||
/**
|
||||
* Override the standard error method in the IJG JPEG decoder code. This
|
||||
* was mostly copied from nsJPEGDecoder.cpp
|
||||
*/
|
||||
static void errorExit(jpeg_common_struct* cinfo);
|
||||
};
|
||||
|
||||
// used to pass error info through the JPEG library
|
||||
struct encoder_error_mgr {
|
||||
jpeg_error_mgr pub;
|
||||
|
@ -111,7 +154,7 @@ nsJPEGEncoder::InitFromData(const uint8_t* aData,
|
|||
// This must be done before the call to create_compress
|
||||
encoder_error_mgr errmgr;
|
||||
cinfo.err = jpeg_std_error(&errmgr.pub);
|
||||
errmgr.pub.error_exit = errorExit;
|
||||
errmgr.pub.error_exit = nsJPEGEncoderInternal::errorExit;
|
||||
// Establish the setjmp return context for my_error_exit to use.
|
||||
if (setjmp(errmgr.setjmp_buffer)) {
|
||||
// If we get here, the JPEG code has signaled an error.
|
||||
|
@ -138,9 +181,9 @@ nsJPEGEncoder::InitFromData(const uint8_t* aData,
|
|||
|
||||
// set up the destination manager
|
||||
jpeg_destination_mgr destmgr;
|
||||
destmgr.init_destination = initDestination;
|
||||
destmgr.empty_output_buffer = emptyOutputBuffer;
|
||||
destmgr.term_destination = termDestination;
|
||||
destmgr.init_destination = nsJPEGEncoderInternal::initDestination;
|
||||
destmgr.empty_output_buffer = nsJPEGEncoderInternal::emptyOutputBuffer;
|
||||
destmgr.term_destination = nsJPEGEncoderInternal::termDestination;
|
||||
cinfo.dest = &destmgr;
|
||||
cinfo.client_data = this;
|
||||
|
||||
|
@ -347,14 +390,39 @@ void nsJPEGEncoder::ConvertRGBARow(const uint8_t* aSrc, uint8_t* aDest,
|
|||
}
|
||||
}
|
||||
|
||||
// nsJPEGEncoder::initDestination
|
||||
//
|
||||
// Initialize destination. This is called by jpeg_start_compress() before
|
||||
// any data is actually written. It must initialize next_output_byte and
|
||||
// free_in_buffer. free_in_buffer must be initialized to a positive value.
|
||||
|
||||
void // static
|
||||
nsJPEGEncoder::initDestination(jpeg_compress_struct* cinfo) {
|
||||
void nsJPEGEncoder::NotifyListener() {
|
||||
// We might call this function on multiple threads (any threads that call
|
||||
// AsyncWait and any that do encoding) so we lock to avoid notifying the
|
||||
// listener twice about the same data (which generally leads to a truncated
|
||||
// image).
|
||||
ReentrantMonitorAutoEnter autoEnter(mReentrantMonitor);
|
||||
|
||||
if (mCallback &&
|
||||
(mImageBufferUsed - mImageBufferReadPoint >= mNotifyThreshold ||
|
||||
mFinished)) {
|
||||
nsCOMPtr<nsIInputStreamCallback> callback;
|
||||
if (mCallbackTarget) {
|
||||
callback = NS_NewInputStreamReadyEvent("nsJPEGEncoder::NotifyListener",
|
||||
mCallback, mCallbackTarget);
|
||||
} else {
|
||||
callback = mCallback;
|
||||
}
|
||||
|
||||
NS_ASSERTION(callback, "Shouldn't fail to make the callback");
|
||||
// Null the callback first because OnInputStreamReady could reenter
|
||||
// AsyncWait
|
||||
mCallback = nullptr;
|
||||
mCallbackTarget = nullptr;
|
||||
mNotifyThreshold = 0;
|
||||
|
||||
callback->OnInputStreamReady(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* static */ void
|
||||
nsJPEGEncoderInternal::initDestination(jpeg_compress_struct* cinfo) {
|
||||
nsJPEGEncoder* that = static_cast<nsJPEGEncoder*>(cinfo->client_data);
|
||||
NS_ASSERTION(!that->mImageBuffer, "Image buffer already initialized");
|
||||
|
||||
|
@ -366,19 +434,8 @@ nsJPEGEncoder::initDestination(jpeg_compress_struct* cinfo) {
|
|||
cinfo->dest->free_in_buffer = that->mImageBufferSize;
|
||||
}
|
||||
|
||||
// nsJPEGEncoder::emptyOutputBuffer
|
||||
//
|
||||
// This is called whenever the buffer has filled (free_in_buffer reaches
|
||||
// zero). In typical applications, it should write out the *entire* buffer
|
||||
// (use the saved start address and buffer length; ignore the current state
|
||||
// of next_output_byte and free_in_buffer). Then reset the pointer & count
|
||||
// to the start of the buffer, and return TRUE indicating that the buffer
|
||||
// has been dumped. free_in_buffer must be set to a positive value when
|
||||
// TRUE is returned. A FALSE return should only be used when I/O suspension
|
||||
// is desired (this operating mode is discussed in the next section).
|
||||
|
||||
boolean // static
|
||||
nsJPEGEncoder::emptyOutputBuffer(jpeg_compress_struct* cinfo) {
|
||||
/* static */ boolean
|
||||
nsJPEGEncoderInternal::emptyOutputBuffer(jpeg_compress_struct* cinfo) {
|
||||
nsJPEGEncoder* that = static_cast<nsJPEGEncoder*>(cinfo->client_data);
|
||||
NS_ASSERTION(that->mImageBuffer, "No buffer to empty!");
|
||||
|
||||
|
@ -413,15 +470,8 @@ nsJPEGEncoder::emptyOutputBuffer(jpeg_compress_struct* cinfo) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// nsJPEGEncoder::termDestination
|
||||
//
|
||||
// Terminate destination --- called by jpeg_finish_compress() after all data
|
||||
// has been written. In most applications, this must flush any data
|
||||
// remaining in the buffer. Use either next_output_byte or free_in_buffer
|
||||
// to determine how much data is in the buffer.
|
||||
|
||||
void // static
|
||||
nsJPEGEncoder::termDestination(jpeg_compress_struct* cinfo) {
|
||||
/* static */ void
|
||||
nsJPEGEncoderInternal::termDestination(jpeg_compress_struct* cinfo) {
|
||||
nsJPEGEncoder* that = static_cast<nsJPEGEncoder*>(cinfo->client_data);
|
||||
if (!that->mImageBuffer) {
|
||||
return;
|
||||
|
@ -432,13 +482,8 @@ nsJPEGEncoder::termDestination(jpeg_compress_struct* cinfo) {
|
|||
that->NotifyListener();
|
||||
}
|
||||
|
||||
// nsJPEGEncoder::errorExit
|
||||
//
|
||||
// Override the standard error method in the IJG JPEG decoder code. This
|
||||
// was mostly copied from nsJPEGDecoder.cpp
|
||||
|
||||
void // static
|
||||
nsJPEGEncoder::errorExit(jpeg_common_struct* cinfo) {
|
||||
/* static */ void
|
||||
nsJPEGEncoderInternal::errorExit(jpeg_common_struct* cinfo) {
|
||||
nsresult error_code;
|
||||
encoder_error_mgr* err = (encoder_error_mgr*)cinfo->err;
|
||||
|
||||
|
@ -454,33 +499,4 @@ nsJPEGEncoder::errorExit(jpeg_common_struct* cinfo) {
|
|||
// Return control to the setjmp point. We pass an nsresult masquerading as
|
||||
// an int, which works because the setjmp() caller casts it back.
|
||||
longjmp(err->setjmp_buffer, static_cast<int>(error_code));
|
||||
}
|
||||
|
||||
void nsJPEGEncoder::NotifyListener() {
|
||||
// We might call this function on multiple threads (any threads that call
|
||||
// AsyncWait and any that do encoding) so we lock to avoid notifying the
|
||||
// listener twice about the same data (which generally leads to a truncated
|
||||
// image).
|
||||
ReentrantMonitorAutoEnter autoEnter(mReentrantMonitor);
|
||||
|
||||
if (mCallback &&
|
||||
(mImageBufferUsed - mImageBufferReadPoint >= mNotifyThreshold ||
|
||||
mFinished)) {
|
||||
nsCOMPtr<nsIInputStreamCallback> callback;
|
||||
if (mCallbackTarget) {
|
||||
callback = NS_NewInputStreamReadyEvent("nsJPEGEncoder::NotifyListener",
|
||||
mCallback, mCallbackTarget);
|
||||
} else {
|
||||
callback = mCallback;
|
||||
}
|
||||
|
||||
NS_ASSERTION(callback, "Shouldn't fail to make the callback");
|
||||
// Null the callback first because OnInputStreamReady could reenter
|
||||
// AsyncWait
|
||||
mCallback = nullptr;
|
||||
mCallbackTarget = nullptr;
|
||||
mNotifyThreshold = 0;
|
||||
|
||||
callback->OnInputStreamReady(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,12 +13,8 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// needed for JPEG library
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C" {
|
||||
#include "jpeglib.h"
|
||||
}
|
||||
struct jpeg_compress_struct;
|
||||
struct jpeg_common_struct;
|
||||
|
||||
#define NS_JPEGENCODER_CID \
|
||||
{ \
|
||||
|
@ -30,8 +26,10 @@ extern "C" {
|
|||
|
||||
// Provides JPEG encoding functionality. Use InitFromData() to do the
|
||||
// encoding. See that function definition for encoding options.
|
||||
class nsJPEGEncoderInternal;
|
||||
|
||||
class nsJPEGEncoder final : public imgIEncoder {
|
||||
friend class nsJPEGEncoderInternal;
|
||||
typedef mozilla::ReentrantMonitor ReentrantMonitor;
|
||||
|
||||
public:
|
||||
|
@ -51,12 +49,6 @@ class nsJPEGEncoder final : public imgIEncoder {
|
|||
void ConvertRGBARow(const uint8_t* aSrc, uint8_t* aDest,
|
||||
uint32_t aPixelWidth);
|
||||
|
||||
static void initDestination(jpeg_compress_struct* cinfo);
|
||||
static boolean emptyOutputBuffer(jpeg_compress_struct* cinfo);
|
||||
static void termDestination(jpeg_compress_struct* cinfo);
|
||||
|
||||
static void errorExit(jpeg_common_struct* cinfo);
|
||||
|
||||
void NotifyListener();
|
||||
|
||||
bool mFinished;
|
||||
|
|
|
@ -54,6 +54,7 @@ EXPORTS += [
|
|||
]
|
||||
|
||||
EXPORTS.mozilla.image += [
|
||||
'encoders/jpeg/nsJPEGEncoder.h',
|
||||
'ImageMemoryReporter.h',
|
||||
'RecyclingSourceSurface.h',
|
||||
]
|
||||
|
|
|
@ -689,18 +689,15 @@ class ExprDeref(ExprPrefixUnop):
|
|||
|
||||
class ExprCast(Node):
|
||||
def __init__(self, expr, type,
|
||||
dynamic=0, static=0, reinterpret=0, const=False, C=0):
|
||||
assert 1 == sum([dynamic, static, reinterpret, const, C])
|
||||
assert isinstance(const, bool)
|
||||
static=False, const=False):
|
||||
# Exactly one of these should be set
|
||||
assert static ^ const
|
||||
|
||||
Node.__init__(self)
|
||||
self.expr = expr
|
||||
self.type = type
|
||||
self.dynamic = dynamic
|
||||
self.static = static
|
||||
self.reinterpret = reinterpret
|
||||
self.const = const
|
||||
self.C = C
|
||||
|
||||
|
||||
class ExprBinary(Node):
|
||||
|
|
|
@ -329,17 +329,11 @@ class CxxCodeGen(CodePrinter, Visitor):
|
|||
self.write(')')
|
||||
|
||||
def visitExprCast(self, c):
|
||||
pfx, sfx = '', ''
|
||||
if c.dynamic:
|
||||
pfx, sfx = 'dynamic_cast<', '>'
|
||||
elif c.static:
|
||||
if c.static:
|
||||
pfx, sfx = 'static_cast<', '>'
|
||||
elif c.reinterpret:
|
||||
pfx, sfx = 'reinterpret_cast<', '>'
|
||||
elif c.const:
|
||||
else:
|
||||
assert c.const
|
||||
pfx, sfx = 'const_cast<', '>'
|
||||
elif c.C:
|
||||
pfx, sfx = '(', ')'
|
||||
self.write(pfx)
|
||||
c.type.accept(self)
|
||||
self.write(sfx + '(')
|
||||
|
|
|
@ -1955,7 +1955,7 @@ class _ParamTraits():
|
|||
Whitespace.NL,
|
||||
StmtExpr(ExprAssn(ExprDeref(cls.var),
|
||||
ExprCast(ExprCall(ExprSelect(actorvar, '.', 'value')),
|
||||
cxxtype, static=1))),
|
||||
cxxtype, static=True))),
|
||||
StmtReturn.TRUE,
|
||||
]
|
||||
|
||||
|
@ -2360,7 +2360,7 @@ def _generateCxxUnion(ud):
|
|||
return ifdied
|
||||
|
||||
def voidCast(expr):
|
||||
return ExprCast(expr, Type.VOID, static=1)
|
||||
return ExprCast(expr, Type.VOID, static=True)
|
||||
|
||||
# compute all the typedefs and forward decls we need to make
|
||||
gettypedeps = _ComputeTypeDeps(ud.decl.type)
|
||||
|
@ -2635,7 +2635,7 @@ def _generateCxxUnion(ud):
|
|||
# The void cast prevents Coverity from complaining about missing return
|
||||
# value checks.
|
||||
StmtBlock([StmtExpr(ExprCast(callMaybeDestroy(rhstypevar), Type.VOID,
|
||||
static=1)),
|
||||
static=True)),
|
||||
StmtBreak()])
|
||||
)
|
||||
opeqswitch.addcase(
|
||||
|
@ -3248,7 +3248,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
'Manager', ret=managertype, const=True))
|
||||
managerexp = ExprCall(ExprVar('IProtocol::Manager'), args=[])
|
||||
managermeth.addstmt(StmtReturn(
|
||||
ExprCast(managerexp, managertype, static=1)))
|
||||
ExprCast(managerexp, managertype, static=True)))
|
||||
|
||||
self.cls.addstmts([managermeth, Whitespace.NL])
|
||||
|
||||
|
@ -3665,7 +3665,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
|
||||
case.addstmts([
|
||||
StmtDecl(Decl(manageecxxtype, actorvar.name),
|
||||
ExprCast(listenervar, manageecxxtype, static=1)),
|
||||
ExprCast(listenervar, manageecxxtype, static=True)),
|
||||
# Use a temporary variable here so all the assertion expressions
|
||||
# in the _abortIfFalse call below are textually identical; the
|
||||
# linker can then merge the strings from the assertion macro(s).
|
||||
|
@ -4028,7 +4028,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
init=ExprCast(ExprCall(ExprSelect(ExprVar('untypedCallback'),
|
||||
'.', 'get')),
|
||||
callbackptr,
|
||||
static=1)),
|
||||
static=True)),
|
||||
ifnocallback]
|
||||
|
||||
resolvecallback = [StmtExpr(ExprCall(ExprSelect(callback, '->', 'Resolve'),
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
== xbl-basic-02.svg pass.svg
|
||||
== xbl-basic-03.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-binding-01.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-binding-02.svg pass.svg
|
||||
fails == xbl-grad-ref--grad-in-binding-02.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-bound-01.svg pass.svg
|
||||
fails == xbl-grad-ref--grad-in-bound-02.svg pass-black.svg
|
||||
fails == xbl-grad-ref--grad-in-resources-01.svg pass.svg
|
||||
fails == xbl-grad-ref--grad-in-resources-02.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-binding-03.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-bound-03.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-binding-04.svg pass.svg
|
||||
fails == xbl-grad-ref--grad-in-binding-04.svg pass.svg
|
||||
== xbl-grad-ref--grad-in-bound-04.svg pass.svg
|
||||
|
||||
# Tests for zooming with the full page zoom UI
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.gfx.GeckoSurface;
|
||||
import org.mozilla.gecko.gfx.SyncConfig;
|
||||
|
||||
interface ISurfaceAllocator {
|
||||
GeckoSurface acquireSurface(in int width, in int height, in boolean singleBufferMode);
|
||||
void releaseSurface(in int handle);
|
||||
void configureSync(in SyncConfig config);
|
||||
void sync(in int handle);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
parcelable SyncConfig;
|
|
@ -10,28 +10,30 @@ import android.graphics.SurfaceTexture;
|
|||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.view.Surface;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
|
||||
import static org.mozilla.geckoview.BuildConfig.DEBUG_BUILD;
|
||||
|
||||
public final class GeckoSurface extends Surface {
|
||||
private static final String LOGTAG = "GeckoSurface";
|
||||
|
||||
private static final HashMap<Integer, GeckoSurfaceTexture> sSurfaceTextures = new HashMap<Integer, GeckoSurfaceTexture>();
|
||||
|
||||
private int mHandle;
|
||||
private boolean mIsSingleBuffer;
|
||||
private volatile boolean mIsAvailable;
|
||||
private boolean mOwned = true;
|
||||
|
||||
private int mMyPid;
|
||||
// Locally allocated surface/texture. Do not pass it over IPC.
|
||||
private GeckoSurface mSyncSurface;
|
||||
|
||||
@WrapForJNI(exceptionMode = "nsresult")
|
||||
public GeckoSurface(GeckoSurfaceTexture gst) {
|
||||
super(gst);
|
||||
mHandle = gst.getHandle();
|
||||
mIsSingleBuffer = gst.isSingleBuffer();
|
||||
mIsAvailable = true;
|
||||
mMyPid = android.os.Process.myPid();
|
||||
}
|
||||
|
||||
public GeckoSurface(Parcel p, SurfaceTexture dummy) {
|
||||
|
@ -44,6 +46,7 @@ public final class GeckoSurface extends Surface {
|
|||
mHandle = p.readInt();
|
||||
mIsSingleBuffer = p.readByte() == 1 ? true : false;
|
||||
mIsAvailable = (p.readByte() == 1 ? true : false);
|
||||
mMyPid = p.readInt();
|
||||
|
||||
dummy.release();
|
||||
}
|
||||
|
@ -64,12 +67,22 @@ public final class GeckoSurface extends Surface {
|
|||
out.writeInt(mHandle);
|
||||
out.writeByte((byte) (mIsSingleBuffer ? 1 : 0));
|
||||
out.writeByte((byte) (mIsAvailable ? 1 : 0));
|
||||
out.writeInt(mMyPid);
|
||||
|
||||
mOwned = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
if (mSyncSurface != null) {
|
||||
mSyncSurface.release();
|
||||
GeckoSurfaceTexture gst = GeckoSurfaceTexture.lookup(mSyncSurface.getHandle());
|
||||
if (gst != null) {
|
||||
gst.decrementUse();
|
||||
}
|
||||
mSyncSurface = null;
|
||||
}
|
||||
|
||||
if (mOwned) {
|
||||
super.release();
|
||||
}
|
||||
|
@ -89,4 +102,25 @@ public final class GeckoSurface extends Surface {
|
|||
public void setAvailable(boolean available) {
|
||||
mIsAvailable = available;
|
||||
}
|
||||
|
||||
/* package */ boolean inProcess() {
|
||||
return android.os.Process.myPid() == mMyPid;
|
||||
}
|
||||
|
||||
/* package */ SyncConfig initSyncSurface(int width, int height) {
|
||||
if (DEBUG_BUILD) {
|
||||
if (inProcess()) {
|
||||
throw new AssertionError("no need for sync when allocated in process");
|
||||
}
|
||||
}
|
||||
if (GeckoSurfaceTexture.lookup(mHandle) != null) {
|
||||
throw new AssertionError("texture#" + mHandle + " already in use.");
|
||||
}
|
||||
GeckoSurfaceTexture texture = GeckoSurfaceTexture.acquire(false, mHandle);
|
||||
texture.setDefaultBufferSize(width, height);
|
||||
texture.track(mHandle);
|
||||
mSyncSurface = new GeckoSurface(texture);
|
||||
|
||||
return new SyncConfig(mHandle, mSyncSurface, width, height);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.HashMap;
|
|||
import java.util.LinkedList;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.mozglue.JNIObject;
|
||||
|
||||
/* package */ final class GeckoSurfaceTexture extends SurfaceTexture {
|
||||
private static final String LOGTAG = "GeckoSurfaceTexture";
|
||||
|
@ -36,6 +37,9 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|
|||
private AtomicInteger mUseCount;
|
||||
private boolean mFinalized;
|
||||
|
||||
private int mUpstream;
|
||||
private NativeGLBlitHelper mBlitter;
|
||||
|
||||
private GeckoSurfaceTexture(int handle) {
|
||||
super(0);
|
||||
init(handle, false);
|
||||
|
@ -111,6 +115,9 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|
|||
@WrapForJNI
|
||||
public synchronized void updateTexImage() {
|
||||
try {
|
||||
if (mUpstream != 0) {
|
||||
SurfaceAllocator.sync(mUpstream);
|
||||
}
|
||||
super.updateTexImage();
|
||||
if (mListener != null) {
|
||||
mListener.onUpdateTexImage();
|
||||
|
@ -122,6 +129,10 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|
|||
|
||||
@Override
|
||||
public synchronized void release() {
|
||||
mUpstream = 0;
|
||||
if (mBlitter != null) {
|
||||
mBlitter.disposeNative();
|
||||
}
|
||||
try {
|
||||
super.release();
|
||||
synchronized (sSurfaceTextures) {
|
||||
|
@ -237,7 +248,7 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|
|||
}
|
||||
}
|
||||
|
||||
public static GeckoSurfaceTexture acquire(boolean singleBufferMode) {
|
||||
public static GeckoSurfaceTexture acquire(boolean singleBufferMode, int handle) {
|
||||
if (singleBufferMode && !isSingleBufferSupported()) {
|
||||
throw new IllegalArgumentException("single buffer mode not supported on API version < 19");
|
||||
}
|
||||
|
@ -250,7 +261,10 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|
|||
return null;
|
||||
}
|
||||
|
||||
int handle = sNextHandle++;
|
||||
if (handle == 0) {
|
||||
// Generate new handle value when none specified.
|
||||
handle = sNextHandle++;
|
||||
}
|
||||
|
||||
final GeckoSurfaceTexture gst;
|
||||
if (isSingleBufferSupported()) {
|
||||
|
@ -276,8 +290,32 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|
|||
}
|
||||
}
|
||||
|
||||
/* package */ synchronized void track(int upstream) {
|
||||
mUpstream = upstream;
|
||||
}
|
||||
|
||||
/* package */ synchronized void configureSnapshot(GeckoSurface target, int width, int height) {
|
||||
mBlitter = NativeGLBlitHelper.create(mHandle, target, width, height);
|
||||
}
|
||||
|
||||
/* package */ synchronized void takeSnapshot() {
|
||||
mBlitter.blit();
|
||||
}
|
||||
|
||||
public interface Callbacks {
|
||||
void onUpdateTexImage();
|
||||
void onReleaseTexImage();
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public static final class NativeGLBlitHelper extends JNIObject {
|
||||
public native static NativeGLBlitHelper create(int textureHandle,
|
||||
GeckoSurface targetSurface,
|
||||
int width,
|
||||
int height);
|
||||
public native void blit();
|
||||
|
||||
@Override
|
||||
protected native void disposeNative();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,9 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
|
@ -49,8 +46,12 @@ import org.mozilla.gecko.GeckoAppShell;
|
|||
if (singleBufferMode && !GeckoSurfaceTexture.isSingleBufferSupported()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return sConnection.getAllocator().acquireSurface(width, height, singleBufferMode);
|
||||
ISurfaceAllocator allocator = sConnection.getAllocator();
|
||||
GeckoSurface surface = allocator.acquireSurface(width, height, singleBufferMode);
|
||||
if (surface != null && !surface.inProcess()) {
|
||||
allocator.configureSync(surface.initSyncSurface(width, height));
|
||||
}
|
||||
return surface;
|
||||
} catch (Exception e) {
|
||||
Log.w(LOGTAG, "Failed to acquire GeckoSurface", e);
|
||||
return null;
|
||||
|
@ -81,6 +82,22 @@ import org.mozilla.gecko.GeckoAppShell;
|
|||
}
|
||||
}
|
||||
|
||||
public static void sync(int upstream) {
|
||||
try {
|
||||
ensureConnection();
|
||||
} catch (Exception e) {
|
||||
Log.w(LOGTAG, "Failed to sync texture, no connection");
|
||||
return;
|
||||
}
|
||||
|
||||
// Release the SurfaceTexture on the other side
|
||||
try {
|
||||
sConnection.getAllocator().sync(upstream);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOGTAG, "Failed to sync texture", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SurfaceAllocatorConnection implements ServiceConnection {
|
||||
private ISurfaceAllocator mAllocator;
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ import android.app.Service;
|
|||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
public final class SurfaceAllocatorService extends Service {
|
||||
|
||||
|
@ -22,7 +20,7 @@ public final class SurfaceAllocatorService extends Service {
|
|||
|
||||
private Binder mBinder = new ISurfaceAllocator.Stub() {
|
||||
public GeckoSurface acquireSurface(int width, int height, boolean singleBufferMode) {
|
||||
GeckoSurfaceTexture gst = GeckoSurfaceTexture.acquire(singleBufferMode);
|
||||
GeckoSurfaceTexture gst = GeckoSurfaceTexture.acquire(singleBufferMode, 0);
|
||||
|
||||
if (gst == null) {
|
||||
return null;
|
||||
|
@ -41,6 +39,20 @@ public final class SurfaceAllocatorService extends Service {
|
|||
gst.decrementUse();
|
||||
}
|
||||
}
|
||||
|
||||
public void configureSync(SyncConfig config) {
|
||||
final GeckoSurfaceTexture gst = GeckoSurfaceTexture.lookup(config.sourceTextureHandle);
|
||||
if (gst != null) {
|
||||
gst.configureSnapshot(config.targetSurface, config.width, config.height);
|
||||
}
|
||||
}
|
||||
|
||||
public void sync(int handle) {
|
||||
final GeckoSurfaceTexture gst = GeckoSurfaceTexture.lookup(handle);
|
||||
if (gst != null) {
|
||||
gst.takeSnapshot();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public IBinder onBind(final Intent intent) {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/* package */ final class SyncConfig implements Parcelable {
|
||||
final int sourceTextureHandle;
|
||||
final GeckoSurface targetSurface;
|
||||
final int width;
|
||||
final int height;
|
||||
|
||||
/* package */ SyncConfig(int sourceTextureHandle,
|
||||
GeckoSurface targetSurface,
|
||||
int width,
|
||||
int height) {
|
||||
this.sourceTextureHandle = sourceTextureHandle;
|
||||
this.targetSurface = targetSurface;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public static final Creator<SyncConfig> CREATOR =
|
||||
new Creator<SyncConfig>() {
|
||||
@Override
|
||||
public SyncConfig createFromParcel(Parcel parcel) {
|
||||
return new SyncConfig(parcel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SyncConfig[] newArray(int i) {
|
||||
return new SyncConfig[i];
|
||||
}
|
||||
};
|
||||
|
||||
private SyncConfig(Parcel parcel) {
|
||||
sourceTextureHandle = parcel.readInt();
|
||||
targetSurface = GeckoSurface.CREATOR.createFromParcel(parcel);
|
||||
width = parcel.readInt();
|
||||
height = parcel.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeInt(sourceTextureHandle);
|
||||
targetSurface.writeToParcel(parcel, flags);
|
||||
parcel.writeInt(width);
|
||||
parcel.writeInt(height);
|
||||
}
|
||||
}
|
|
@ -55,7 +55,7 @@ public class SharedMemory implements Parcelable {
|
|||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
return CONTENTS_FILE_DESCRIPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -462,7 +462,8 @@ class nsHttpChannel final : public HttpBaseChannel,
|
|||
|
||||
inline static bool DoNotRender3xxBody(nsresult rv) {
|
||||
return rv == NS_ERROR_REDIRECT_LOOP || rv == NS_ERROR_CORRUPTED_CONTENT ||
|
||||
rv == NS_ERROR_UNKNOWN_PROTOCOL || rv == NS_ERROR_MALFORMED_URI;
|
||||
rv == NS_ERROR_UNKNOWN_PROTOCOL || rv == NS_ERROR_MALFORMED_URI ||
|
||||
rv == NS_ERROR_PORT_ACCESS_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
// Report net vs cache time telemetry
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -204,7 +204,6 @@ class nsHtml5AttributeName {
|
|||
static nsHtml5AttributeName* ATTR_K4;
|
||||
static nsHtml5AttributeName* ATTR_XML_SPACE;
|
||||
static nsHtml5AttributeName* ATTR_XML_LANG;
|
||||
static nsHtml5AttributeName* ATTR_XML_BASE;
|
||||
static nsHtml5AttributeName* ATTR_ARIA_GRAB;
|
||||
static nsHtml5AttributeName* ATTR_ARIA_VALUEMAX;
|
||||
static nsHtml5AttributeName* ATTR_ARIA_LABELLEDBY;
|
||||
|
|
|
@ -1171,4 +1171,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1553170230614000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1553515916483000);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -5,7 +5,7 @@
|
|||
//! Collects a series of applicable rules for a given element.
|
||||
|
||||
use crate::applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList};
|
||||
use crate::dom::{TElement, TShadowRoot};
|
||||
use crate::dom::{TElement, TNode, TShadowRoot};
|
||||
use crate::properties::{AnimationRules, PropertyDeclarationBlock};
|
||||
use crate::rule_tree::{CascadeLevel, ShadowCascadeOrder};
|
||||
use crate::selector_map::SelectorMap;
|
||||
|
@ -17,6 +17,43 @@ use selectors::matching::{ElementSelectorFlags, MatchingContext};
|
|||
use servo_arc::ArcBorrow;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
/// This is a bit of a hack so <svg:use> matches the rules of the enclosing
|
||||
/// tree.
|
||||
///
|
||||
/// This function returns the containing shadow host ignoring <svg:use> shadow
|
||||
/// trees, since those match the enclosing tree's rules.
|
||||
///
|
||||
/// Only a handful of places need to really care about this. This is not a
|
||||
/// problem for invalidation and that kind of stuff because they still don't
|
||||
/// match rules based on elements outside of the shadow tree, and because the
|
||||
/// <svg:use> subtrees are immutable and recreated each time the source tree
|
||||
/// changes.
|
||||
///
|
||||
/// We historically allow cross-document <svg:use> to have these rules applied,
|
||||
/// but I think that's not great. Gecko is the only engine supporting that.
|
||||
///
|
||||
/// See https://github.com/w3c/svgwg/issues/504 for the relevant spec
|
||||
/// discussion.
|
||||
#[inline]
|
||||
pub fn containing_shadow_ignoring_svg_use<E: TElement>(
|
||||
element: E,
|
||||
) -> Option<<E::ConcreteNode as TNode>::ConcreteShadowRoot> {
|
||||
let mut shadow = element.containing_shadow()?;
|
||||
loop {
|
||||
let host = shadow.host();
|
||||
let host_is_svg_use_element =
|
||||
host.is_svg_element() && host.local_name() == &*local_name!("use");
|
||||
if !host_is_svg_use_element {
|
||||
return Some(shadow);
|
||||
}
|
||||
debug_assert!(
|
||||
shadow.style_data().is_none(),
|
||||
"We allow no stylesheets in <svg:use> subtrees"
|
||||
);
|
||||
shadow = host.containing_shadow()?;
|
||||
}
|
||||
}
|
||||
|
||||
/// An object that we use with all the intermediate state needed for the
|
||||
/// cascade.
|
||||
///
|
||||
|
@ -213,43 +250,19 @@ where
|
|||
return;
|
||||
}
|
||||
|
||||
let mut current_containing_shadow = self.rule_hash_target.containing_shadow();
|
||||
while let Some(containing_shadow) = current_containing_shadow {
|
||||
let cascade_data = containing_shadow.style_data();
|
||||
let host = containing_shadow.host();
|
||||
if let Some(map) = cascade_data.and_then(|data| data.normal_rules(self.pseudo_element))
|
||||
{
|
||||
self.collect_rules_in_shadow_tree(host, map, CascadeLevel::SameTreeAuthorNormal);
|
||||
}
|
||||
let host_is_svg_use_element =
|
||||
host.is_svg_element() && host.local_name() == &*local_name!("use");
|
||||
if !host_is_svg_use_element {
|
||||
self.matches_document_author_rules = false;
|
||||
break;
|
||||
}
|
||||
let containing_shadow = containing_shadow_ignoring_svg_use(self.rule_hash_target);
|
||||
let containing_shadow = match containing_shadow {
|
||||
Some(s) => s,
|
||||
None => return,
|
||||
};
|
||||
|
||||
debug_assert!(
|
||||
cascade_data.is_none(),
|
||||
"We allow no stylesheets in <svg:use> subtrees"
|
||||
);
|
||||
self.matches_document_author_rules = false;
|
||||
|
||||
// NOTE(emilio): Hack so <svg:use> matches the rules of the
|
||||
// enclosing tree.
|
||||
//
|
||||
// This is not a problem for invalidation and that kind of stuff
|
||||
// because they still don't match rules based on elements
|
||||
// outside of the shadow tree, and because the <svg:use>
|
||||
// subtrees are immutable and recreated each time the source
|
||||
// tree changes.
|
||||
//
|
||||
// We historically allow cross-document <svg:use> to have these
|
||||
// rules applied, but I think that's not great. Gecko is the
|
||||
// only engine supporting that.
|
||||
//
|
||||
// See https://github.com/w3c/svgwg/issues/504 for the relevant
|
||||
// spec discussion.
|
||||
current_containing_shadow = host.containing_shadow();
|
||||
self.matches_document_author_rules = current_containing_shadow.is_none();
|
||||
let cascade_data = containing_shadow.style_data();
|
||||
let host = containing_shadow.host();
|
||||
if let Some(map) = cascade_data.and_then(|data| data.normal_rules(self.pseudo_element))
|
||||
{
|
||||
self.collect_rules_in_shadow_tree(host, map, CascadeLevel::SameTreeAuthorNormal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use crate::media_queries::Device;
|
|||
use crate::properties::{self, CascadeMode, ComputedValues};
|
||||
use crate::properties::{AnimationRules, PropertyDeclarationBlock};
|
||||
use crate::rule_cache::{RuleCache, RuleCacheConditions};
|
||||
use crate::rule_collector::RuleCollector;
|
||||
use crate::rule_collector::{RuleCollector, containing_shadow_ignoring_svg_use};
|
||||
use crate::rule_tree::{CascadeLevel, RuleTree, ShadowCascadeOrder, StrongRuleNode, StyleSource};
|
||||
use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
|
||||
use crate::selector_parser::{PerPseudoElementMap, PseudoElement, SelectorImpl, SnapshotMap};
|
||||
|
@ -1190,7 +1190,9 @@ impl Stylist {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(shadow) = element.containing_shadow() {
|
||||
// Use the same rules to look for the containing host as we do for rule
|
||||
// collection.
|
||||
if let Some(shadow) = containing_shadow_ignoring_svg_use(element) {
|
||||
if let Some(data) = shadow.style_data() {
|
||||
try_find_in!(data);
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[clip-filter-order.html]
|
||||
expected:
|
||||
if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
|
||||
if not debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
|
|
@ -1,61 +0,0 @@
|
|||
[historical.sub.xhtml]
|
||||
[The 'src' attribute of the 'iframe' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'href' attribute of the 'a' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'formaction' attribute of the 'button' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'input' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'data' attribute of the 'object' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'href' attribute of the 'area' element]
|
||||
expected: FAIL
|
||||
|
||||
[Change the base URL must not effect the descendant elements]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'audio' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'script' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'img' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'track' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'cite' attribute of the 'q' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'cite' attribute of the 'ins' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'href' attribute of the 'link' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'cite' attribute of the 'del' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'action' attribute of the 'form' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'embed' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'source' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'src' attribute of the 'video' element]
|
||||
expected: FAIL
|
||||
|
||||
[The 'cite' attribute of the 'blockquote' element]
|
||||
expected: FAIL
|
||||
|
|
@ -9,25 +9,23 @@
|
|||
|
||||
// Run captureStream() on different videos, and assert data is flowing.
|
||||
|
||||
var makeAsyncTest = function(filename) {
|
||||
async_test(function(test) {
|
||||
var video = document.createElement('video');
|
||||
function makeAsyncTest(filename) {
|
||||
promise_test(async test => {
|
||||
const video = document.createElement('video');
|
||||
video.src = "/media/" + filename;
|
||||
video.onerror = this.unreached_func("<video> error");
|
||||
video.play();
|
||||
|
||||
var stream = video.captureStream();
|
||||
const stream = video.captureStream();
|
||||
|
||||
// onactive event is marked for deprecation (https://crbug.com/649328)
|
||||
stream.onactive = this.step_func_done(function() {
|
||||
var recorder = new MediaRecorder(stream);
|
||||
recorder.ondataavailable = test.step_func_done(function(event) {
|
||||
assert_true(event.data.size > 0, 'Recorded data size should be > 0');
|
||||
});
|
||||
recorder.start(0);
|
||||
});
|
||||
}), "<video>.captureStream() and assert data flows.";
|
||||
};
|
||||
await new Promise(r => stream.onaddtrack = r);
|
||||
const recorder = new MediaRecorder(stream);
|
||||
|
||||
recorder.start(0);
|
||||
const {data} = await new Promise(r => recorder.ondataavailable = r);
|
||||
assert_true(data.size > 0, 'Recorded data size should be > 0');
|
||||
}), "<video>.captureStream() and assert data flows.";
|
||||
}
|
||||
|
||||
generate_tests(makeAsyncTest, [
|
||||
[ "video-only", "test-v-128k-320x240-24fps-8kfr.webm" ],
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Test Reference</title>
|
||||
<svg width="100" height="100" viewBox="0 0 100 100">
|
||||
<rect width="100%" height="100%" fill="lime" />
|
||||
</svg>
|
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Test: Keyframe animations from the document match in use elements</title>
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1513920">
|
||||
<link rel="match" href="use-keyframes-ref.html">
|
||||
<style>
|
||||
@keyframes animationname {
|
||||
from { fill: lime; }
|
||||
to { fill: lime; }
|
||||
}
|
||||
</style>
|
||||
<svg width="100" height="100" viewBox="0 0 100 100">
|
||||
<symbol id="symbol">
|
||||
<rect width="100%" height="100%" fill="red" style="animation: animationname 1s infinite;" />
|
||||
</symbol>
|
||||
<use href="#symbol" />
|
||||
</svg>
|
|
@ -52,7 +52,7 @@ either hg or git. To enable a pre-push hg hook, add the following to hgrc:
|
|||
.. parsed-literal::
|
||||
|
||||
[hooks]
|
||||
pre-push.lint = python:/path/to/gecko/tools/lint/hooks.py:hg
|
||||
pre-push.lint = python:./tools/lint/hooks.py:hg
|
||||
|
||||
|
||||
To enable a pre-commit hg hook, add the following to hgrc:
|
||||
|
@ -60,7 +60,7 @@ To enable a pre-commit hg hook, add the following to hgrc:
|
|||
.. parsed-literal::
|
||||
|
||||
[hooks]
|
||||
pretxncommit.lint = python:/path/to/gecko/tools/lint/hooks.py:hg
|
||||
pretxncommit.lint = python:./tools/lint/hooks.py:hg
|
||||
|
||||
|
||||
To enable a pre-push git hook, run the following command:
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче