mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 14:55:44 -04:00
The great layout servo rust update
This commit is contained in:
parent
f6d16ef724
commit
7b3dbae42d
@ -295,14 +295,11 @@ module.exports = {
|
||||
],
|
||||
"rules": {
|
||||
"consistent-return": "off",
|
||||
"dot-notation": "off",
|
||||
"mozilla/avoid-removeChild": "off",
|
||||
"mozilla/consistent-if-bracing": "off",
|
||||
"mozilla/no-arbitrary-setTimeout": "off",
|
||||
"mozilla/no-compare-against-boolean-literals": "off",
|
||||
"mozilla/no-define-cc-etc": "off",
|
||||
"mozilla/no-useless-parameters": "off",
|
||||
"mozilla/no-useless-run-test": "off",
|
||||
"mozilla/reject-importGlobalProperties": "off",
|
||||
"mozilla/use-cc-etc": "off",
|
||||
"mozilla/use-chromeutils-generateqi": "off",
|
||||
@ -318,7 +315,6 @@ module.exports = {
|
||||
"no-else-return": "off",
|
||||
"no-empty": "off",
|
||||
"no-eval": "off",
|
||||
"no-extra-boolean-cast": "off",
|
||||
"no-func-assign": "off",
|
||||
"no-global-assign": "off",
|
||||
"no-implied-eval": "off",
|
||||
@ -338,7 +334,6 @@ module.exports = {
|
||||
"no-shadow-restricted-names": "off",
|
||||
"no-sparse-arrays": "off",
|
||||
"no-throw-literal": "off",
|
||||
"no-unneeded-ternary": "off",
|
||||
"no-unreachable": "off",
|
||||
"no-unsanitized/method": "off",
|
||||
"no-unsanitized/property": "off",
|
||||
|
517
Cargo.lock
generated
517
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -605,8 +605,8 @@ TextAttrsMgr::TextDecorValue::TextDecorValue(nsIFrame* aFrame) {
|
||||
mStyle = textReset->mTextDecorationStyle;
|
||||
mColor = textReset->mTextDecorationColor.CalcColor(aFrame);
|
||||
mLine =
|
||||
textReset->mTextDecorationLine & (StyleTextDecorationLine_UNDERLINE |
|
||||
StyleTextDecorationLine_LINE_THROUGH);
|
||||
textReset->mTextDecorationLine & (StyleTextDecorationLine::UNDERLINE |
|
||||
StyleTextDecorationLine::LINE_THROUGH);
|
||||
}
|
||||
|
||||
TextAttrsMgr::TextDecorTextAttr::TextDecorTextAttr(nsIFrame* aRootFrame,
|
||||
|
@ -357,7 +357,7 @@ class TextAttrsMgr {
|
||||
public:
|
||||
TextDecorValue()
|
||||
: mColor{0},
|
||||
mLine{StyleTextDecorationLine_NONE},
|
||||
mLine{StyleTextDecorationLine::NONE},
|
||||
mStyle{NS_STYLE_TEXT_DECORATION_STYLE_NONE} {}
|
||||
explicit TextDecorValue(nsIFrame* aFrame);
|
||||
|
||||
@ -366,10 +366,10 @@ class TextAttrsMgr {
|
||||
|
||||
bool IsDefined() const { return IsUnderline() || IsLineThrough(); }
|
||||
bool IsUnderline() const {
|
||||
return bool(mLine & mozilla::StyleTextDecorationLine_UNDERLINE);
|
||||
return bool(mLine & mozilla::StyleTextDecorationLine::UNDERLINE);
|
||||
}
|
||||
bool IsLineThrough() const {
|
||||
return bool(mLine & mozilla::StyleTextDecorationLine_LINE_THROUGH);
|
||||
return bool(mLine & mozilla::StyleTextDecorationLine::LINE_THROUGH);
|
||||
}
|
||||
|
||||
bool operator==(const TextDecorValue& aValue) {
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs_ui.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2D.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
@ -240,7 +241,7 @@ KeyBinding Accessible::AccessKey() const {
|
||||
if (!key) return KeyBinding();
|
||||
|
||||
// Get modifier mask. Use ui.key.generalAccessKey (unless it is -1).
|
||||
switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
|
||||
switch (StaticPrefs::ui_key_generalAccessKey()) {
|
||||
case -1:
|
||||
break;
|
||||
case dom::KeyboardEvent_Binding::DOM_VK_SHIFT:
|
||||
@ -266,10 +267,12 @@ KeyBinding Accessible::AccessKey() const {
|
||||
int32_t modifierMask = 0;
|
||||
switch (treeItem->ItemType()) {
|
||||
case nsIDocShellTreeItem::typeChrome:
|
||||
rv = Preferences::GetInt("ui.key.chromeAccess", &modifierMask);
|
||||
modifierMask = StaticPrefs::ui_key_chromeAccess();
|
||||
rv = NS_OK;
|
||||
break;
|
||||
case nsIDocShellTreeItem::typeContent:
|
||||
rv = Preferences::GetInt("ui.key.contentAccess", &modifierMask);
|
||||
modifierMask = StaticPrefs::ui_key_contentAccess();
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1187,11 +1187,19 @@ Accessible* DocAccessible::GetAccessibleOrDescendant(nsINode* aNode) const {
|
||||
Accessible* acc = GetAccessible(aNode);
|
||||
if (acc) return acc;
|
||||
|
||||
if (aNode == mContent || aNode == mDocumentNode->GetRootElement()) {
|
||||
// If the node is the doc's body or root element, return the doc accessible.
|
||||
return const_cast<DocAccessible*>(this);
|
||||
}
|
||||
|
||||
acc = GetContainerAccessible(aNode);
|
||||
if (acc) {
|
||||
uint32_t childCnt = acc->ChildCount();
|
||||
// We access the `mChildren` array directly so that we don't access
|
||||
// lazily created children in places like `XULTreeAccessible` and
|
||||
// `XULTreeGridAccessible`.
|
||||
uint32_t childCnt = acc->mChildren.Length();
|
||||
for (uint32_t idx = 0; idx < childCnt; idx++) {
|
||||
Accessible* child = acc->GetChildAt(idx);
|
||||
Accessible* child = acc->mChildren.ElementAt(idx);
|
||||
for (nsIContent* elm = child->GetContent();
|
||||
elm && elm != acc->GetContent();
|
||||
elm = elm->GetFlattenedTreeParent()) {
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "mozilla/TextEditor.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLBRElement.h"
|
||||
#include "mozilla/dom/HTMLHeadingElement.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "gfxSkipChars.h"
|
||||
#include <algorithm>
|
||||
@ -882,13 +883,9 @@ HyperTextAccessible::DefaultTextAttributes() {
|
||||
}
|
||||
|
||||
int32_t HyperTextAccessible::GetLevelInternal() {
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::h1)) return 1;
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::h2)) return 2;
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::h3)) return 3;
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::h4)) return 4;
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::h5)) return 5;
|
||||
if (mContent->IsHTMLElement(nsGkAtoms::h6)) return 6;
|
||||
|
||||
if (auto* heading = dom::HTMLHeadingElement::FromNode(mContent)) {
|
||||
return heading->AccessibilityLevel();
|
||||
}
|
||||
return AccessibleWrap::GetLevelInternal();
|
||||
}
|
||||
|
||||
|
@ -569,47 +569,23 @@
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// HTML:h1, HTML:h2, HTML:h3, HTML:h4, HTML:h5, HTML:h6
|
||||
|
||||
obj = {
|
||||
role: ROLE_HEADING,
|
||||
attributes: { "level": "1" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
|
||||
};
|
||||
testElm("h1", obj);
|
||||
function headingWithLevel(i) {
|
||||
return {
|
||||
role: ROLE_HEADING,
|
||||
attributes: { "level": i.toString() },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
|
||||
};
|
||||
}
|
||||
|
||||
obj = {
|
||||
role: ROLE_HEADING,
|
||||
attributes: { "level": "2" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
|
||||
};
|
||||
testElm("h2", obj);
|
||||
|
||||
obj = {
|
||||
role: ROLE_HEADING,
|
||||
attributes: { "level": "3" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
|
||||
};
|
||||
testElm("h3", obj);
|
||||
|
||||
obj = {
|
||||
role: ROLE_HEADING,
|
||||
attributes: { "level": "4" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
|
||||
};
|
||||
testElm("h4", obj);
|
||||
|
||||
obj = {
|
||||
role: ROLE_HEADING,
|
||||
attributes: { "level": "5" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
|
||||
};
|
||||
testElm("h5", obj);
|
||||
|
||||
obj = {
|
||||
role: ROLE_HEADING,
|
||||
attributes: { "level": "6" },
|
||||
interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ],
|
||||
};
|
||||
testElm("h6", obj);
|
||||
const headingChangesEnabled = SpecialPowers.getBoolPref("accessibility.heading-element-level-changes.enabled");
|
||||
for (let level = 1; level <= 6; ++level) {
|
||||
testElm("h" + level, headingWithLevel(level));
|
||||
let expectedLevelWithAncestors = headingChangesEnabled ? level + 1 : level;
|
||||
for (const ancestor of ["section", "article", "aside", "nav"]) {
|
||||
testElm("h" + level + "_in_" + ancestor, headingWithLevel(level == 1 ? expectedLevelWithAncestors : level));
|
||||
testElm("h" + level + "_in_" + ancestor + "_in_hgroup", headingWithLevel(expectedLevelWithAncestors));
|
||||
}
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// HTML:header
|
||||
@ -1596,15 +1572,71 @@
|
||||
<header id="header">A logo</header>
|
||||
<article>
|
||||
<header id="header_in_article">Not logo</header>
|
||||
<h1 id="h1_in_article">heading1</h1>
|
||||
<h2 id="h2_in_article">heading2</h2>
|
||||
<h3 id="h3_in_article">heading3</h3>
|
||||
<h4 id="h4_in_article">heading4</h4>
|
||||
<h5 id="h5_in_article">heading5</h5>
|
||||
<h6 id="h6_in_article">heading6</h6>
|
||||
<hgroup>
|
||||
<h1 id="h1_in_article_in_hgroup">heading1</h1>
|
||||
<h2 id="h2_in_article_in_hgroup">heading2</h2>
|
||||
<h3 id="h3_in_article_in_hgroup">heading3</h3>
|
||||
<h4 id="h4_in_article_in_hgroup">heading4</h4>
|
||||
<h5 id="h5_in_article_in_hgroup">heading5</h5>
|
||||
<h6 id="h6_in_article_in_hgroup">heading6</h6>
|
||||
</hgroup>
|
||||
</article>
|
||||
<aside>
|
||||
<header id="header_in_aside">Not logo</header>
|
||||
<h1 id="h1_in_aside">heading1</h1>
|
||||
<h2 id="h2_in_aside">heading2</h2>
|
||||
<h3 id="h3_in_aside">heading3</h3>
|
||||
<h4 id="h4_in_aside">heading4</h4>
|
||||
<h5 id="h5_in_aside">heading5</h5>
|
||||
<h6 id="h6_in_aside">heading6</h6>
|
||||
<hgroup>
|
||||
<h1 id="h1_in_aside_in_hgroup">heading1</h1>
|
||||
<h2 id="h2_in_aside_in_hgroup">heading2</h2>
|
||||
<h3 id="h3_in_aside_in_hgroup">heading3</h3>
|
||||
<h4 id="h4_in_aside_in_hgroup">heading4</h4>
|
||||
<h5 id="h5_in_aside_in_hgroup">heading5</h5>
|
||||
<h6 id="h6_in_aside_in_hgroup">heading6</h6>
|
||||
</hgroup>
|
||||
</aside>
|
||||
<nav>
|
||||
<header id="header_in_nav">Not logo</header>
|
||||
<h1 id="h1_in_nav">heading1</h1>
|
||||
<h2 id="h2_in_nav">heading2</h2>
|
||||
<h3 id="h3_in_nav">heading3</h3>
|
||||
<h4 id="h4_in_nav">heading4</h4>
|
||||
<h5 id="h5_in_nav">heading5</h5>
|
||||
<h6 id="h6_in_nav">heading6</h6>
|
||||
<hgroup>
|
||||
<h1 id="h1_in_nav_in_hgroup">heading1</h1>
|
||||
<h2 id="h2_in_nav_in_hgroup">heading2</h2>
|
||||
<h3 id="h3_in_nav_in_hgroup">heading3</h3>
|
||||
<h4 id="h4_in_nav_in_hgroup">heading4</h4>
|
||||
<h5 id="h5_in_nav_in_hgroup">heading5</h5>
|
||||
<h6 id="h6_in_nav_in_hgroup">heading6</h6>
|
||||
</hgroup>
|
||||
</nav>
|
||||
<section>
|
||||
<header id="header_in_section">Not logo</header>
|
||||
<h1 id="h1_in_section">heading1</h1>
|
||||
<h2 id="h2_in_section">heading2</h2>
|
||||
<h3 id="h3_in_section">heading3</h3>
|
||||
<h4 id="h4_in_section">heading4</h4>
|
||||
<h5 id="h5_in_section">heading5</h5>
|
||||
<h6 id="h6_in_section">heading6</h6>
|
||||
<hgroup>
|
||||
<h1 id="h1_in_section_in_hgroup">heading1</h1>
|
||||
<h2 id="h2_in_section_in_hgroup">heading2</h2>
|
||||
<h3 id="h3_in_section_in_hgroup">heading3</h3>
|
||||
<h4 id="h4_in_section_in_hgroup">heading4</h4>
|
||||
<h5 id="h5_in_section_in_hgroup">heading5</h5>
|
||||
<h6 id="h6_in_section_in_hgroup">heading6</h6>
|
||||
</hgroup>
|
||||
</section>
|
||||
<blockquote>
|
||||
<header id="header_in_blockquote">Not logo</header>
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
zoomDocument(document, 2.0);
|
||||
|
||||
document.body.offsetTop; // getBounds doesn't flush layout on its own, looks like.
|
||||
|
||||
[x, y, width, height] = getBounds(textNode);
|
||||
testOffsetAtPoint(hyperText, x + width / 2, y + height / 2,
|
||||
COORDTYPE_SCREEN_RELATIVE,
|
||||
|
@ -19,7 +19,7 @@
|
||||
// __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
|
||||
var IDs = [ "i1", "d1", "e1", "t1" ];
|
||||
var IDs = [ "i1", "d1", "d1wrap", "e1", "t1" ];
|
||||
|
||||
testCharacterCount(IDs, 15);
|
||||
|
||||
@ -96,6 +96,7 @@
|
||||
|
||||
<input id="i1" value="hello my friend"/>
|
||||
<div id="d1">hello my friend</div>
|
||||
<div id="d1wrap" style="word-wrap:break-word; width:1px">hello my friend</div>
|
||||
<div id="e1" contenteditable="true">hello my friend</div>
|
||||
<textarea id="t1">hello my friend</textarea>
|
||||
|
||||
|
@ -167,7 +167,6 @@ pref("browser.uitour.surveyDuration", 7200);
|
||||
pref("keyword.enabled", false);
|
||||
pref("browser.fixup.domainwhitelist.localhost", true);
|
||||
|
||||
pref("general.smoothScroll", true);
|
||||
#ifdef UNIX_BUT_NOT_MAC
|
||||
pref("general.autoScroll", false);
|
||||
#else
|
||||
|
@ -22,7 +22,7 @@ skip-if = (debug && os == "win") || os == "mac" # bug 1393761, macosx1014 due to
|
||||
[browser_devices_get_user_media_paused.js]
|
||||
skip-if = (os == "win" && !debug) || (os =="linux" && !debug && bits == 64) || os == 'mac' # macosx1014 due to 1567735, Bug 1440900
|
||||
[browser_devices_get_user_media_screen.js]
|
||||
skip-if = (os == 'linux') || os == 'mac' # Bug 1503991, macosx1014 due to 1568135
|
||||
skip-if = (os == 'linux') || (os == 'win' && debug && webrender) || os == 'mac' # Bug 1503991, macosx1014 due to 1568135, bug 1553579 for WR
|
||||
[browser_devices_get_user_media_tear_off_tab.js]
|
||||
[browser_devices_get_user_media_unprompted_access.js]
|
||||
[browser_devices_get_user_media_unprompted_access_in_frame.js]
|
||||
|
@ -1349,7 +1349,6 @@ this.tabs = class extends ExtensionAPI {
|
||||
printSettings.printSilent = true;
|
||||
printSettings.showPrintProgress = false;
|
||||
|
||||
printSettings.printFrameType = Ci.nsIPrintSettings.kFramesAsIs;
|
||||
printSettings.outputFormat =
|
||||
Ci.nsIPrintSettings.kOutputFormatPDF;
|
||||
|
||||
|
@ -82,6 +82,7 @@ skip-if = (verify && (os == 'linux' || os == 'mac'))
|
||||
[browser_ext_commands_execute_sidebar_action.js]
|
||||
[browser_ext_commands_getAll.js]
|
||||
[browser_ext_commands_onCommand.js]
|
||||
skip-if = (webrender && debug) # bug 1553577
|
||||
[browser_ext_commands_update.js]
|
||||
[browser_ext_connect_and_move_tabs.js]
|
||||
[browser_ext_contentscript_connect.js]
|
||||
|
@ -33,14 +33,14 @@ add_task(async function testPageActionPopupResize() {
|
||||
|
||||
browser = await awaitExtensionPanel(extension);
|
||||
|
||||
async function checkSize(expected) {
|
||||
async function checkSize(height, width) {
|
||||
let dims = await promiseContentDimensions(browser);
|
||||
let { body, root } = dims;
|
||||
|
||||
is(
|
||||
dims.window.innerHeight,
|
||||
expected,
|
||||
`Panel window should be ${expected}px tall`
|
||||
height,
|
||||
`Panel window should be ${height}px tall`
|
||||
);
|
||||
is(
|
||||
body.clientHeight,
|
||||
@ -53,16 +53,20 @@ add_task(async function testPageActionPopupResize() {
|
||||
"Panel root should be tall enough to fit its contents"
|
||||
);
|
||||
|
||||
// Tolerate if it is 1px too wide, as that may happen with the current resizing method.
|
||||
ok(
|
||||
Math.abs(dims.window.innerWidth - expected) <= 1,
|
||||
`Panel window should be ${expected}px wide`
|
||||
);
|
||||
is(
|
||||
body.clientWidth,
|
||||
body.scrollWidth,
|
||||
"Panel body should be wide enough to fit its contents"
|
||||
);
|
||||
if (width) {
|
||||
is(
|
||||
body.clientWidth,
|
||||
body.scrollWidth,
|
||||
"Panel body should be wide enough to fit its contents"
|
||||
);
|
||||
|
||||
// Tolerate if it is 1px too wide, as that may happen with the current
|
||||
// resizing method.
|
||||
ok(
|
||||
Math.abs(dims.window.innerWidth - width) <= 1,
|
||||
`Panel window should be ${width}px wide`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function setSize(size) {
|
||||
@ -71,11 +75,17 @@ add_task(async function testPageActionPopupResize() {
|
||||
elem.style.width = `${size}px`;
|
||||
}
|
||||
|
||||
function setHeight(height) {
|
||||
content.document.body.style.overflow = "hidden";
|
||||
let elem = content.document.body.firstElementChild;
|
||||
elem.style.height = `${height}px`;
|
||||
}
|
||||
|
||||
let sizes = [200, 400, 300];
|
||||
|
||||
for (let size of sizes) {
|
||||
await alterContent(browser, setSize, size);
|
||||
await checkSize(size);
|
||||
await checkSize(size, size);
|
||||
}
|
||||
|
||||
let dims = await alterContent(browser, setSize, 1400);
|
||||
@ -95,6 +105,11 @@ add_task(async function testPageActionPopupResize() {
|
||||
);
|
||||
is(root.scrollHeight, 1400, "Panel root scroll height");
|
||||
|
||||
for (let size of sizes) {
|
||||
await alterContent(browser, setHeight, size);
|
||||
await checkSize(size, null);
|
||||
}
|
||||
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
|
@ -13,7 +13,7 @@ option(env='CBINDGEN', nargs=1, when=cbindgen_is_needed,
|
||||
def check_cbindgen_version(cbindgen, fatal=False):
|
||||
log.debug("trying cbindgen: %s" % cbindgen)
|
||||
|
||||
cbindgen_min_version = Version('0.9.1')
|
||||
cbindgen_min_version = Version('0.11.1')
|
||||
|
||||
# cbindgen x.y.z
|
||||
version = Version(check_cmd_output(cbindgen, '--version').strip().split(" ")[1])
|
||||
|
@ -81,6 +81,8 @@ skip-if = os == "mac" # Bug 1569508
|
||||
fail-if = true # Bug 1547783
|
||||
[browser_user_agent_input.js]
|
||||
[browser_viewport_basics.js]
|
||||
[browser_viewport_changed_meta.js]
|
||||
[browser_viewport_resizing_after_reload.js]
|
||||
[browser_viewport_resizing_fixed_width.js]
|
||||
[browser_viewport_resizing_fixed_width_and_zoom.js]
|
||||
[browser_viewport_resizing_minimum_scale.js]
|
||||
|
@ -0,0 +1,129 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that resolution is as expected when the viewport tag is changed.
|
||||
// The page content is a 400 x 400 div in a 200 x 200 viewport. Initially,
|
||||
// the viewport width is set to 800 at initial-scale 1, but then the tag
|
||||
// content is changed. This triggers various rescale operations that will
|
||||
// changge the resolution of the page after reflow.
|
||||
|
||||
// Chrome handles many of these cases differently. The Chrome results are
|
||||
// included as TODOs, but labelled as "res_chrome" to indicate that the
|
||||
// goal is not necessarily to match an agreed-upon standard, but to
|
||||
// achieve web compatability through changing either Firefox or Chrome
|
||||
// behavior.
|
||||
|
||||
info("--- Starting viewport test output ---");
|
||||
|
||||
const WIDTH = 200;
|
||||
const HEIGHT = 200;
|
||||
const INITIAL_CONTENT = "width=800, initial-scale=1";
|
||||
const INITIAL_RES_TARGET = 1.0;
|
||||
const TESTS = [
|
||||
// This checks that when the replaced content matches the original content,
|
||||
// we get the same values as the original values.
|
||||
{ content: INITIAL_CONTENT, res_target: INITIAL_RES_TARGET },
|
||||
|
||||
// Section 1: Check the case of a viewport shrinking with the display width
|
||||
// staying the same. In this case, the shrink will fit the max of the 400px
|
||||
// content width and the viewport width into the 200px display area.
|
||||
{ content: "width=200", res_target: 0.5 }, // fitting 400px content
|
||||
{ content: "width=400", res_target: 0.5 }, // fitting 400px content/viewport
|
||||
{ content: "width=500", res_target: 0.4 }, // fitting 500px viewport
|
||||
|
||||
// Section 2: Same as Section 1, but adds user-scalable=no. The expected
|
||||
// results are similar to Section 1, but we ignore the content size and only
|
||||
// adjust resolution to make the viewport fit into the display area.
|
||||
{ content: "width=200, user-scalable=no", res_target: 1.0 },
|
||||
{ content: "width=400, user-scalable=no", res_target: 0.5 },
|
||||
{ content: "width=500, user-scalable=no", res_target: 0.4 },
|
||||
|
||||
// Section 3: Same as Section 1, but adds initial-scale=1. Initial-scale
|
||||
// prevents content shrink in Firefox, so the viewport is scaled based on its
|
||||
// changing size relative to the display area. In this case, the resolution
|
||||
// is increased to maintain the proportional amount of the previously visible
|
||||
// content. With the initial conditions, the display area was showing 1/4 of
|
||||
// the content at 0.25x resolution. As the viewport width is shrunk, the
|
||||
// resolution will increase to ensure that only 1/4 of the content is visible.
|
||||
// Essentially, the new viewport width times the resolution will equal 800px,
|
||||
// the original viewport width times resolution.
|
||||
//
|
||||
// Chrome treats the initial-scale=1 as inviolable and sets resolution to 1.0.
|
||||
{ content: "width=200, initial-scale=1", res_target: 4.0, res_chrome: 1.0 },
|
||||
{ content: "width=400, initial-scale=1", res_target: 2.0, res_chrome: 1.0 },
|
||||
{ content: "width=500, initial-scale=1", res_target: 1.6, res_chrome: 1.0 },
|
||||
|
||||
// Section 4: Same as Section 3, but adds user-scalable=no. The combination
|
||||
// of this and initial-scale=1 prevents the scaling-up of the resolution to
|
||||
// keep the proportional amount of the previously visible content.
|
||||
{ content: "width=200, initial-scale=1, user-scalable=no", res_target: 1.0 },
|
||||
{ content: "width=400, initial-scale=1, user-scalable=no", res_target: 1.0 },
|
||||
{ content: "width=500, initial-scale=1, user-scalable=no", res_target: 1.0 },
|
||||
];
|
||||
|
||||
const TEST_URL =
|
||||
`data:text/html;charset=utf-8,` +
|
||||
`<html><head><meta name="viewport" content="${INITIAL_CONTENT}"></head>` +
|
||||
`<body style="margin:0">` +
|
||||
`<div id="box" style="width:400px;height:400px;background-color:green">` +
|
||||
`Initial</div></body></html>`;
|
||||
|
||||
addRDMTask(
|
||||
TEST_URL,
|
||||
async function({ ui, manager, browser }) {
|
||||
await setViewportSize(ui, manager, WIDTH, HEIGHT);
|
||||
await setTouchAndMetaViewportSupport(ui, true);
|
||||
|
||||
// Check initial resolution value.
|
||||
const initial_resolution = await spawnViewportTask(ui, {}, () => {
|
||||
return content.windowUtils.getResolution();
|
||||
});
|
||||
|
||||
is(
|
||||
initial_resolution.toFixed(2),
|
||||
INITIAL_RES_TARGET.toFixed(2),
|
||||
`Initial resolution is as expected.`
|
||||
);
|
||||
|
||||
for (const test of TESTS) {
|
||||
const { content: content, res_target, res_chrome } = test;
|
||||
|
||||
await spawnViewportTask(ui, { content }, args => {
|
||||
const box = content.document.getElementById("box");
|
||||
box.textContent = args.content;
|
||||
|
||||
const meta = content.document.getElementsByTagName("meta")[0];
|
||||
info(`Changing meta viewport content to "${args.content}".`);
|
||||
meta.content = args.content;
|
||||
});
|
||||
|
||||
await promiseContentReflow(ui);
|
||||
|
||||
const resolution = await spawnViewportTask(ui, {}, () => {
|
||||
return content.windowUtils.getResolution();
|
||||
});
|
||||
|
||||
is(
|
||||
resolution.toFixed(2),
|
||||
res_target.toFixed(2),
|
||||
`Replaced meta viewport content "${content}" resolution is as expected.`
|
||||
);
|
||||
|
||||
if (typeof res_chrome !== "undefined") {
|
||||
todo_is(
|
||||
resolution.toFixed(2),
|
||||
res_chrome.toFixed(2),
|
||||
`Replaced meta viewport content "${content}" resolution matches Chrome resolution.`
|
||||
);
|
||||
}
|
||||
|
||||
// Reload to prepare for next test.
|
||||
const reload = waitForViewportLoad(ui);
|
||||
browser.reload();
|
||||
await reload;
|
||||
}
|
||||
},
|
||||
{ usingBrowserUI: true }
|
||||
);
|
@ -0,0 +1,101 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test viewport resizing, with and without meta viewport support.
|
||||
|
||||
const TEST_URL =
|
||||
"data:text/html;charset=utf-8," +
|
||||
'<head><meta name="viewport" content="width=device-width"/></head>' +
|
||||
'<body style="margin:0px;min-width:600px">' +
|
||||
'<div style="width:100%;height:100px;background-color:black"></div>' +
|
||||
'<div style="width:100%;height:1100px;background-color:lightblue"></div>' +
|
||||
"</body>";
|
||||
|
||||
addRDMTask(TEST_URL, async function({ ui, manager }) {
|
||||
// Turn on the pref that allows meta viewport support.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["devtools.responsive.metaViewport.enabled", true]],
|
||||
});
|
||||
|
||||
const store = ui.toolWindow.store;
|
||||
|
||||
// Wait until the viewport has been added.
|
||||
await waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
info("--- Starting viewport test output ---");
|
||||
|
||||
// We're going to take a 300,600 viewport (before), reload it,
|
||||
// then resize it to 600,300 (after) and then resize it back.
|
||||
// At the before and after points, we'll measure zoom and the
|
||||
// layout viewport width and height.
|
||||
const expected = [
|
||||
{
|
||||
metaSupport: false,
|
||||
before: [1.0, 300, 600],
|
||||
after: [1.0, 600, 300],
|
||||
},
|
||||
{
|
||||
metaSupport: true,
|
||||
before: [0.5, 600, 1200],
|
||||
after: [1.0, 600, 300],
|
||||
},
|
||||
];
|
||||
|
||||
for (const e of expected) {
|
||||
const b = e.before;
|
||||
const a = e.after;
|
||||
|
||||
const message = "Meta Viewport " + (e.metaSupport ? "ON" : "OFF");
|
||||
|
||||
// Ensure meta viewport is set.
|
||||
info(message + " setting meta viewport support.");
|
||||
await setTouchAndMetaViewportSupport(ui, e.metaSupport);
|
||||
|
||||
// Get to the initial size and check values.
|
||||
await setViewportSize(ui, manager, 300, 600);
|
||||
await testViewportZoomWidthAndHeight(
|
||||
message + " before resize",
|
||||
ui,
|
||||
b[0],
|
||||
b[1],
|
||||
b[2]
|
||||
);
|
||||
|
||||
// Force a reload.
|
||||
const reload = waitForViewportLoad(ui);
|
||||
const browser = ui.getViewportBrowser();
|
||||
browser.reload();
|
||||
await reload;
|
||||
|
||||
// Check initial values again.
|
||||
await testViewportZoomWidthAndHeight(
|
||||
message + " after reload",
|
||||
ui,
|
||||
b[0],
|
||||
b[1],
|
||||
b[2]
|
||||
);
|
||||
|
||||
// Move to the smaller size.
|
||||
await setViewportSize(ui, manager, 600, 300);
|
||||
await testViewportZoomWidthAndHeight(
|
||||
message + " after resize",
|
||||
ui,
|
||||
a[0],
|
||||
a[1],
|
||||
a[2]
|
||||
);
|
||||
|
||||
// Go back to the initial size and check again.
|
||||
await setViewportSize(ui, manager, 300, 600);
|
||||
await testViewportZoomWidthAndHeight(
|
||||
message + " return to initial size",
|
||||
ui,
|
||||
b[0],
|
||||
b[1],
|
||||
b[2]
|
||||
);
|
||||
}
|
||||
});
|
@ -156,8 +156,11 @@ function addRDMTask(url, task) {
|
||||
});
|
||||
}
|
||||
|
||||
function spawnViewportTask(ui, args, task) {
|
||||
return ContentTask.spawn(ui.getViewportBrowser(), args, task);
|
||||
async function spawnViewportTask(ui, args, task) {
|
||||
// Await a reflow after the task.
|
||||
const result = await ContentTask.spawn(ui.getViewportBrowser(), args, task);
|
||||
await promiseContentReflow(ui);
|
||||
return result;
|
||||
}
|
||||
|
||||
function waitForFrameLoad(ui, targetURL) {
|
||||
@ -235,16 +238,7 @@ var setViewportSize = async function(ui, manager, width, height) {
|
||||
// ensures that reflow of the viewport has completed.
|
||||
var setViewportSizeAndAwaitReflow = async function(ui, manager, width, height) {
|
||||
await setViewportSize(ui, manager, width, height);
|
||||
const reflowed = ContentTask.spawn(
|
||||
ui.getViewportBrowser(),
|
||||
{},
|
||||
async function() {
|
||||
return new Promise(resolve => {
|
||||
content.requestAnimationFrame(resolve);
|
||||
});
|
||||
}
|
||||
);
|
||||
await reflowed;
|
||||
await promiseContentReflow(ui);
|
||||
};
|
||||
|
||||
function getViewportDevicePixelRatio(ui) {
|
||||
@ -707,6 +701,7 @@ async function setTouchAndMetaViewportSupport(ui, value) {
|
||||
const browser = ui.getViewportBrowser();
|
||||
browser.reload();
|
||||
await reload;
|
||||
await promiseContentReflow(ui);
|
||||
}
|
||||
return reloadNeeded;
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"-moz-text-size-adjust",
|
||||
"-webkit-text-stroke-width",
|
||||
"text-transform",
|
||||
"text-underline-position",
|
||||
"touch-action",
|
||||
"transform-box",
|
||||
"transform-style",
|
||||
@ -219,15 +220,12 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"padding-block-start",
|
||||
"padding-inline-end",
|
||||
"padding-inline-start",
|
||||
"rotate",
|
||||
"scale",
|
||||
"-moz-script-level",
|
||||
"-moz-top-layer",
|
||||
"transition-delay",
|
||||
"transition-duration",
|
||||
"transition-property",
|
||||
"transition-timing-function",
|
||||
"translate",
|
||||
"-moz-window-shadow",
|
||||
]),
|
||||
],
|
||||
@ -287,10 +285,13 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"offset-rotate",
|
||||
"order",
|
||||
"perspective-origin",
|
||||
"rotate",
|
||||
"scale",
|
||||
"shape-outside",
|
||||
"stroke-dasharray",
|
||||
"transform",
|
||||
"transform-origin",
|
||||
"translate",
|
||||
"-moz-window-transform",
|
||||
"-moz-window-transform-origin",
|
||||
"-webkit-line-clamp",
|
||||
@ -310,6 +311,8 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"bottom",
|
||||
"column-gap",
|
||||
"column-width",
|
||||
"cx",
|
||||
"cy",
|
||||
"flex-basis",
|
||||
"height",
|
||||
"left",
|
||||
@ -333,6 +336,9 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"padding-right",
|
||||
"padding-top",
|
||||
"perspective",
|
||||
"r",
|
||||
"rx",
|
||||
"ry",
|
||||
"right",
|
||||
"row-gap",
|
||||
"scroll-padding-block-start",
|
||||
@ -362,6 +368,8 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"vertical-align",
|
||||
"width",
|
||||
"word-spacing",
|
||||
"x",
|
||||
"y",
|
||||
"z-index",
|
||||
]),
|
||||
],
|
||||
|
@ -97,13 +97,13 @@ function getDocShellChromeEventHandler(docShell) {
|
||||
}
|
||||
|
||||
function getChildDocShells(parentDocShell) {
|
||||
const docShellsEnum = parentDocShell.getDocShellEnumerator(
|
||||
const allDocShells = parentDocShell.getAllDocShellsInSubtree(
|
||||
Ci.nsIDocShellTreeItem.typeAll,
|
||||
Ci.nsIDocShell.ENUMERATE_FORWARDS
|
||||
);
|
||||
|
||||
const docShells = [];
|
||||
for (const docShell of docShellsEnum) {
|
||||
for (const docShell of allDocShells) {
|
||||
docShell
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
|
@ -101,12 +101,12 @@ Timeline.prototype = {
|
||||
return [];
|
||||
}
|
||||
|
||||
const docShellsEnum = originalDocShell.getDocShellEnumerator(
|
||||
const docShells = originalDocShell.getAllDocShellsInSubtree(
|
||||
Ci.nsIDocShellTreeItem.typeAll,
|
||||
Ci.nsIDocShell.ENUMERATE_FORWARDS
|
||||
);
|
||||
|
||||
return Array.from(docShellsEnum);
|
||||
return docShells;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -123,7 +123,11 @@ add_task(async function() {
|
||||
|
||||
const slottedChildren = await walker.children(shadowChildren.nodes[1]);
|
||||
ok(slottedChildren.nodes[0].isBeforePseudoElement, "slot has ::before");
|
||||
ok(slottedChildren.nodes[2].isAfterPseudoElement, "slot has ::after");
|
||||
ok(
|
||||
slottedChildren.nodes[slottedChildren.nodes.length - 1]
|
||||
.isAfterPseudoElement,
|
||||
"slot has ::after"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function() {
|
||||
|
@ -829,6 +829,21 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"-moz-column-span": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"column-span"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"all",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"-moz-column-width": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -3217,6 +3232,7 @@ exports.CSS_PROPERTIES = {
|
||||
"text-rendering",
|
||||
"-moz-control-character-visibility",
|
||||
"text-underline-offset",
|
||||
"text-underline-position",
|
||||
"text-decoration-skip-ink",
|
||||
"cursor",
|
||||
"pointer-events",
|
||||
@ -3309,6 +3325,13 @@ exports.CSS_PROPERTIES = {
|
||||
"mask-size",
|
||||
"mask-composite",
|
||||
"mask-image",
|
||||
"x",
|
||||
"y",
|
||||
"cx",
|
||||
"cy",
|
||||
"rx",
|
||||
"ry",
|
||||
"r",
|
||||
"table-layout",
|
||||
"text-overflow",
|
||||
"text-decoration-line",
|
||||
@ -5670,6 +5693,21 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"column-span": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"column-span"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"all",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"column-width": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -5838,6 +5876,32 @@ exports.CSS_PROPERTIES = {
|
||||
"zoom-out"
|
||||
]
|
||||
},
|
||||
"cx": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"cx"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"cy": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"cy"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"direction": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
@ -8246,6 +8310,32 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"offset": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"offset-path",
|
||||
"offset-distance",
|
||||
"offset-rotate",
|
||||
"offset-anchor"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"bottom",
|
||||
"center",
|
||||
"inherit",
|
||||
"initial",
|
||||
"left",
|
||||
"none",
|
||||
"path",
|
||||
"ray",
|
||||
"reverse",
|
||||
"revert",
|
||||
"right",
|
||||
"top",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"offset-anchor": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -9014,6 +9104,19 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"r": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"r"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"resize": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -9047,6 +9150,20 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"rotate": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"rotate"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"row-gap": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -9093,6 +9210,48 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"rx": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"rx"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"ry": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"ry"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"scale": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"scale"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"scroll-behavior": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -9906,6 +10065,21 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"text-decoration-skip-ink": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"text-decoration-skip-ink"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"text-decoration-style": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -9925,6 +10099,21 @@ exports.CSS_PROPERTIES = {
|
||||
"wavy"
|
||||
]
|
||||
},
|
||||
"text-decoration-thickness": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"text-decoration-thickness"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"from-font",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"text-emphasis": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
@ -10138,6 +10327,38 @@ exports.CSS_PROPERTIES = {
|
||||
"uppercase"
|
||||
]
|
||||
},
|
||||
"text-underline-offset": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"text-underline-offset"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"from-font",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"text-underline-position": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"text-underline-position"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"inherit",
|
||||
"initial",
|
||||
"left",
|
||||
"revert",
|
||||
"right",
|
||||
"under",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"top": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -10350,6 +10571,20 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"translate": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"translate"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"unicode-bidi": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -10565,6 +10800,32 @@ exports.CSS_PROPERTIES = {
|
||||
"vertical-rl"
|
||||
]
|
||||
},
|
||||
"x": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"x"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"y": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"y"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"z-index": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@ -10649,6 +10910,10 @@ exports.PREFERENCES = [
|
||||
"text-justify",
|
||||
"layout.css.text-justify.enabled"
|
||||
],
|
||||
[
|
||||
"text-underline-position",
|
||||
"layout.css.text-underline-position.enabled"
|
||||
],
|
||||
[
|
||||
"touch-action",
|
||||
"layout.css.touch_action.enabled"
|
||||
@ -10725,14 +10990,14 @@ exports.PREFERENCES = [
|
||||
"text-underline-offset",
|
||||
"layout.css.text-underline-offset.enabled"
|
||||
],
|
||||
[
|
||||
"offset-distance",
|
||||
"layout.css.motion-path.enabled"
|
||||
],
|
||||
[
|
||||
"-moz-binding",
|
||||
"layout.css.moz-binding.content.enabled"
|
||||
],
|
||||
[
|
||||
"offset-distance",
|
||||
"layout.css.motion-path.enabled"
|
||||
],
|
||||
[
|
||||
"overflow-clip-box",
|
||||
"layout.css.overflow-clip-box.enabled"
|
||||
@ -10741,6 +11006,14 @@ exports.PREFERENCES = [
|
||||
"overscroll-behavior",
|
||||
"layout.css.overscroll-behavior.enabled"
|
||||
],
|
||||
[
|
||||
"offset",
|
||||
"layout.css.motion-path.enabled"
|
||||
],
|
||||
[
|
||||
"zoom",
|
||||
"layout.css.zoom-transform-hack.enabled"
|
||||
],
|
||||
[
|
||||
"-moz-transition-duration",
|
||||
"layout.css.prefixes.transitions"
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsISearchService.h"
|
||||
#include "nsIURIFixup.h"
|
||||
#include "nsIURIMutator.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsDefaultURIFixup.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
@ -359,6 +360,27 @@ nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDefaultURIFixup::WebNavigationFlagsToFixupFlags(const nsACString& aStringURI,
|
||||
uint32_t aDocShellFlags,
|
||||
uint32_t* aFixupFlags) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
NS_NewURI(getter_AddRefs(uri), aStringURI);
|
||||
if (uri) {
|
||||
aDocShellFlags &= ~nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
}
|
||||
|
||||
*aFixupFlags = 0;
|
||||
if (aDocShellFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
|
||||
*aFixupFlags |= FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
|
||||
}
|
||||
if (aDocShellFlags & nsIWebNavigation::LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
|
||||
*aFixupFlags |= FIXUP_FLAG_FIX_SCHEME_TYPOS;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword,
|
||||
nsIInputStream** aPostData,
|
||||
|
@ -1895,38 +1895,23 @@ nsDocShell::GetMayEnableCharacterEncodingMenu(
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetDocShellEnumerator(int32_t aItemType,
|
||||
DocShellEnumeratorDirection aDirection,
|
||||
nsISimpleEnumerator** aResult) {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = nullptr;
|
||||
nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType,
|
||||
DocShellEnumeratorDirection aDirection,
|
||||
nsTArray<RefPtr<nsIDocShell>>& aResult) {
|
||||
aResult.Clear();
|
||||
|
||||
RefPtr<nsDocShellEnumerator> docShellEnum;
|
||||
if (aDirection == ENUMERATE_FORWARDS) {
|
||||
docShellEnum = new nsDocShellForwardsEnumerator;
|
||||
} else {
|
||||
docShellEnum = new nsDocShellBackwardsEnumerator;
|
||||
}
|
||||
nsDocShellEnumerator docShellEnum(
|
||||
(aDirection == ENUMERATE_FORWARDS)
|
||||
? nsDocShellEnumerator::EnumerationDirection::Forwards
|
||||
: nsDocShellEnumerator::EnumerationDirection::Backwards,
|
||||
aItemType, *this);
|
||||
|
||||
nsresult rv = docShellEnum->SetEnumDocShellType(aItemType);
|
||||
nsresult rv = docShellEnum.BuildDocShellArray(aResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = docShellEnum->SetEnumerationRootItem((nsIDocShellTreeItem*)this);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = docShellEnum->First();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = docShellEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator),
|
||||
(void**)aResult);
|
||||
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -3388,6 +3373,15 @@ NS_IMETHODIMP
|
||||
nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
|
||||
NS_ENSURE_ARG_POINTER(aChild);
|
||||
|
||||
RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
|
||||
NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED);
|
||||
|
||||
child.forget(aChild);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
|
||||
#ifdef DEBUG
|
||||
if (aIndex < 0) {
|
||||
NS_WARNING("Negative index passed to GetChildAt");
|
||||
@ -3397,9 +3391,9 @@ nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
|
||||
#endif
|
||||
|
||||
nsIDocumentLoader* child = ChildAt(aIndex);
|
||||
NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return CallQueryInterface(child, aChild);
|
||||
// child may be nullptr here.
|
||||
return static_cast<nsDocShell*>(child);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -3905,10 +3899,6 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
|
||||
nsCOMPtr<nsIInputStream> postData(aLoadURIOptions.mPostData);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Create a URI from our string; if that succeeds, we want to
|
||||
// change loadFlags to not include the ALLOW_THIRD_PARTY_FIXUP
|
||||
// flag.
|
||||
|
||||
NS_ConvertUTF16toUTF8 uriString(aURI);
|
||||
// Cleanup the empty spaces that might be on each end.
|
||||
uriString.Trim(" ");
|
||||
@ -3920,24 +3910,19 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(uri), uriString);
|
||||
if (uri) {
|
||||
loadFlags &= ~LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURIFixupInfo> fixupInfo;
|
||||
if (sURIFixup) {
|
||||
// Call the fixup object. This will clobber the rv from NS_NewURI
|
||||
// above, but that's fine with us. Note that we need to do this even
|
||||
// if NS_NewURI returned a URI, because fixup handles nested URIs, etc
|
||||
// (things like view-source:mozilla.org for example).
|
||||
uint32_t fixupFlags = 0;
|
||||
if (loadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
|
||||
fixupFlags |= nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
|
||||
}
|
||||
if (loadFlags & LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
|
||||
fixupFlags |= nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS;
|
||||
uint32_t fixupFlags;
|
||||
rv = sURIFixup->WebNavigationFlagsToFixupFlags(uriString, loadFlags,
|
||||
&fixupFlags);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
// If we don't allow keyword lookups for this URL string, make sure to
|
||||
// update loadFlags to indicate this as well.
|
||||
if (!(fixupFlags & nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) {
|
||||
loadFlags &= ~LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> fixupStream;
|
||||
rv = sURIFixup->GetFixupURIInfo(uriString, fixupFlags,
|
||||
getter_AddRefs(fixupStream),
|
||||
@ -3962,9 +3947,11 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI,
|
||||
PromiseFlatString(aURI).get());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No fixup service so just create a URI and see what happens...
|
||||
rv = NS_NewURI(getter_AddRefs(uri), uriString);
|
||||
loadFlags &= ~LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
}
|
||||
// else no fixup service so just use the URI we created and see
|
||||
// what happens
|
||||
|
||||
if (NS_ERROR_MALFORMED_URI == rv) {
|
||||
if (DisplayLoadError(rv, uri, PromiseFlatString(aURI).get(), nullptr) &&
|
||||
|
@ -471,6 +471,8 @@ class nsDocShell final : public nsDocLoader,
|
||||
mSkipBrowsingContextDetachOnDestroy = true;
|
||||
}
|
||||
|
||||
nsDocShell* GetInProcessChildAt(int32_t aIndex);
|
||||
|
||||
private: // member functions
|
||||
friend class nsDSURIContentListener;
|
||||
friend class FramingChecker;
|
||||
@ -506,8 +508,7 @@ class nsDocShell final : public nsDocLoader,
|
||||
nsIDocShellTreeItem* aTargetTreeItem);
|
||||
|
||||
static inline uint32_t PRTimeToSeconds(PRTime aTimeUsec) {
|
||||
PRTime usecPerSec = PR_USEC_PER_SEC;
|
||||
return uint32_t(aTimeUsec /= usecPerSec);
|
||||
return uint32_t(aTimeUsec / PR_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
static const nsCString FrameTypeToString(uint32_t aFrameType) {
|
||||
|
@ -4,135 +4,47 @@
|
||||
|
||||
#include "nsDocShellEnumerator.h"
|
||||
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsDocShell.h"
|
||||
|
||||
nsDocShellEnumerator::nsDocShellEnumerator(int32_t aEnumerationDirection)
|
||||
: mRootItem(nullptr),
|
||||
mCurIndex(0),
|
||||
mDocShellType(nsIDocShellTreeItem::typeAll),
|
||||
mArrayValid(false),
|
||||
mEnumerationDirection(aEnumerationDirection) {}
|
||||
|
||||
nsDocShellEnumerator::~nsDocShellEnumerator() {}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellEnumerator::GetNext(nsISupports** aResult) {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = nullptr;
|
||||
|
||||
nsresult rv = EnsureDocShellArray();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mCurIndex >= mItemArray.Length()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// post-increment is important here
|
||||
nsCOMPtr<nsISupports> item = do_QueryReferent(mItemArray[mCurIndex++], &rv);
|
||||
item.forget(aResult);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellEnumerator::HasMoreElements(bool* aResult) {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = false;
|
||||
|
||||
nsresult rv = EnsureDocShellArray();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*aResult = (mCurIndex < mItemArray.Length());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShellEnumerator::GetEnumerationRootItem(
|
||||
nsIDocShellTreeItem** aEnumerationRootItem) {
|
||||
NS_ENSURE_ARG_POINTER(aEnumerationRootItem);
|
||||
nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
|
||||
item.forget(aEnumerationRootItem);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShellEnumerator::SetEnumerationRootItem(
|
||||
nsIDocShellTreeItem* aEnumerationRootItem) {
|
||||
mRootItem = do_GetWeakReference(aEnumerationRootItem);
|
||||
ClearState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShellEnumerator::GetEnumDocShellType(
|
||||
int32_t* aEnumerationItemType) {
|
||||
NS_ENSURE_ARG_POINTER(aEnumerationItemType);
|
||||
*aEnumerationItemType = mDocShellType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShellEnumerator::SetEnumDocShellType(
|
||||
int32_t aEnumerationItemType) {
|
||||
mDocShellType = aEnumerationItemType;
|
||||
ClearState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShellEnumerator::First() {
|
||||
mCurIndex = 0;
|
||||
return EnsureDocShellArray();
|
||||
}
|
||||
|
||||
nsresult nsDocShellEnumerator::EnsureDocShellArray() {
|
||||
if (!mArrayValid) {
|
||||
mArrayValid = true;
|
||||
return BuildDocShellArray(mItemArray);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShellEnumerator::ClearState() {
|
||||
mItemArray.Clear();
|
||||
mArrayValid = false;
|
||||
mCurIndex = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
nsDocShellEnumerator::nsDocShellEnumerator(
|
||||
nsDocShellEnumerator::EnumerationDirection aDirection,
|
||||
int32_t aDocShellType, nsDocShell& aRootItem)
|
||||
: mRootItem(&aRootItem),
|
||||
mDocShellType(aDocShellType),
|
||||
mDirection(aDirection) {}
|
||||
|
||||
nsresult nsDocShellEnumerator::BuildDocShellArray(
|
||||
nsTArray<nsWeakPtr>& aItemArray) {
|
||||
NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED);
|
||||
nsTArray<RefPtr<nsIDocShell>>& aItemArray) {
|
||||
MOZ_ASSERT(mRootItem);
|
||||
|
||||
aItemArray.Clear();
|
||||
nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
|
||||
return BuildArrayRecursive(item, aItemArray);
|
||||
|
||||
if (mDirection == EnumerationDirection::Forwards) {
|
||||
return BuildArrayRecursiveForwards(mRootItem, aItemArray);
|
||||
}
|
||||
MOZ_ASSERT(mDirection == EnumerationDirection::Backwards);
|
||||
return BuildArrayRecursiveBackwards(mRootItem, aItemArray);
|
||||
}
|
||||
|
||||
nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(
|
||||
nsIDocShellTreeItem* aItem, nsTArray<nsWeakPtr>& aItemArray) {
|
||||
nsresult nsDocShellEnumerator::BuildArrayRecursiveForwards(
|
||||
nsDocShell* aItem, nsTArray<RefPtr<nsIDocShell>>& aItemArray) {
|
||||
nsresult rv;
|
||||
|
||||
// add this item to the array
|
||||
if (mDocShellType == nsIDocShellTreeItem::typeAll ||
|
||||
aItem->ItemType() == mDocShellType) {
|
||||
if (!aItemArray.AppendElement(do_GetWeakReference(aItem))) {
|
||||
if (!aItemArray.AppendElement(aItem, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t numChildren;
|
||||
rv = aItem->GetInProcessChildCount(&numChildren);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
int32_t numChildren = aItem->ChildCount();
|
||||
|
||||
for (int32_t i = 0; i < numChildren; ++i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> curChild;
|
||||
rv = aItem->GetInProcessChildAt(i, getter_AddRefs(curChild));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
RefPtr<nsDocShell> curChild = aItem->GetInProcessChildAt(i);
|
||||
MOZ_ASSERT(curChild);
|
||||
|
||||
rv = BuildArrayRecursive(curChild, aItemArray);
|
||||
rv = BuildArrayRecursiveForwards(curChild, aItemArray);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -141,24 +53,17 @@ nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(
|
||||
nsIDocShellTreeItem* aItem, nsTArray<nsWeakPtr>& aItemArray) {
|
||||
nsresult nsDocShellEnumerator::BuildArrayRecursiveBackwards(
|
||||
nsDocShell* aItem, nsTArray<RefPtr<nsIDocShell>>& aItemArray) {
|
||||
nsresult rv;
|
||||
|
||||
int32_t numChildren;
|
||||
rv = aItem->GetInProcessChildCount(&numChildren);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
uint32_t numChildren = aItem->ChildCount();
|
||||
|
||||
for (int32_t i = numChildren - 1; i >= 0; --i) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> curChild;
|
||||
rv = aItem->GetInProcessChildAt(i, getter_AddRefs(curChild));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
RefPtr<nsDocShell> curChild = aItem->GetInProcessChildAt(i);
|
||||
MOZ_ASSERT(curChild);
|
||||
|
||||
rv = BuildArrayRecursive(curChild, aItemArray);
|
||||
rv = BuildArrayRecursiveBackwards(curChild, aItemArray);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -167,7 +72,7 @@ nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(
|
||||
// add this item to the array
|
||||
if (mDocShellType == nsIDocShellTreeItem::typeAll ||
|
||||
aItem->ItemType() == mDocShellType) {
|
||||
if (!aItemArray.AppendElement(do_GetWeakReference(aItem))) {
|
||||
if (!aItemArray.AppendElement(aItem)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
@ -5,89 +5,33 @@
|
||||
#ifndef nsDocShellEnumerator_h___
|
||||
#define nsDocShellEnumerator_h___
|
||||
|
||||
#include "nsSimpleEnumerator.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
|
||||
class nsIDocShellTreeItem;
|
||||
class nsDocShell;
|
||||
class nsIDocShell;
|
||||
|
||||
/*
|
||||
// {13cbc281-35ae-11d5-be5b-bde0edece43c}
|
||||
#define NS_DOCSHELL_FORWARDS_ENUMERATOR_CID \
|
||||
{ 0x13cbc281, 0x35ae, 0x11d5, { 0xbe, 0x5b, 0xbd, 0xe0, 0xed, 0xec, 0xe4, 0x3c }
|
||||
}
|
||||
class MOZ_STACK_CLASS nsDocShellEnumerator {
|
||||
public:
|
||||
enum class EnumerationDirection : uint8_t { Forwards, Backwards };
|
||||
|
||||
#define NS_DOCSHELL_FORWARDS_ENUMERATOR_CONTRACTID \
|
||||
"@mozilla.org/docshell/enumerator-forwards;1"
|
||||
|
||||
// {13cbc282-35ae-11d5-be5b-bde0edece43c}
|
||||
#define NS_DOCSHELL_BACKWARDS_ENUMERATOR_CID \
|
||||
{ 0x13cbc282, 0x35ae, 0x11d5, { 0xbe, 0x5b, 0xbd, 0xe0, 0xed, 0xec, 0xe4, 0x3c }
|
||||
}
|
||||
|
||||
#define NS_DOCSHELL_BACKWARDS_ENUMERATOR_CONTRACTID \
|
||||
"@mozilla.org/docshell/enumerator-backwards;1"
|
||||
*/
|
||||
|
||||
class nsDocShellEnumerator : public nsSimpleEnumerator {
|
||||
protected:
|
||||
enum { enumerateForwards, enumerateBackwards };
|
||||
|
||||
virtual ~nsDocShellEnumerator();
|
||||
nsDocShellEnumerator(EnumerationDirection aDirection, int32_t aDocShellType,
|
||||
nsDocShell& aRootItem);
|
||||
|
||||
public:
|
||||
explicit nsDocShellEnumerator(int32_t aEnumerationDirection);
|
||||
nsresult BuildDocShellArray(nsTArray<RefPtr<nsIDocShell>>& aItemArray);
|
||||
|
||||
// nsISimpleEnumerator
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
private:
|
||||
nsresult BuildArrayRecursiveForwards(
|
||||
nsDocShell* aItem, nsTArray<RefPtr<nsIDocShell>>& aItemArray);
|
||||
nsresult BuildArrayRecursiveBackwards(
|
||||
nsDocShell* aItem, nsTArray<RefPtr<nsIDocShell>>& aItemArray);
|
||||
|
||||
const nsID& DefaultInterface() override { return NS_GET_IID(nsIDocShell); }
|
||||
private:
|
||||
const RefPtr<nsDocShell> mRootItem;
|
||||
|
||||
public:
|
||||
nsresult GetEnumerationRootItem(nsIDocShellTreeItem** aEnumerationRootItem);
|
||||
nsresult SetEnumerationRootItem(nsIDocShellTreeItem* aEnumerationRootItem);
|
||||
const int32_t mDocShellType; // only want shells of this type
|
||||
|
||||
nsresult GetEnumDocShellType(int32_t* aEnumerationItemType);
|
||||
nsresult SetEnumDocShellType(int32_t aEnumerationItemType);
|
||||
|
||||
nsresult First();
|
||||
|
||||
protected:
|
||||
nsresult EnsureDocShellArray();
|
||||
nsresult ClearState();
|
||||
|
||||
nsresult BuildDocShellArray(nsTArray<nsWeakPtr>& aItemArray);
|
||||
virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* aItem,
|
||||
nsTArray<nsWeakPtr>& aItemArray) = 0;
|
||||
|
||||
protected:
|
||||
nsWeakPtr mRootItem; // weak ref!
|
||||
|
||||
nsTArray<nsWeakPtr> mItemArray; // flattened list of items with matching type
|
||||
uint32_t mCurIndex;
|
||||
|
||||
int32_t mDocShellType; // only want shells of this type
|
||||
bool mArrayValid; // is mItemArray up to date?
|
||||
|
||||
const int8_t mEnumerationDirection;
|
||||
};
|
||||
|
||||
class nsDocShellForwardsEnumerator : public nsDocShellEnumerator {
|
||||
public:
|
||||
nsDocShellForwardsEnumerator() : nsDocShellEnumerator(enumerateForwards) {}
|
||||
|
||||
protected:
|
||||
virtual nsresult BuildArrayRecursive(
|
||||
nsIDocShellTreeItem* aItem, nsTArray<nsWeakPtr>& aItemArray) override;
|
||||
};
|
||||
|
||||
class nsDocShellBackwardsEnumerator : public nsDocShellEnumerator {
|
||||
public:
|
||||
nsDocShellBackwardsEnumerator() : nsDocShellEnumerator(enumerateBackwards) {}
|
||||
|
||||
protected:
|
||||
virtual nsresult BuildArrayRecursive(
|
||||
nsIDocShellTreeItem* aItem, nsTArray<nsWeakPtr>& aItemArray) override;
|
||||
const EnumerationDirection mDirection;
|
||||
};
|
||||
|
||||
#endif // nsDocShellEnumerator_h___
|
||||
|
@ -45,7 +45,6 @@ interface nsIContentSecurityPolicy;
|
||||
interface nsIDocShellLoadInfo;
|
||||
interface nsIEditor;
|
||||
interface nsIEditingSession;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIInputStream;
|
||||
interface nsIRequest;
|
||||
interface nsISHEntry;
|
||||
@ -250,7 +249,7 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
[infallible] attribute boolean inheritPrivateBrowsingId;
|
||||
|
||||
/**
|
||||
* Get an enumerator over this docShell and its children.
|
||||
* Get an array of this docShell and its children.
|
||||
*
|
||||
* @param aItemType - Only include docShells of this type, or if typeAll,
|
||||
* include all child shells.
|
||||
@ -263,8 +262,8 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
ENUMERATE_BACKWARDS = 1
|
||||
};
|
||||
|
||||
nsISimpleEnumerator getDocShellEnumerator(in long aItemType,
|
||||
in nsIDocShell_DocShellEnumeratorDirection aDirection);
|
||||
Array<nsIDocShell> getAllDocShellsInSubtree(in long aItemType,
|
||||
in nsIDocShell_DocShellEnumeratorDirection aDirection);
|
||||
|
||||
/**
|
||||
* The type of application that created this window.
|
||||
|
@ -133,6 +133,17 @@ interface nsIURIFixup : nsISupports
|
||||
in unsigned long aFixupFlags,
|
||||
[optional] out nsIInputStream aPostData);
|
||||
|
||||
/**
|
||||
* Convert load flags from nsIWebNavigation to URI fixup flags for use in
|
||||
* createFixupURI or getFixupURIInfo.
|
||||
*
|
||||
* @param aURIText Candidate URI; used for determining whether to
|
||||
* allow keyword lookups.
|
||||
* @param aDocShellFlags Load flags from nsIDocShell to convert.
|
||||
*/
|
||||
unsigned long webNavigationFlagsToFixupFlags(
|
||||
in AUTF8String aURIText, in unsigned long aDocShellFlags);
|
||||
|
||||
/**
|
||||
* Converts the specified keyword string into a URI. Note that it's the
|
||||
* caller's responsibility to check whether keywords are enabled and
|
||||
|
@ -31,10 +31,8 @@ addEventListener("unload", e => {
|
||||
});
|
||||
|
||||
function getChildDocShells() {
|
||||
let docShellsEnum = docShell.getDocShellEnumerator(
|
||||
return docShell.getAllDocShellsInSubtree(
|
||||
Ci.nsIDocShellTreeItem.typeAll,
|
||||
Ci.nsIDocShell.ENUMERATE_FORWARDS
|
||||
);
|
||||
|
||||
return Array.from(docShellsEnum);
|
||||
}
|
||||
|
@ -81,17 +81,14 @@ skip-if = (verify && !debug && (os == 'win'))
|
||||
skip-if = (verify && !debug && (os == 'win'))
|
||||
[test_bug590573.html]
|
||||
[test_bug598895.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug634834.html]
|
||||
[test_bug637644.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug640387_1.html]
|
||||
[test_bug640387_2.html]
|
||||
[test_bug653741.html]
|
||||
[test_bug660404.html]
|
||||
[test_bug662170.html]
|
||||
[test_bug668513.html]
|
||||
skip-if = toolkit == 'android'
|
||||
support-files = file_bug668513.html
|
||||
[test_bug669671.html]
|
||||
[test_bug675587.html]
|
||||
@ -111,7 +108,6 @@ support-files = file_bug675587.html
|
||||
[test_close_onpagehide_by_window_close.html]
|
||||
[test_forceinheritprincipal_overrule_owner.html]
|
||||
[test_framedhistoryframes.html]
|
||||
skip-if = toolkit == 'android' # bug 784321
|
||||
support-files = file_framedhistoryframes.html
|
||||
[test_pushState_after_document_open.html]
|
||||
[test_windowedhistoryframes.html]
|
||||
|
@ -972,7 +972,7 @@ bool Animation::ShouldBeSynchronizedWithMainThread(
|
||||
}
|
||||
|
||||
return keyframeEffect->ShouldBlockAsyncTransformAnimations(
|
||||
aFrame, aPerformanceWarning);
|
||||
aFrame, aPropertySet, aPerformanceWarning);
|
||||
}
|
||||
|
||||
void Animation::UpdateRelevance() {
|
||||
|
@ -57,6 +57,9 @@ bool AnimationPerformanceWarning::ToLocalizedString(
|
||||
case Type::TransformFrameInactive:
|
||||
key = "CompositorAnimationWarningTransformFrameInactive";
|
||||
break;
|
||||
case Type::TransformIsBlockedByImportantRules:
|
||||
key = "CompositorAnimationWarningTransformIsBlockedByImportantRules";
|
||||
break;
|
||||
case Type::OpacityFrameInactive:
|
||||
key = "CompositorAnimationWarningOpacityFrameInactive";
|
||||
break;
|
||||
|
@ -25,6 +25,7 @@ struct AnimationPerformanceWarning {
|
||||
TransformWithGeometricProperties,
|
||||
TransformWithSyncGeometricAnimations,
|
||||
TransformFrameInactive,
|
||||
TransformIsBlockedByImportantRules,
|
||||
OpacityFrameInactive,
|
||||
HasRenderingObserver,
|
||||
};
|
||||
|
@ -137,14 +137,6 @@ bool FindAnimationsForCompositor(
|
||||
}
|
||||
}
|
||||
|
||||
// If the property will be added to the animations level of the cascade but
|
||||
// there is an !important rule for that property in the cascade then the
|
||||
// animation will not be applied since the !important rule overrides it.
|
||||
if (effects->PropertiesWithImportantRules().Intersects(aPropertySet) &&
|
||||
effects->PropertiesForAnimationsLevel().Intersects(aPropertySet)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AnimationPerformanceWarning::Type warning =
|
||||
AnimationPerformanceWarning::Type::None;
|
||||
if (!EffectCompositor::AllowCompositorAnimationsOnFrame(aFrame, warning)) {
|
||||
@ -283,15 +275,15 @@ void EffectCompositor::PostRestyleForAnimation(dom::Element* aElement,
|
||||
}
|
||||
|
||||
RestyleHint hint = aCascadeLevel == CascadeLevel::Transitions
|
||||
? StyleRestyleHint_RESTYLE_CSS_TRANSITIONS
|
||||
: StyleRestyleHint_RESTYLE_CSS_ANIMATIONS;
|
||||
? RestyleHint::RESTYLE_CSS_TRANSITIONS
|
||||
: RestyleHint::RESTYLE_CSS_ANIMATIONS;
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Restyle request during restyling should be requested only on "
|
||||
"the main-thread. e.g. after the parallel traversal");
|
||||
if (ServoStyleSet::IsInServoTraversal() || mIsInPreTraverse) {
|
||||
MOZ_ASSERT(hint == StyleRestyleHint_RESTYLE_CSS_ANIMATIONS ||
|
||||
hint == StyleRestyleHint_RESTYLE_CSS_TRANSITIONS);
|
||||
MOZ_ASSERT(hint == RestyleHint::RESTYLE_CSS_ANIMATIONS ||
|
||||
hint == RestyleHint::RESTYLE_CSS_TRANSITIONS);
|
||||
|
||||
// We can't call Servo_NoteExplicitHints here since AtomicRefCell does not
|
||||
// allow us mutate ElementData of the |aElement| in SequentialTask.
|
||||
@ -892,8 +884,8 @@ bool EffectCompositor::PreTraverseInSubtree(ServoTraversalFlags aFlags,
|
||||
mPresContext->RestyleManager()->PostRestyleEventForAnimations(
|
||||
target.mElement, target.mPseudoType,
|
||||
cascadeLevel == CascadeLevel::Transitions
|
||||
? StyleRestyleHint_RESTYLE_CSS_TRANSITIONS
|
||||
: StyleRestyleHint_RESTYLE_CSS_ANIMATIONS);
|
||||
? RestyleHint::RESTYLE_CSS_TRANSITIONS
|
||||
: RestyleHint::RESTYLE_CSS_ANIMATIONS);
|
||||
|
||||
foundElementsNeedingRestyle = true;
|
||||
|
||||
|
@ -279,35 +279,13 @@ const AnimationProperty* KeyframeEffect::GetEffectiveAnimationOfProperty(
|
||||
|
||||
bool KeyframeEffect::HasEffectiveAnimationOfPropertySet(
|
||||
const nsCSSPropertyIDSet& aPropertySet, const EffectSet& aEffectSet) const {
|
||||
// The various transform properties ('transform', 'scale' etc.) get combined
|
||||
// on the compositor.
|
||||
//
|
||||
// As a result, if we have an animation of 'scale' and 'translate', but the
|
||||
// 'translate' property is covered by an !important rule, we will not be
|
||||
// able to combine the result on the compositor since we won't have the
|
||||
// !important rule to incorporate. In that case we should run all the
|
||||
// transform-related animations on the main thread (where we have the
|
||||
// !important rule).
|
||||
//
|
||||
// Bug 1534884: Move this check to ShouldBlockAsyncTransformAnimations (or
|
||||
// similar) and add a performance warning for this case.
|
||||
|
||||
bool result = false;
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (!aPropertySet.HasProperty(property.mProperty)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsEffectiveProperty(aEffectSet, property.mProperty)) {
|
||||
result = true;
|
||||
} else if (nsCSSPropertyIDSet::TransformLikeProperties().HasProperty(
|
||||
property.mProperty)) {
|
||||
return false;
|
||||
if (aPropertySet.HasProperty(property.mProperty) &&
|
||||
IsEffectiveProperty(aEffectSet, property.mProperty)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCSSPropertyIDSet KeyframeEffect::GetPropertiesForCompositor(
|
||||
@ -323,22 +301,44 @@ nsCSSPropertyIDSet KeyframeEffect::GetPropertiesForCompositor(
|
||||
|
||||
static constexpr nsCSSPropertyIDSet compositorAnimatables =
|
||||
nsCSSPropertyIDSet::CompositorAnimatables();
|
||||
static constexpr nsCSSPropertyIDSet transformLikeProperties =
|
||||
nsCSSPropertyIDSet::TransformLikeProperties();
|
||||
|
||||
nsCSSPropertyIDSet transformSet;
|
||||
AnimationPerformanceWarning::Type dummyWarning;
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (!compositorAnimatables.HasProperty(property.mProperty)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AnimationPerformanceWarning::Type warning;
|
||||
// Transform-like properties are combined together on the compositor so we
|
||||
// need to evaluate them as a group. We build up a separate set here then
|
||||
// evaluate it as a separate step below.
|
||||
if (transformLikeProperties.HasProperty(property.mProperty)) {
|
||||
transformSet.AddProperty(property.mProperty);
|
||||
continue;
|
||||
}
|
||||
|
||||
KeyframeEffect::MatchForCompositor matchResult = IsMatchForCompositor(
|
||||
nsCSSPropertyIDSet{property.mProperty}, aFrame, aEffects, warning);
|
||||
nsCSSPropertyIDSet{property.mProperty}, aFrame, aEffects, dummyWarning);
|
||||
if (matchResult ==
|
||||
KeyframeEffect::MatchForCompositor::NoAndBlockThisProperty ||
|
||||
matchResult == KeyframeEffect::MatchForCompositor::No) {
|
||||
continue;
|
||||
}
|
||||
|
||||
properties.AddProperty(property.mProperty);
|
||||
}
|
||||
|
||||
if (!transformSet.IsEmpty()) {
|
||||
KeyframeEffect::MatchForCompositor matchResult =
|
||||
IsMatchForCompositor(transformSet, aFrame, aEffects, dummyWarning);
|
||||
if (matchResult == KeyframeEffect::MatchForCompositor::Yes ||
|
||||
matchResult == KeyframeEffect::MatchForCompositor::IfNeeded) {
|
||||
properties |= transformSet;
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@ -1185,7 +1185,25 @@ void KeyframeEffect::GetKeyframes(JSContext*& aCx, nsTArray<JSObject*>& aResult,
|
||||
}
|
||||
}
|
||||
|
||||
const char* name = nsCSSProps::PropertyIDLName(propertyValue.mProperty);
|
||||
// Basically, we need to do the mapping:
|
||||
// * eCSSProperty_offset => "cssOffset"
|
||||
// * eCSSProperty_float => "cssFloat"
|
||||
// This means if property refers to the CSS "offset"/"float" property,
|
||||
// return the string "cssOffset"/"cssFloat". (So avoid overlapping
|
||||
// "offset" property in BaseKeyframe.)
|
||||
// https://drafts.csswg.org/web-animations/#property-name-conversion
|
||||
const char* name = nullptr;
|
||||
switch (propertyValue.mProperty) {
|
||||
case nsCSSPropertyID::eCSSProperty_offset:
|
||||
name = "cssOffset";
|
||||
break;
|
||||
case nsCSSPropertyID::eCSSProperty_float:
|
||||
// FIXME: Bug 1582314: Should handle cssFloat manually if we remove it
|
||||
// from nsCSSProps::PropertyIDLName().
|
||||
default:
|
||||
name = nsCSSProps::PropertyIDLName(propertyValue.mProperty);
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!ToJSValue(aCx, stringValue, &value) ||
|
||||
!JS_DefineProperty(aCx, keyframeObject, name, value,
|
||||
@ -1495,10 +1513,28 @@ bool KeyframeEffect::CanAnimateTransformOnCompositor(
|
||||
}
|
||||
|
||||
bool KeyframeEffect::ShouldBlockAsyncTransformAnimations(
|
||||
const nsIFrame* aFrame,
|
||||
const nsIFrame* aFrame, const nsCSSPropertyIDSet& aPropertySet,
|
||||
AnimationPerformanceWarning::Type& aPerformanceWarning /* out */) const {
|
||||
EffectSet* effectSet =
|
||||
EffectSet::GetEffectSet(mTarget->mElement, mTarget->mPseudoType);
|
||||
// The various transform properties ('transform', 'scale' etc.) get combined
|
||||
// on the compositor.
|
||||
//
|
||||
// As a result, if we have an animation of 'scale' and 'translate', but the
|
||||
// 'translate' property is covered by an !important rule, we will not be
|
||||
// able to combine the result on the compositor since we won't have the
|
||||
// !important rule to incorporate. In that case we should run all the
|
||||
// transform-related animations on the main thread (where we have the
|
||||
// !important rule).
|
||||
nsCSSPropertyIDSet blockedProperties =
|
||||
effectSet->PropertiesWithImportantRules().Intersect(
|
||||
effectSet->PropertiesForAnimationsLevel());
|
||||
if (blockedProperties.Intersects(aPropertySet)) {
|
||||
aPerformanceWarning =
|
||||
AnimationPerformanceWarning::Type::TransformIsBlockedByImportantRules;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
// If there is a property for animations level that is overridden by
|
||||
// !important rules, it should not block other animations from running
|
||||
@ -1586,7 +1622,8 @@ void KeyframeEffect::CalculateCumulativeChangeHint(
|
||||
mNeedsStyleData = false;
|
||||
|
||||
nsPresContext* presContext =
|
||||
nsContentUtils::GetContextForContent(mTarget->mElement);
|
||||
mTarget ? nsContentUtils::GetContextForContent(mTarget->mElement)
|
||||
: nullptr;
|
||||
if (!presContext) {
|
||||
// Change hints make no sense if we're not rendered.
|
||||
//
|
||||
|
@ -200,9 +200,10 @@ class KeyframeEffect : public AnimationEffect {
|
||||
// this function is typically called for all KeyframeEffects on an element
|
||||
// so that we can avoid multiple calls of EffectSet::GetEffect().
|
||||
//
|
||||
// NOTE: Unlike HasEffectiveAnimationOfPropertySet below, this function does
|
||||
// not check for the effect of !important rules on animations of related
|
||||
// transform properties.
|
||||
// Note that does not consider the interaction between related transform
|
||||
// properties where an !important rule on another transform property may
|
||||
// cause all transform properties to be run on the main thread. That check is
|
||||
// performed by GetPropertiesForCompositor.
|
||||
bool HasEffectiveAnimationOfProperty(nsCSSPropertyID aProperty,
|
||||
const EffectSet& aEffect) const {
|
||||
return GetEffectiveAnimationOfProperty(aProperty, aEffect) != nullptr;
|
||||
@ -215,16 +216,10 @@ class KeyframeEffect : public AnimationEffect {
|
||||
// one property in |aPropertySet| that is not overridden by an !important
|
||||
// rule.
|
||||
//
|
||||
// Unlike HasEffectiveAnimationOfProperty, however, when |aPropertySet|
|
||||
// includes transform-like properties (transform, rotate etc.) this function
|
||||
// returns true if and only if all the transform-like properties that are
|
||||
// present are effective.
|
||||
//
|
||||
// That is because the transform-like properties, unlike other properties, are
|
||||
// combined on the compositor and if !important rules affect any of the
|
||||
// individual properties we will not be able to correctly compose the result
|
||||
// on the compositor so we should run the animations on the main thread
|
||||
// instead.
|
||||
// Note that does not consider the interaction between related transform
|
||||
// properties where an !important rule on another transform property may
|
||||
// cause all transform properties to be run on the main thread. That check is
|
||||
// performed by GetPropertiesForCompositor.
|
||||
bool HasEffectiveAnimationOfPropertySet(
|
||||
const nsCSSPropertyIDSet& aPropertySet,
|
||||
const EffectSet& aEffectSet) const;
|
||||
@ -278,7 +273,7 @@ class KeyframeEffect : public AnimationEffect {
|
||||
// When returning true, |aPerformanceWarning| stores the reason why
|
||||
// we shouldn't run the transform animations.
|
||||
bool ShouldBlockAsyncTransformAnimations(
|
||||
const nsIFrame* aFrame,
|
||||
const nsIFrame* aFrame, const nsCSSPropertyIDSet& aPropertySet,
|
||||
AnimationPerformanceWarning::Type& aPerformanceWarning /* out */) const;
|
||||
bool HasGeometricProperties() const;
|
||||
bool AffectsGeometry() const override {
|
||||
|
@ -504,8 +504,24 @@ static bool GetPropertyValuesPairs(JSContext* aCx,
|
||||
if (!propName.init(aCx, ids[i])) {
|
||||
return false;
|
||||
}
|
||||
nsCSSPropertyID property = nsCSSProps::LookupPropertyByIDLName(
|
||||
propName, CSSEnabledState::ForAllContent);
|
||||
|
||||
// Basically, we have to handle "cssOffset" and "cssFloat" specially here:
|
||||
// "cssOffset" => eCSSProperty_offset
|
||||
// "cssFloat" => eCSSProperty_float
|
||||
// This means if the attribute is the string "cssOffset"/"cssFloat", we use
|
||||
// CSS "offset"/"float" property.
|
||||
// https://drafts.csswg.org/web-animations/#property-name-conversion
|
||||
nsCSSPropertyID property = nsCSSPropertyID::eCSSProperty_UNKNOWN;
|
||||
if (propName.EqualsLiteral("cssOffset")) {
|
||||
property = nsCSSPropertyID::eCSSProperty_offset;
|
||||
} else if (propName.EqualsLiteral("cssFloat")) {
|
||||
property = nsCSSPropertyID::eCSSProperty_float;
|
||||
} else if (!propName.EqualsLiteral("offset") &&
|
||||
!propName.EqualsLiteral("float")) {
|
||||
property = nsCSSProps::LookupPropertyByIDLName(
|
||||
propName, CSSEnabledState::ForAllContent);
|
||||
}
|
||||
|
||||
if (KeyframeUtils::IsAnimatableProperty(property)) {
|
||||
AdditionalProperty* p = properties.AppendElement();
|
||||
p->mProperty = property;
|
||||
|
@ -4,6 +4,7 @@ prefs =
|
||||
dom.animations-api.compositing.enabled=true
|
||||
gfx.omta.background-color=true
|
||||
layout.css.individual-transform.enabled=true
|
||||
layout.css.motion-path.enabled=true
|
||||
support-files =
|
||||
testcommon.js
|
||||
../../imptests/testharness.js
|
||||
|
@ -1602,6 +1602,48 @@ function testTransformSVG() {
|
||||
});
|
||||
}
|
||||
|
||||
function testImportantRuleOverride() {
|
||||
promise_test(async t => {
|
||||
const elem = addDiv(t, { class: 'compositable' });
|
||||
const anim = elem.animate({ translate: [ '0px', '100px' ],
|
||||
rotate: ['0deg', '90deg'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
await waitForAnimationReadyToRestyle(anim);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_property_state_equals(
|
||||
anim.effect.getProperties(),
|
||||
[ { property: 'translate', runningOnCompositor: true },
|
||||
{ property: 'rotate', runningOnCompositor: true } ]
|
||||
);
|
||||
|
||||
elem.style.setProperty('rotate', '45deg', 'important');
|
||||
getComputedStyle(elem).rotate;
|
||||
|
||||
await waitForFrame();
|
||||
|
||||
assert_animation_property_state_equals(
|
||||
anim.effect.getProperties(),
|
||||
[
|
||||
{
|
||||
property: 'translate',
|
||||
runningOnCompositor: false,
|
||||
warning:
|
||||
'CompositorAnimationWarningTransformIsBlockedByImportantRules'
|
||||
},
|
||||
{
|
||||
property: 'rotate',
|
||||
runningOnCompositor: false,
|
||||
warning:
|
||||
'CompositorAnimationWarningTransformIsBlockedByImportantRules'
|
||||
},
|
||||
]
|
||||
);
|
||||
}, 'The animations of transform-like properties are not running on the ' +
|
||||
'compositor because any of the properties has important rules');
|
||||
}
|
||||
|
||||
function start() {
|
||||
var bundleService = SpecialPowers.Cc['@mozilla.org/intl/stringbundle;1']
|
||||
.getService(SpecialPowers.Ci.nsIStringBundleService);
|
||||
@ -1620,6 +1662,7 @@ function start() {
|
||||
testSynchronizedAnimations();
|
||||
testTooLargeFrame();
|
||||
testTransformSVG();
|
||||
testImportantRuleOverride();
|
||||
|
||||
promise_test(async t => {
|
||||
var div = addDiv(t, { class: 'compositable',
|
||||
|
@ -1115,12 +1115,134 @@ promise_test(async t => {
|
||||
});
|
||||
}, 'Multiple transform-like properties animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ offsetPath: ['none', 'none'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'offset-path animation should be running on the compositor even if ' +
|
||||
'it is always none');
|
||||
}, 'offset-path none animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ offsetPath: ['path("M0 0l100 100")',
|
||||
'path("M0 0l200 200")'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'offset-path animation should be running on the compositor');
|
||||
}, 'offset-path animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ offsetDistance: ['0%', '100%'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_not_running_on_compositor(animation,
|
||||
'offset-distance animation is not running on the compositor because ' +
|
||||
'offset-path is none');
|
||||
|
||||
const newAnim = div.animate({ offsetPath: ['None', 'None'] },
|
||||
100 * MS_PER_SEC);
|
||||
await waitForAnimationReadyToRestyle(newAnim);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'offset-distance animation should be running on the compositor');
|
||||
assert_animation_is_running_on_compositor(newAnim,
|
||||
'new added offset-path animation should be running on the compositor');
|
||||
}, 'offset-distance animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ offsetRotate: ['0deg', '45deg'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_not_running_on_compositor(animation,
|
||||
'offset-rotate animation is not running on the compositor because ' +
|
||||
'offset-path is none');
|
||||
|
||||
const newAnim = div.animate({ offsetPath: ['None', 'None'] },
|
||||
100 * MS_PER_SEC);
|
||||
await waitForAnimationReadyToRestyle(newAnim);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'offset-rotate animation should be running on the compositor');
|
||||
assert_animation_is_running_on_compositor(newAnim,
|
||||
'new added offset-path animation should be running on the compositor');
|
||||
}, 'offset-rotate animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ offsetAnchor: ['0% 0%', '100% 100%'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_not_running_on_compositor(animation,
|
||||
'offset-anchor animation is not running on the compositor because ' +
|
||||
'offset-path is none');
|
||||
|
||||
const newAnim = div.animate({ offsetPath: ['None', 'None'] },
|
||||
100 * MS_PER_SEC);
|
||||
await waitForAnimationReadyToRestyle(newAnim);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'offset-anchor animation should be running on the compositor');
|
||||
assert_animation_is_running_on_compositor(newAnim,
|
||||
'new added offset-path animation should be running on the compositor');
|
||||
}, 'offset-anchor animation runs on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ translate: ['0px', '100px'],
|
||||
rotate: ['0deg', '45deg'],
|
||||
transform: ['translate(0px)',
|
||||
'translate(100px)'],
|
||||
offsetDistance: ['0%', '100%'] },
|
||||
100 * MS_PER_SEC);
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'Animation is running on the compositor even though we do not have ' +
|
||||
'offset-path');
|
||||
|
||||
div.style.offsetPath = 'path("M50 0v100")';
|
||||
getComputedStyle(div).offsetPath;
|
||||
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'Animation is running on the compositor');
|
||||
|
||||
}, 'Multiple transform-like properties (include motion-path) animation runs ' +
|
||||
'on the compositor');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ translate: ['0px', '100px'],
|
||||
rotate: ['0deg', '45deg'],
|
||||
transform: ['translate(20px)',
|
||||
'translate(30px)'] },
|
||||
'translate(30px)'],
|
||||
offsetDistance: ['0%', '100%'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
div.style.setProperty('translate', '50px', 'important');
|
||||
@ -1130,8 +1252,8 @@ promise_test(async t => {
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_not_running_on_compositor(animation,
|
||||
'Animation overridden by an !important rule reports that it is ' +
|
||||
'NOT running on the compositor');
|
||||
'Animation overridden by an !important rule reports that it is ' +
|
||||
'NOT running on the compositor');
|
||||
|
||||
const properties = animation.effect.getProperties();
|
||||
properties.forEach(property => {
|
||||
@ -1142,5 +1264,94 @@ promise_test(async t => {
|
||||
'compositor because one of the transform-like property is overridden ' +
|
||||
'by an !important rule');
|
||||
|
||||
// FIXME: Bug 1593106: We should still run the animations on the compositor if
|
||||
// offset-* doesn't have any effect.
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ translate: ['0px', '100px'],
|
||||
rotate: ['0deg', '45deg'],
|
||||
transform: ['translate(0px)',
|
||||
'translate(100px)'],
|
||||
offsetDistance: ['0%', '100%'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
div.style.setProperty('offset-distance', '50%', 'important');
|
||||
getComputedStyle(div).offsetDistance;
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_not_running_on_compositor(animation,
|
||||
'Animation overridden by an !important rule reports that it is ' +
|
||||
'NOT running on the compositor');
|
||||
|
||||
const properties = animation.effect.getProperties();
|
||||
properties.forEach(property => {
|
||||
assert_true(!property.runningOnCompositor,
|
||||
property.property + ' is not running on the compositor');
|
||||
});
|
||||
}, 'Multiple transform-like properties animation does not runs on the ' +
|
||||
'compositor because one of the offset-* property is overridden ' +
|
||||
'by an !important rule');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t);
|
||||
const animation = div.animate({ rotate: ['0deg', '45deg'],
|
||||
transform: ['translate(20px)',
|
||||
'translate(30px)'],
|
||||
offsetDistance: ['0%', '100%'] },
|
||||
100 * MS_PER_SEC);
|
||||
|
||||
div.style.setProperty('translate', '50px', 'important');
|
||||
getComputedStyle(div).translate;
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'Animation is still running on the compositor');
|
||||
|
||||
const properties = animation.effect.getProperties();
|
||||
properties.forEach(property => {
|
||||
assert_true(property.runningOnCompositor,
|
||||
property.property + ' is running on the compositor');
|
||||
});
|
||||
}, 'Multiple transform-like properties animation still runs on the ' +
|
||||
'compositor because the overridden-by-!important property does not have ' +
|
||||
'animation');
|
||||
|
||||
promise_test(async t => {
|
||||
// We should run the animations on the compositor for this case:
|
||||
// 1. A transition of 'translate'
|
||||
// 2. An !important rule on 'translate'
|
||||
// 3. An animation of 'scale'
|
||||
const div = addDiv(t, { style: 'translate: 100px !important;' });
|
||||
const animation = div.animate({ rotate: ['0deg', '45deg'] },
|
||||
100 * MS_PER_SEC);
|
||||
div.style.transition = 'translate 100s';
|
||||
getComputedStyle(div).transition;
|
||||
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(animation,
|
||||
'rotate animation should be running on the compositor');
|
||||
|
||||
div.style.setProperty('translate', '200px', 'important');
|
||||
getComputedStyle(div).translate;
|
||||
|
||||
const anims = div.getAnimations();
|
||||
await waitForPaints();
|
||||
|
||||
assert_animation_is_running_on_compositor(anims[0],
|
||||
`${anims[0].effect.getProperties()[0].property} animation should be ` +
|
||||
`running on the compositor`);
|
||||
assert_animation_is_running_on_compositor(anims[1],
|
||||
`${anims[1].effect.getProperties()[0].property} animation should be ` +
|
||||
`running on the compositor`);
|
||||
}, 'Transform-like animations and transitions still runs on the compositor ' +
|
||||
'because the !important rule is overridden by a transition, and the ' +
|
||||
'transition property does not have animations');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
24
dom/animation/test/crashtests/1575926.html
Normal file
24
dom/animation/test/crashtests/1575926.html
Normal file
@ -0,0 +1,24 @@
|
||||
<style>
|
||||
@keyframes animation_0 {
|
||||
88% { }
|
||||
}
|
||||
|
||||
* {
|
||||
animation-name: animation_0;
|
||||
animation-delay: 4s;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function start () {
|
||||
const input = document.createElement('input')
|
||||
document.documentElement.appendChild(input)
|
||||
const animations = input.getAnimations({})
|
||||
const animation = animations[(3782796448 % animations.length)]
|
||||
const effect = animation.effect
|
||||
effect.setKeyframes({ 'borderLeft': ['inherit'] })
|
||||
effect.target = null
|
||||
input.contentEditable = 'true'
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', start)
|
||||
</script>
|
@ -43,3 +43,4 @@ pref(dom.animations-api.core.enabled,true) pref(dom.animations-api.timelines.ena
|
||||
pref(dom.animations-api.implicit-keyframes.enabled,true) load 1468294-1.html
|
||||
pref(dom.animations-api.implicit-keyframes.enabled,true) load 1467277-1.html
|
||||
load 1524480-1.html
|
||||
load 1575926.html
|
||||
|
@ -365,8 +365,6 @@ waitForAllPaints(() => {
|
||||
|
||||
add_task(
|
||||
async function restyling_transform_animations_in_scrolled_out_element() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [["ui.showHideScrollbars", 1]] });
|
||||
|
||||
// Make sure we start from the state right after requestAnimationFrame.
|
||||
await waitForFrame();
|
||||
|
||||
@ -1549,8 +1547,6 @@ waitForAllPaints(() => {
|
||||
|
||||
add_task(
|
||||
async function no_overflow_transform_animations_in_scrollable_element() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [["ui.showHideScrollbars", 1]] });
|
||||
|
||||
const parentElement = addDiv(null,
|
||||
{ style: 'overflow-y: scroll; height: 100px;' });
|
||||
const div = addDiv(null);
|
||||
|
@ -12,6 +12,7 @@ SpecialPowers.pushPrefEnv(
|
||||
set: [
|
||||
['layout.reflow.synthMouseMove', false],
|
||||
['privacy.reduceTimerPrecision', false],
|
||||
["ui.showHideScrollbars", 1],
|
||||
],
|
||||
},
|
||||
function() {
|
||||
|
@ -328,8 +328,7 @@ Directionality GetDirectionFromText(const char16_t* aText,
|
||||
uint32_t current = start - aText;
|
||||
uint32_t ch = *start++;
|
||||
|
||||
if (NS_IS_HIGH_SURROGATE(ch) && start < end &&
|
||||
NS_IS_LOW_SURROGATE(*start)) {
|
||||
if (start < end && NS_IS_SURROGATE_PAIR(ch, *start)) {
|
||||
ch = SURROGATE_TO_UCS4(ch, *start++);
|
||||
current++;
|
||||
}
|
||||
|
@ -5657,7 +5657,7 @@ already_AddRefed<PresShell> Document::CreatePresShell(
|
||||
|
||||
AssertNoStaleServoDataIn(*this);
|
||||
|
||||
RefPtr<PresShell> presShell = new PresShell;
|
||||
RefPtr<PresShell> presShell = new PresShell(this);
|
||||
// Note: we don't hold a ref to the shell (it holds a ref to us)
|
||||
mPresShell = presShell;
|
||||
|
||||
@ -5666,7 +5666,7 @@ already_AddRefed<PresShell> Document::CreatePresShell(
|
||||
FillStyleSet();
|
||||
}
|
||||
|
||||
presShell->Init(this, aContext, aViewManager);
|
||||
presShell->Init(aContext, aViewManager);
|
||||
|
||||
if (hadStyleSheets) {
|
||||
// Gaining a shell causes changes in how media queries are evaluated, so
|
||||
@ -9558,6 +9558,19 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
|
||||
size.height = clamped(size.height, effectiveMinSize.height,
|
||||
float(kViewportMaxSize.height));
|
||||
|
||||
// In cases of user-scalable=no, if we have a positive scale, clamp it to
|
||||
// min and max, and then use the clamped value for the scale, the min, and
|
||||
// the max. If we don't have a positive scale, assert that we are setting
|
||||
// the auto scale flag.
|
||||
if (effectiveZoomFlag == nsViewportInfo::ZoomFlag::DisallowZoom &&
|
||||
scaleFloat > CSSToScreenScale(0.0f)) {
|
||||
scaleFloat = scaleMinFloat = scaleMaxFloat =
|
||||
clamped(scaleFloat, scaleMinFloat, scaleMaxFloat);
|
||||
}
|
||||
MOZ_ASSERT(
|
||||
scaleFloat > CSSToScreenScale(0.0f) || !mValidScaleFloat,
|
||||
"If we don't have a positive scale, we should be using auto scale.");
|
||||
|
||||
// We need to perform a conversion, but only if the initial or maximum
|
||||
// scale were set explicitly by the user.
|
||||
if (mValidScaleFloat && scaleFloat >= scaleMinFloat &&
|
||||
@ -12996,8 +13009,8 @@ void Document::CleanupFullscreenState() {
|
||||
// Restore the zoom level that was in place prior to entering fullscreen.
|
||||
if (PresShell* presShell = GetPresShell()) {
|
||||
if (presShell->GetMobileViewportManager()) {
|
||||
presShell->SetResolutionAndScaleTo(mSavedResolution,
|
||||
ResolutionChangeOrigin::MainThread);
|
||||
presShell->SetResolutionAndScaleTo(
|
||||
mSavedResolution, ResolutionChangeOrigin::MainThreadRestore);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13393,7 +13406,7 @@ bool Document::ApplyFullscreen(UniquePtr<FullscreenRequest> aRequest) {
|
||||
child->mSavedResolution = presShell->GetResolution();
|
||||
presShell->SetResolutionAndScaleTo(
|
||||
manager->ComputeIntrinsicResolution(),
|
||||
ResolutionChangeOrigin::MainThread);
|
||||
ResolutionChangeOrigin::MainThreadRestore);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13791,9 +13804,6 @@ void Document::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const {
|
||||
|
||||
mStyleSet->AddSizeOfIncludingThis(aWindowSizes);
|
||||
|
||||
aWindowSizes.mDOMOtherSize += mLangGroupFontPrefs.SizeOfExcludingThis(
|
||||
aWindowSizes.mState.mMallocSizeOf);
|
||||
|
||||
aWindowSizes.mPropertyTablesSize +=
|
||||
mPropertyTable.SizeOfExcludingThis(aWindowSizes.mState.mMallocSizeOf);
|
||||
|
||||
@ -15446,6 +15456,12 @@ void Document::RemoveToplevelLoadingDocument(Document* aDoc) {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool Document::UseOverlayScrollbars(const Document* aDocument) {
|
||||
return LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) ||
|
||||
(aDocument && aDocument->InRDMPane());
|
||||
}
|
||||
|
||||
bool Document::HasRecentlyStartedForegroundLoads() {
|
||||
if (!sLoadingForegroundTopLevelContentDocument) {
|
||||
return false;
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "nsTHashtable.h" // for member
|
||||
#include "nsURIHashKey.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/StaticPresData.h"
|
||||
#include "Units.h"
|
||||
#include "nsContentListDeclarations.h"
|
||||
#include "nsExpirationTracker.h"
|
||||
@ -55,7 +54,6 @@
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/NotNull.h"
|
||||
#include "mozilla/SegmentedVector.h"
|
||||
#include "mozilla/ServoBindingTypes.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
@ -4056,6 +4054,10 @@ class Document : public nsINode,
|
||||
bool InRDMPane() const { return mInRDMPane; }
|
||||
void SetInRDMPane(bool aInRDMPane) { mInRDMPane = aInRDMPane; }
|
||||
|
||||
// Returns true if we use overlay scrollbars on the system wide or on the
|
||||
// given document.
|
||||
static bool UseOverlayScrollbars(const Document* aDocument);
|
||||
|
||||
static bool HasRecentlyStartedForegroundLoads();
|
||||
|
||||
static bool AutomaticStorageAccessCanBeGranted(nsIPrincipal* aPrincipal);
|
||||
@ -5112,13 +5114,6 @@ class Document : public nsINode,
|
||||
// resolution.
|
||||
nsTHashtable<nsPtrHashKey<SVGElement>> mLazySVGPresElements;
|
||||
|
||||
// Most documents will only use one (or very few) language groups. Rather
|
||||
// than have the overhead of a hash lookup, we simply look along what will
|
||||
// typically be a very short (usually of length 1) linked list. There are 31
|
||||
// language groups, so in the worst case scenario we'll need to traverse 31
|
||||
// link items.
|
||||
LangGroupFontPrefs mLangGroupFontPrefs;
|
||||
|
||||
nsTHashtable<nsRefPtrHashKey<nsAtom>> mLanguagesUsed;
|
||||
|
||||
// TODO(emilio): Is this hot enough to warrant to be cached?
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/StaticPrefs_full_screen_api.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/Attr.h"
|
||||
#include "mozilla/dom/BindContext.h"
|
||||
@ -50,7 +51,10 @@
|
||||
#include "mozilla/dom/AnimatableBinding.h"
|
||||
#include "mozilla/dom/FeaturePolicyUtils.h"
|
||||
#include "mozilla/dom/HTMLDivElement.h"
|
||||
#include "mozilla/dom/HTMLParagraphElement.h"
|
||||
#include "mozilla/dom/HTMLPreElement.h"
|
||||
#include "mozilla/dom/HTMLSpanElement.h"
|
||||
#include "mozilla/dom/HTMLTableCellElement.h"
|
||||
#include "mozilla/dom/KeyframeAnimationOptionsBinding.h"
|
||||
#include "mozilla/dom/MutationEventBinding.h"
|
||||
#include "mozilla/AnimationComparator.h"
|
||||
@ -193,7 +197,10 @@ namespace dom {
|
||||
// bucket sizes.
|
||||
ASSERT_NODE_SIZE(Element, 128, 80);
|
||||
ASSERT_NODE_SIZE(HTMLDivElement, 128, 80);
|
||||
ASSERT_NODE_SIZE(HTMLParagraphElement, 128, 80);
|
||||
ASSERT_NODE_SIZE(HTMLPreElement, 128, 80);
|
||||
ASSERT_NODE_SIZE(HTMLSpanElement, 128, 80);
|
||||
ASSERT_NODE_SIZE(HTMLTableCellElement, 128, 80);
|
||||
ASSERT_NODE_SIZE(Text, 120, 64);
|
||||
|
||||
#undef ASSERT_NODE_SIZE
|
||||
@ -632,6 +639,16 @@ nsDOMTokenList* Element::ClassList() {
|
||||
return slots->mClassList;
|
||||
}
|
||||
|
||||
nsDOMTokenList* Element::Part() {
|
||||
Element::nsDOMSlots* slots = DOMSlots();
|
||||
|
||||
if (!slots->mPart) {
|
||||
slots->mPart = new nsDOMTokenList(this, nsGkAtoms::part);
|
||||
}
|
||||
|
||||
return slots->mPart;
|
||||
}
|
||||
|
||||
void Element::GetAttributeNames(nsTArray<nsString>& aResult) {
|
||||
uint32_t count = mAttrs.AttrCount();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
@ -981,7 +998,7 @@ nsRect Element::GetClientAreaRect() {
|
||||
// The display check is OK even though we're not looking at the style
|
||||
// frame, because the style frame only differs from "frame" for tables,
|
||||
// and table wrappers have the same display as the table itself.
|
||||
(frame->StyleDisplay()->mDisplay != StyleDisplay::Inline ||
|
||||
(!frame->StyleDisplay()->IsInlineFlow() ||
|
||||
frame->IsFrameOfType(nsIFrame::eReplaced))) {
|
||||
// Special case code to make client area work even when there isn't
|
||||
// a scroll view, see bug 180552, bug 227567.
|
||||
@ -1737,7 +1754,8 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
|
||||
// XXXbz if we already have a style attr parsed, this won't do
|
||||
// anything... need to fix that.
|
||||
// If MayHaveStyle() is true, we must be an nsStyledElement
|
||||
static_cast<nsStyledElement*>(this)->ReparseStyleAttribute(false, false);
|
||||
static_cast<nsStyledElement*>(this)->ReparseStyleAttribute(
|
||||
/* aForceInDataDoc = */ false);
|
||||
}
|
||||
|
||||
// FIXME(emilio): Why is this needed? The element shouldn't even be styled in
|
||||
@ -2023,7 +2041,7 @@ void Element::SetSMILOverrideStyleDeclaration(DeclarationBlock& aDeclaration) {
|
||||
// that's been detached since the previous animation sample.)
|
||||
if (Document* doc = GetComposedDoc()) {
|
||||
if (PresShell* presShell = doc->GetPresShell()) {
|
||||
presShell->RestyleForAnimation(this, StyleRestyleHint_RESTYLE_SMIL);
|
||||
presShell->RestyleForAnimation(this, RestyleHint::RESTYLE_SMIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2589,6 +2607,12 @@ bool Element::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::exportparts &&
|
||||
StaticPrefs::layout_css_shadow_parts_enabled()) {
|
||||
aResult.ParsePartMapping(aValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::id) {
|
||||
// Store id as an atom. id="" means that the element has no id,
|
||||
// not that it has an emptystring as the id.
|
||||
@ -3188,47 +3212,14 @@ nsresult Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor) {
|
||||
|
||||
void Element::GetLinkTarget(nsAString& aTarget) { aTarget.Truncate(); }
|
||||
|
||||
static void nsDOMTokenListPropertyDestructor(void* aObject, nsAtom* aProperty,
|
||||
void* aPropertyValue,
|
||||
void* aData) {
|
||||
nsDOMTokenList* list = static_cast<nsDOMTokenList*>(aPropertyValue);
|
||||
NS_RELEASE(list);
|
||||
}
|
||||
|
||||
static nsStaticAtom* const sPropertiesToTraverseAndUnlink[] = {
|
||||
nsGkAtoms::sandbox, nsGkAtoms::sizes, nsGkAtoms::dirAutoSetBy, nullptr};
|
||||
nsGkAtoms::dirAutoSetBy, nullptr};
|
||||
|
||||
// static
|
||||
nsStaticAtom* const* Element::HTMLSVGPropertiesToTraverseAndUnlink() {
|
||||
return sPropertiesToTraverseAndUnlink;
|
||||
}
|
||||
|
||||
nsDOMTokenList* Element::GetTokenList(
|
||||
nsAtom* aAtom, const DOMTokenListSupportedTokenArray aSupportedTokens) {
|
||||
#ifdef DEBUG
|
||||
const nsStaticAtom* const* props = HTMLSVGPropertiesToTraverseAndUnlink();
|
||||
bool found = false;
|
||||
for (uint32_t i = 0; props[i]; ++i) {
|
||||
if (props[i] == aAtom) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
|
||||
#endif
|
||||
|
||||
nsDOMTokenList* list = nullptr;
|
||||
if (HasProperties()) {
|
||||
list = static_cast<nsDOMTokenList*>(GetProperty(aAtom));
|
||||
}
|
||||
if (!list) {
|
||||
list = new nsDOMTokenList(this, aAtom, aSupportedTokens);
|
||||
NS_ADDREF(list);
|
||||
SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
nsresult Element::CopyInnerTo(Element* aDst, ReparseAttributes aReparse) {
|
||||
nsresult rv = aDst->mAttrs.EnsureCapacityToClone(mAttrs);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1026,6 +1026,8 @@ class Element : public FragmentOrElement {
|
||||
}
|
||||
|
||||
nsDOMTokenList* ClassList();
|
||||
nsDOMTokenList* Part();
|
||||
|
||||
nsDOMAttributeMap* Attributes() {
|
||||
nsDOMSlots* slots = DOMSlots();
|
||||
if (!slots->mAttributeMap) {
|
||||
@ -1906,10 +1908,6 @@ class Element : public FragmentOrElement {
|
||||
*/
|
||||
virtual void GetLinkTarget(nsAString& aTarget);
|
||||
|
||||
nsDOMTokenList* GetTokenList(
|
||||
nsAtom* aAtom,
|
||||
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
|
||||
|
||||
enum class ReparseAttributes { No, Yes };
|
||||
/**
|
||||
* Copy attributes and state to another element
|
||||
|
@ -584,6 +584,9 @@ void FragmentOrElement::nsDOMSlots::Traverse(
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mSlots->mClassList");
|
||||
aCb.NoteXPCOMChild(mClassList.get());
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mSlots->mPart");
|
||||
aCb.NoteXPCOMChild(mPart.get());
|
||||
}
|
||||
|
||||
void FragmentOrElement::nsDOMSlots::Unlink() {
|
||||
@ -595,6 +598,7 @@ void FragmentOrElement::nsDOMSlots::Unlink() {
|
||||
}
|
||||
mChildrenList = nullptr;
|
||||
mClassList = nullptr;
|
||||
mPart = nullptr;
|
||||
}
|
||||
|
||||
size_t FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(
|
||||
@ -1103,23 +1107,23 @@ void nsIContent::SetXBLInsertionPoint(nsIContent* aContent) {
|
||||
|
||||
#ifdef DEBUG
|
||||
void nsIContent::AssertAnonymousSubtreeRelatedInvariants() const {
|
||||
NS_ASSERTION(!IsRootOfNativeAnonymousSubtree() ||
|
||||
(GetParent() && GetBindingParent() == GetParent()),
|
||||
"root of native anonymous subtree must have parent equal "
|
||||
"to binding parent");
|
||||
NS_ASSERTION(!GetParent() || !IsInComposedDoc() ||
|
||||
((GetBindingParent() == GetParent()) ==
|
||||
HasFlag(NODE_IS_ANONYMOUS_ROOT)) ||
|
||||
// Unfortunately default content for XBL insertion points
|
||||
// is anonymous content that is bound with the parent of
|
||||
// the insertion point as the parent but the bound element
|
||||
// for the binding as the binding parent. So we have to
|
||||
// complicate the assert a bit here.
|
||||
(GetBindingParent() &&
|
||||
(GetBindingParent() == GetParent()->GetBindingParent()) ==
|
||||
HasFlag(NODE_IS_ANONYMOUS_ROOT)),
|
||||
"For connected nodes, flag and GetBindingParent() check "
|
||||
"should match");
|
||||
MOZ_ASSERT(!IsRootOfNativeAnonymousSubtree() ||
|
||||
(GetParent() && GetBindingParent() == GetParent()),
|
||||
"root of native anonymous subtree must have parent equal "
|
||||
"to binding parent");
|
||||
MOZ_ASSERT(!GetParent() || !IsInComposedDoc() ||
|
||||
((GetBindingParent() == GetParent()) ==
|
||||
HasFlag(NODE_IS_ANONYMOUS_ROOT)) ||
|
||||
// Unfortunately default content for XBL insertion points
|
||||
// is anonymous content that is bound with the parent of
|
||||
// the insertion point as the parent but the bound element
|
||||
// for the binding as the binding parent. So we have to
|
||||
// complicate the assert a bit here.
|
||||
(GetBindingParent() &&
|
||||
(GetBindingParent() == GetParent()->GetBindingParent()) ==
|
||||
HasFlag(NODE_IS_ANONYMOUS_ROOT)),
|
||||
"For connected nodes, flag and GetBindingParent() check "
|
||||
"should match");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -238,6 +238,11 @@ class FragmentOrElement : public nsIContent {
|
||||
* An object implementing the .classList property for this element.
|
||||
*/
|
||||
RefPtr<nsDOMTokenList> mClassList;
|
||||
|
||||
/**
|
||||
* An object implementing the .part property for this element.
|
||||
*/
|
||||
RefPtr<nsDOMTokenList> mPart;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "Link.h"
|
||||
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
@ -92,240 +91,9 @@ void Link::CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
}
|
||||
}
|
||||
|
||||
void Link::GetContentPolicyMimeTypeMedia(nsAttrValue& aAsAttr,
|
||||
nsContentPolicyType& aPolicyType,
|
||||
nsString& aMimeType,
|
||||
nsAString& aMedia) {
|
||||
nsAutoString as;
|
||||
mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::as, as);
|
||||
Link::ParseAsValue(as, aAsAttr);
|
||||
aPolicyType = AsValueToContentPolicy(aAsAttr);
|
||||
|
||||
nsAutoString type;
|
||||
mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
|
||||
nsAutoString notUsed;
|
||||
nsContentUtils::SplitMimeType(type, aMimeType, notUsed);
|
||||
|
||||
mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
|
||||
}
|
||||
|
||||
void Link::TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender() {
|
||||
MOZ_ASSERT(mElement->IsInComposedDoc());
|
||||
if (!ElementHasHref()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString rel;
|
||||
if (!mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nsContentUtils::PrefetchPreloadEnabled(
|
||||
mElement->OwnerDoc()->GetDocShell())) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
|
||||
|
||||
if ((linkTypes & nsStyleLinkElement::ePREFETCH) ||
|
||||
(linkTypes & nsStyleLinkElement::eNEXT) ||
|
||||
(linkTypes & nsStyleLinkElement::ePRELOAD)) {
|
||||
nsCOMPtr<nsIPrefetchService> prefetchService(
|
||||
components::Prefetch::Service());
|
||||
if (prefetchService) {
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (uri) {
|
||||
bool preload = !!(linkTypes & nsStyleLinkElement::ePRELOAD);
|
||||
nsContentPolicyType policyType;
|
||||
|
||||
if (preload) {
|
||||
nsAttrValue asAttr;
|
||||
nsAutoString mimeType;
|
||||
nsAutoString media;
|
||||
GetContentPolicyMimeTypeMedia(asAttr, policyType, mimeType, media);
|
||||
|
||||
if (policyType == nsIContentPolicy::TYPE_INVALID) {
|
||||
// Ignore preload with a wrong or empty as attribute.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
policyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
|
||||
referrerInfo->InitWithNode(mElement);
|
||||
if (preload) {
|
||||
prefetchService->PreloadURI(uri, referrerInfo, mElement, policyType);
|
||||
} else {
|
||||
prefetchService->PrefetchURI(
|
||||
uri, referrerInfo, mElement,
|
||||
linkTypes & nsStyleLinkElement::ePREFETCH);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (linkTypes & nsStyleLinkElement::ePRECONNECT) {
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (uri && mElement->OwnerDoc()) {
|
||||
mElement->OwnerDoc()->MaybePreconnect(
|
||||
uri, Element::AttrValueToCORSMode(
|
||||
mElement->GetParsedAttr(nsGkAtoms::crossorigin)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
if (nsHTMLDNSPrefetch::IsAllowed(mElement->OwnerDoc())) {
|
||||
nsHTMLDNSPrefetch::PrefetchLow(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Link::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue) {
|
||||
MOZ_ASSERT(mElement->IsInComposedDoc());
|
||||
|
||||
if (!ElementHasHref()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString rel;
|
||||
if (!mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nsContentUtils::PrefetchPreloadEnabled(
|
||||
mElement->OwnerDoc()->GetDocShell())) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel);
|
||||
|
||||
if (!(linkTypes & nsStyleLinkElement::ePRELOAD)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
|
||||
if (!prefetchService) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAttrValue asAttr;
|
||||
nsContentPolicyType asPolicyType;
|
||||
nsAutoString mimeType;
|
||||
nsAutoString media;
|
||||
GetContentPolicyMimeTypeMedia(asAttr, asPolicyType, mimeType, media);
|
||||
|
||||
if (asPolicyType == nsIContentPolicy::TYPE_INVALID) {
|
||||
// Ignore preload with a wrong or empty as attribute, but be sure to cancel
|
||||
// the old one.
|
||||
prefetchService->CancelPrefetchPreloadURI(uri, mElement);
|
||||
return;
|
||||
}
|
||||
|
||||
nsContentPolicyType policyType = asPolicyType;
|
||||
if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
policyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::crossorigin) {
|
||||
CORSMode corsMode = Element::AttrValueToCORSMode(aValue);
|
||||
CORSMode oldCorsMode = Element::AttrValueToCORSMode(aOldValue);
|
||||
if (corsMode != oldCorsMode) {
|
||||
prefetchService->CancelPrefetchPreloadURI(uri, mElement);
|
||||
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
|
||||
referrerInfo->InitWithNode(mElement);
|
||||
prefetchService->PreloadURI(uri, referrerInfo, mElement, policyType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsContentPolicyType oldPolicyType;
|
||||
|
||||
if (aName == nsGkAtoms::as) {
|
||||
if (aOldValue) {
|
||||
oldPolicyType = AsValueToContentPolicy(*aOldValue);
|
||||
if (!HTMLLinkElement::CheckPreloadAttrs(*aOldValue, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
} else {
|
||||
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
} else if (aName == nsGkAtoms::type) {
|
||||
nsAutoString oldType;
|
||||
nsAutoString notUsed;
|
||||
if (aOldValue) {
|
||||
aOldValue->ToString(oldType);
|
||||
} else {
|
||||
oldType = EmptyString();
|
||||
}
|
||||
nsAutoString oldMimeType;
|
||||
nsContentUtils::SplitMimeType(oldType, oldMimeType, notUsed);
|
||||
if (HTMLLinkElement::CheckPreloadAttrs(asAttr, oldMimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
oldPolicyType = asPolicyType;
|
||||
} else {
|
||||
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(aName == nsGkAtoms::media);
|
||||
nsAutoString oldMedia;
|
||||
if (aOldValue) {
|
||||
aOldValue->ToString(oldMedia);
|
||||
} else {
|
||||
oldMedia = EmptyString();
|
||||
}
|
||||
if (HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, oldMedia,
|
||||
mElement->OwnerDoc())) {
|
||||
oldPolicyType = asPolicyType;
|
||||
} else {
|
||||
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if ((policyType != oldPolicyType) &&
|
||||
(oldPolicyType != nsIContentPolicy::TYPE_INVALID)) {
|
||||
prefetchService->CancelPrefetchPreloadURI(uri, mElement);
|
||||
}
|
||||
|
||||
// Trigger a new preload if the policy type has changed.
|
||||
// Also trigger load if the new policy type is invalid, this will only
|
||||
// trigger an error event.
|
||||
if ((policyType != oldPolicyType) ||
|
||||
(policyType == nsIContentPolicy::TYPE_INVALID)) {
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo = new ReferrerInfo();
|
||||
referrerInfo->InitWithNode(mElement);
|
||||
prefetchService->PreloadURI(uri, referrerInfo, mElement, policyType);
|
||||
}
|
||||
}
|
||||
|
||||
void Link::CancelPrefetchOrPreload() {
|
||||
nsCOMPtr<nsIPrefetchService> prefetchService(components::Prefetch::Service());
|
||||
if (prefetchService) {
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (uri) {
|
||||
prefetchService->CancelPrefetchPreloadURI(uri, mElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Link::SetLinkState(nsLinkState aState) {
|
||||
NS_ASSERTION(mRegistered, "Setting the link state of an unregistered Link!");
|
||||
NS_ASSERTION(mLinkState != aState,
|
||||
"Setting state to the currently set state!");
|
||||
MOZ_ASSERT(mRegistered, "Setting the link state of an unregistered Link!");
|
||||
MOZ_ASSERT(mLinkState != aState, "Setting state to the currently set state!");
|
||||
|
||||
// Set our current state as appropriate.
|
||||
mLinkState = aState;
|
||||
@ -344,6 +112,8 @@ void Link::SetLinkState(nsLinkState aState) {
|
||||
EventStates Link::LinkState() const {
|
||||
// We are a constant method, but we are just lazily doing things and have to
|
||||
// track that state. Cast away that constness!
|
||||
//
|
||||
// XXX(emilio): that's evil.
|
||||
Link* self = const_cast<Link*>(this);
|
||||
|
||||
Element* element = self->mElement;
|
||||
@ -744,8 +514,12 @@ void Link::ResetLinkState(bool aNotify, bool aHasHref) {
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an href, we should register with the history.
|
||||
mNeedsRegistration = aHasHref;
|
||||
// If we have an href, and we're not a <link>, we should register with the
|
||||
// history.
|
||||
//
|
||||
// FIXME(emilio): Do we really want to allow all MathML elements to be
|
||||
// :visited? That seems not great.
|
||||
mNeedsRegistration = aHasHref && !mElement->IsHTMLElement(nsGkAtoms::link);
|
||||
|
||||
// If we've cached the URI, reset always invalidates it.
|
||||
UnregisterFromHistory();
|
||||
@ -827,48 +601,5 @@ size_t Link::SizeOfExcludingThis(mozilla::SizeOfState& aState) const {
|
||||
return n;
|
||||
}
|
||||
|
||||
static const nsAttrValue::EnumTable kAsAttributeTable[] = {
|
||||
{"", DESTINATION_INVALID}, {"audio", DESTINATION_AUDIO},
|
||||
{"font", DESTINATION_FONT}, {"image", DESTINATION_IMAGE},
|
||||
{"script", DESTINATION_SCRIPT}, {"style", DESTINATION_STYLE},
|
||||
{"track", DESTINATION_TRACK}, {"video", DESTINATION_VIDEO},
|
||||
{"fetch", DESTINATION_FETCH}, {nullptr, 0}};
|
||||
|
||||
/* static */
|
||||
void Link::ParseAsValue(const nsAString& aValue, nsAttrValue& aResult) {
|
||||
DebugOnly<bool> success =
|
||||
aResult.ParseEnumValue(aValue, kAsAttributeTable, false,
|
||||
// default value is a empty string
|
||||
// if aValue is not a value we
|
||||
// understand
|
||||
&kAsAttributeTable[0]);
|
||||
MOZ_ASSERT(success);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsContentPolicyType Link::AsValueToContentPolicy(const nsAttrValue& aValue) {
|
||||
switch (aValue.GetEnumValue()) {
|
||||
case DESTINATION_INVALID:
|
||||
return nsIContentPolicy::TYPE_INVALID;
|
||||
case DESTINATION_AUDIO:
|
||||
return nsIContentPolicy::TYPE_INTERNAL_AUDIO;
|
||||
case DESTINATION_TRACK:
|
||||
return nsIContentPolicy::TYPE_INTERNAL_TRACK;
|
||||
case DESTINATION_VIDEO:
|
||||
return nsIContentPolicy::TYPE_INTERNAL_VIDEO;
|
||||
case DESTINATION_FONT:
|
||||
return nsIContentPolicy::TYPE_FONT;
|
||||
case DESTINATION_IMAGE:
|
||||
return nsIContentPolicy::TYPE_IMAGE;
|
||||
case DESTINATION_SCRIPT:
|
||||
return nsIContentPolicy::TYPE_SCRIPT;
|
||||
case DESTINATION_STYLE:
|
||||
return nsIContentPolicy::TYPE_STYLESHEET;
|
||||
case DESTINATION_FETCH:
|
||||
return nsIContentPolicy::TYPE_OTHER;
|
||||
}
|
||||
return nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -116,17 +116,11 @@ class Link : public nsISupports {
|
||||
|
||||
virtual bool ElementHasHref() const;
|
||||
|
||||
// This is called by HTMLAnchorElement.
|
||||
// This is called by HTMLAnchorElement and HTMLLinkElement.
|
||||
void TryDNSPrefetch();
|
||||
void CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
nsWrapperCache::FlagsType aRequestedFlag);
|
||||
|
||||
// This is called by HTMLLinkElement.
|
||||
void TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender();
|
||||
void UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue);
|
||||
void CancelPrefetchOrPreload();
|
||||
|
||||
bool HasPendingLinkUpdate() const { return mHasPendingLinkUpdate; }
|
||||
void SetHasPendingLinkUpdate() { mHasPendingLinkUpdate = true; }
|
||||
void ClearHasPendingLinkUpdate() { mHasPendingLinkUpdate = false; }
|
||||
@ -141,9 +135,6 @@ class Link : public nsISupports {
|
||||
void SetIsInDNSPrefetch() { mInDNSPrefetch = true; }
|
||||
void ClearIsInDNSPrefetch() { mInDNSPrefetch = false; }
|
||||
|
||||
static void ParseAsValue(const nsAString& aValue, nsAttrValue& aResult);
|
||||
static nsContentPolicyType AsValueToContentPolicy(const nsAttrValue& aValue);
|
||||
|
||||
protected:
|
||||
virtual ~Link();
|
||||
|
||||
@ -170,10 +161,6 @@ class Link : public nsISupports {
|
||||
|
||||
void SetHrefAttribute(nsIURI* aURI);
|
||||
|
||||
void GetContentPolicyMimeTypeMedia(nsAttrValue& aAsAttr,
|
||||
nsContentPolicyType& aPolicyType,
|
||||
nsString& aMimeType, nsAString& aMedia);
|
||||
|
||||
mutable nsCOMPtr<nsIURI> mCachedURI;
|
||||
|
||||
Element* const mElement;
|
||||
|
@ -30,12 +30,10 @@ void OnPrefChange(const char* aPrefName, void*) {
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> rootDocShell = window->GetDocShell();
|
||||
nsCOMPtr<nsISimpleEnumerator> docShellEnumerator;
|
||||
rootDocShell->GetDocShellEnumerator(nsIDocShell::typeAll,
|
||||
nsIDocShell::ENUMERATE_FORWARDS,
|
||||
getter_AddRefs(docShellEnumerator));
|
||||
NS_ENSURE_TRUE_VOID(docShellEnumerator);
|
||||
for (auto& docShell : SimpleEnumerator<nsIDocShell>(docShellEnumerator)) {
|
||||
nsTArray<RefPtr<nsIDocShell>> docShells;
|
||||
rootDocShell->GetAllDocShellsInSubtree(
|
||||
nsIDocShell::typeAll, nsIDocShell::ENUMERATE_FORWARDS, docShells);
|
||||
for (auto& docShell : docShells) {
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> win = do_GetInterface(docShell)) {
|
||||
if (dom::Document* doc = win->GetExtantDoc()) {
|
||||
doc->ResetDocumentDirection();
|
||||
|
@ -4,7 +4,6 @@
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
body {
|
||||
-moz-column-count: 2;
|
||||
column-count: 2;
|
||||
}
|
||||
svg {
|
||||
|
@ -231,7 +231,7 @@ load 1406109-1.html
|
||||
load 1411473.html
|
||||
load 1413815.html
|
||||
load 1419799.html
|
||||
skip-if(!browserIsRemote) pref(dom.disable_open_during_load,false) load 1419902.html # skip on non e10s loads, Bug 1419902
|
||||
skip-if(!browserIsRemote) skip-if(geckoview&&webrender) pref(dom.disable_open_during_load,false) load 1419902.html # skip on non e10s loads, Bug 1419902. Bug 1563013 for GV+WR
|
||||
load 1422883.html
|
||||
load 1428053.html
|
||||
load 1441029.html
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/ServoBindingTypes.h"
|
||||
#include "mozilla/ServoUtils.h"
|
||||
#include "mozilla/ShadowParts.h"
|
||||
#include "mozilla/DeclarationBlock.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
@ -279,6 +280,7 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
|
||||
cont->mValue.mColor = otherCont->mValue.mColor;
|
||||
break;
|
||||
}
|
||||
case eShadowParts:
|
||||
case eCSSDeclaration: {
|
||||
MOZ_CRASH("These should be refcounted!");
|
||||
}
|
||||
@ -299,9 +301,10 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
|
||||
break;
|
||||
}
|
||||
case eIntMarginValue: {
|
||||
if (otherCont->mValue.mIntMargin)
|
||||
if (otherCont->mValue.mIntMargin) {
|
||||
cont->mValue.mIntMargin =
|
||||
new nsIntMargin(*otherCont->mValue.mIntMargin);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -1153,7 +1156,7 @@ void nsAttrValue::ParseAtomArray(const nsAString& aValue) {
|
||||
void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) {
|
||||
uint32_t len = aValue.Length();
|
||||
// Don't bother with atoms if it's an empty string since
|
||||
// we can store those efficently anyway.
|
||||
// we can store those efficiently anyway.
|
||||
if (len && len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
|
||||
ParseAtom(aValue);
|
||||
} else {
|
||||
@ -1161,6 +1164,17 @@ void nsAttrValue::ParseStringOrAtom(const nsAString& aValue) {
|
||||
}
|
||||
}
|
||||
|
||||
void nsAttrValue::ParsePartMapping(const nsAString& aValue) {
|
||||
ResetIfSet();
|
||||
MiscContainer* cont = EnsureEmptyMiscContainer();
|
||||
|
||||
cont->mType = eShadowParts;
|
||||
cont->mValue.mShadowParts = new ShadowParts(ShadowParts::Parse(aValue));
|
||||
NS_ADDREF(cont);
|
||||
SetMiscAtomOrString(&aValue);
|
||||
MOZ_ASSERT(cont->mValue.mRefCount == 1);
|
||||
}
|
||||
|
||||
void nsAttrValue::SetIntValueAndType(int32_t aValue, ValueType aType,
|
||||
const nsAString* aStringValue) {
|
||||
if (aStringValue || aValue > NS_ATTRVALUE_INTEGERTYPE_MAXVALUE ||
|
||||
@ -1271,7 +1285,7 @@ bool nsAttrValue::DoParseHTMLDimension(const nsAString& aInput,
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#rules-for-parsing-dimension-values
|
||||
|
||||
// Step 1 and 2.
|
||||
// Steps 1 and 2.
|
||||
const char16_t* position = aInput.BeginReading();
|
||||
const char16_t* end = aInput.EndReading();
|
||||
|
||||
@ -1280,36 +1294,19 @@ bool nsAttrValue::DoParseHTMLDimension(const nsAString& aInput,
|
||||
// leading '0' characters, or trailing garbage.
|
||||
bool canonical = true;
|
||||
|
||||
// Step 3
|
||||
// Step 3.
|
||||
while (position != end && nsContentUtils::IsHTMLWhitespace(*position)) {
|
||||
canonical = false; // Leading whitespace
|
||||
++position;
|
||||
}
|
||||
|
||||
// Step 4
|
||||
if (position == end) {
|
||||
// Step 4.
|
||||
if (position == end || *position < char16_t('0') ||
|
||||
*position > char16_t('9')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
if (*position == char16_t('+')) {
|
||||
canonical = false; // Leading '+'
|
||||
++position;
|
||||
|
||||
// Step 6. The spec has this happening regardless of whether we found '+',
|
||||
// but there's no point repeating the step 4 test if we didn't advance
|
||||
// position.
|
||||
if (position == end) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7.
|
||||
if (*position < char16_t('0') || *position > char16_t('9')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 8.
|
||||
// Step 5.
|
||||
CheckedInt32 value = 0;
|
||||
|
||||
// Collect up leading '0' first to avoid extra branching in the main
|
||||
@ -1332,28 +1329,35 @@ bool nsAttrValue::DoParseHTMLDimension(const nsAString& aInput,
|
||||
++position;
|
||||
}
|
||||
|
||||
// Step 9 is implemented implicitly via the various "position != end" guards
|
||||
// Step 6 is implemented implicitly via the various "position != end" guards
|
||||
// from this point on.
|
||||
|
||||
Maybe<double> doubleValue;
|
||||
// Step 10.
|
||||
// Step 7. The return in step 7.2 is handled by just falling through to the
|
||||
// code below this block when we reach end of input or a non-digit, because
|
||||
// the while loop will terminate at that point.
|
||||
if (position != end && *position == char16_t('.')) {
|
||||
canonical = false; // Let's not rely on double serialization reproducing
|
||||
// the string we started with.
|
||||
// Step 7.1.
|
||||
++position;
|
||||
// If we have a '.' _not_ followed by digits, this is not as efficient as it
|
||||
// could be, because we will store as a double while we could have stored as
|
||||
// an int. But that seems like a pretty rare case.
|
||||
doubleValue.emplace(value.value());
|
||||
// Step 7.3.
|
||||
double divisor = 1.0f;
|
||||
// Per spec we should now return a number if there is no next char or if the
|
||||
// next char is not a digit, but no one does that. See
|
||||
// https://github.com/whatwg/html/issues/4736
|
||||
// Step 7.4.
|
||||
while (position != end && *position >= char16_t('0') &&
|
||||
*position <= char16_t('9')) {
|
||||
// Step 7.4.1.
|
||||
divisor = divisor * 10.0f;
|
||||
// Step 7.4.2.
|
||||
doubleValue.ref() += (*position - char16_t('0')) / divisor;
|
||||
// Step 7.4.3.
|
||||
++position;
|
||||
// Step 7.4.4 and 7.4.5 are captured in the while loop condition and the
|
||||
// "position != end" checks below.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1363,7 +1367,7 @@ bool nsAttrValue::DoParseHTMLDimension(const nsAString& aInput,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 11-13.
|
||||
// Step 8 and the spec's early return from step 7.2.
|
||||
ValueType type;
|
||||
if (position != end && *position == char16_t('%')) {
|
||||
type = ePercent;
|
||||
@ -1748,6 +1752,12 @@ MiscContainer* nsAttrValue::ClearMiscContainer() {
|
||||
NS_RELEASE(cont->mValue.mCSSDeclaration);
|
||||
break;
|
||||
}
|
||||
case eShadowParts: {
|
||||
MOZ_ASSERT(cont->mValue.mRefCount == 1);
|
||||
cont->Release();
|
||||
delete cont->mValue.mShadowParts;
|
||||
break;
|
||||
}
|
||||
case eURL: {
|
||||
NS_RELEASE(cont->mValue.mURL);
|
||||
break;
|
||||
|
@ -34,6 +34,7 @@ struct MiscContainer;
|
||||
|
||||
namespace mozilla {
|
||||
class DeclarationBlock;
|
||||
class ShadowParts;
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
|
||||
@ -99,6 +100,10 @@ class nsAttrValue {
|
||||
eAtomArray,
|
||||
eDoubleValue,
|
||||
eIntMarginValue,
|
||||
// eShadowParts is refcounted in the misc container, as we do copy attribute
|
||||
// values quite a bit (for example to process style invalidation), and the
|
||||
// underlying value could get expensive to copy.
|
||||
eShadowParts,
|
||||
eSVGIntegerPair,
|
||||
eSVGTypesBegin = eSVGIntegerPair,
|
||||
eSVGOrient,
|
||||
@ -206,6 +211,7 @@ class nsAttrValue {
|
||||
inline nsIURI* GetURLValue() const;
|
||||
inline double GetDoubleValue() const;
|
||||
bool GetIntMarginValue(nsIntMargin& aMargin) const;
|
||||
inline const mozilla::ShadowParts& GetShadowPartsValue() const;
|
||||
|
||||
/**
|
||||
* Returns the string corresponding to the stored enum value.
|
||||
@ -254,6 +260,13 @@ class nsAttrValue {
|
||||
void ParseAtomArray(const nsAString& aValue);
|
||||
void ParseStringOrAtom(const nsAString& aValue);
|
||||
|
||||
/**
|
||||
* Parses an exportparts attribute.
|
||||
*
|
||||
* https://drafts.csswg.org/css-shadow-parts/#parsing-mapping-list
|
||||
*/
|
||||
void ParsePartMapping(const nsAString&);
|
||||
|
||||
/**
|
||||
* Structure for a mapping from int (enum) values to strings. When you use
|
||||
* it you generally create an array of them.
|
||||
@ -417,12 +430,6 @@ class nsAttrValue {
|
||||
*/
|
||||
bool ParseDoubleValue(const nsAString& aString);
|
||||
|
||||
/**
|
||||
* Parse a lazy URI. This just sets up the storage for the URI; it
|
||||
* doesn't actually allocate it.
|
||||
*/
|
||||
bool ParseLazyURIValue(const nsAString& aString);
|
||||
|
||||
/**
|
||||
* Parse a margin string of format 'top, right, bottom, left' into
|
||||
* an nsIntMargin.
|
||||
|
@ -12,7 +12,9 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ServoUtils.h"
|
||||
|
||||
struct MiscContainer;
|
||||
namespace mozilla {
|
||||
class ShadowParts;
|
||||
}
|
||||
|
||||
struct MiscContainer final {
|
||||
typedef nsAttrValue::ValueType ValueType;
|
||||
@ -41,6 +43,7 @@ struct MiscContainer final {
|
||||
nsIURI* mURL;
|
||||
mozilla::AtomArray* mAtomArray;
|
||||
nsIntMargin* mIntMargin;
|
||||
const mozilla::ShadowParts* mShadowParts;
|
||||
const mozilla::SVGAnimatedIntegerPair* mSVGAnimatedIntegerPair;
|
||||
const mozilla::SVGAnimatedLength* mSVGLength;
|
||||
const mozilla::SVGAnimatedNumberPair* mSVGAnimatedNumberPair;
|
||||
@ -95,7 +98,8 @@ struct MiscContainer final {
|
||||
// Nothing stops us from refcounting (and sharing) other types of
|
||||
// MiscContainer (except eDoubleValue types) but there's no compelling
|
||||
// reason to.
|
||||
return mType == nsAttrValue::eCSSDeclaration;
|
||||
return mType == nsAttrValue::eCSSDeclaration ||
|
||||
mType == nsAttrValue::eShadowParts;
|
||||
}
|
||||
|
||||
inline int32_t AddRef() {
|
||||
@ -247,4 +251,9 @@ inline void nsAttrValue::ToString(mozilla::dom::DOMString& aResult) const {
|
||||
}
|
||||
}
|
||||
|
||||
inline const mozilla::ShadowParts& nsAttrValue::GetShadowPartsValue() const {
|
||||
MOZ_ASSERT(Type() == eShadowParts);
|
||||
return *GetMiscContainer()->mValue.mShadowParts;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -797,8 +797,8 @@ void nsContentSink::PrefetchPreloadHref(const nsAString& aHref,
|
||||
|
||||
if (preload) {
|
||||
nsAttrValue asAttr;
|
||||
Link::ParseAsValue(aAs, asAttr);
|
||||
policyType = Link::AsValueToContentPolicy(asAttr);
|
||||
HTMLLinkElement::ParseAsValue(aAs, asAttr);
|
||||
policyType = HTMLLinkElement::AsValueToContentPolicy(asAttr);
|
||||
|
||||
if (policyType == nsIContentPolicy::TYPE_INVALID) {
|
||||
// Ignore preload with a wrong or empty as attribute.
|
||||
|
@ -2872,8 +2872,7 @@ bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
|
||||
|
||||
uint32_t i = 1;
|
||||
while (i < len) {
|
||||
if (NS_IS_HIGH_SURROGATE(name[i]) && i + 1 < len &&
|
||||
NS_IS_LOW_SURROGATE(name[i + 1])) {
|
||||
if (i + 1 < len && NS_IS_SURROGATE_PAIR(name[i], name[i + 1])) {
|
||||
// Merged two 16-bit surrogate pairs into code point.
|
||||
char32_t code = SURROGATE_TO_UCS4(name[i], name[i + 1]);
|
||||
|
||||
|
@ -107,6 +107,7 @@
|
||||
#include "mozilla/PreloadedStyleSheet.h"
|
||||
#include "mozilla/layers/WebRenderBridgeChild.h"
|
||||
#include "mozilla/layers/WebRenderLayerManager.h"
|
||||
#include "mozilla/ResultExtensions.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# undef GetClassName
|
||||
@ -462,16 +463,6 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
|
||||
new DisplayPortPropertyData(displayport, aPriority),
|
||||
nsINode::DeleteProperty<DisplayPortPropertyData>);
|
||||
|
||||
if (StaticPrefs::layout_scroll_root_frame_containers()) {
|
||||
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
||||
if (rootScrollFrame && aElement == rootScrollFrame->GetContent() &&
|
||||
nsLayoutUtils::UsesAsyncScrolling(rootScrollFrame)) {
|
||||
// We are setting a root displayport for a document.
|
||||
// The pres shell needs a special flag set.
|
||||
presShell->SetIgnoreViewportScrolling(true);
|
||||
}
|
||||
}
|
||||
|
||||
nsLayoutUtils::InvalidateForDisplayPortChange(aElement, hadDisplayPort,
|
||||
oldDisplayPort, displayport);
|
||||
|
||||
@ -559,7 +550,7 @@ nsDOMWindowUtils::SetResolutionAndScaleTo(float aResolution) {
|
||||
}
|
||||
|
||||
presShell->SetResolutionAndScaleTo(aResolution,
|
||||
ResolutionChangeOrigin::MainThread);
|
||||
ResolutionChangeOrigin::MainThreadRestore);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3436,7 +3427,11 @@ nsDOMWindowUtils::GetOMTAStyle(Element* aElement, const nsAString& aProperty,
|
||||
} else if (aProperty.EqualsLiteral("transform") ||
|
||||
aProperty.EqualsLiteral("translate") ||
|
||||
aProperty.EqualsLiteral("rotate") ||
|
||||
aProperty.EqualsLiteral("scale")) {
|
||||
aProperty.EqualsLiteral("scale") ||
|
||||
aProperty.EqualsLiteral("offset-path") ||
|
||||
aProperty.EqualsLiteral("offset-distance") ||
|
||||
aProperty.EqualsLiteral("offset-rotate") ||
|
||||
aProperty.EqualsLiteral("offset-anchor")) {
|
||||
OMTAValue value = GetOMTAValue(frame, DisplayItemType::TYPE_TRANSFORM,
|
||||
GetWebRenderBridge());
|
||||
if (value.type() == OMTAValue::TMatrix4x4) {
|
||||
@ -3663,7 +3658,7 @@ nsDOMWindowUtils::PostRestyleSelfEvent(Element* aElement) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsLayoutUtils::PostRestyleEvent(aElement, StyleRestyleHint_RESTYLE_SELF,
|
||||
nsLayoutUtils::PostRestyleEvent(aElement, RestyleHint::RESTYLE_SELF,
|
||||
nsChangeHint(0));
|
||||
return NS_OK;
|
||||
}
|
||||
@ -4081,14 +4076,60 @@ NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetCompositionRecording(bool aValue) {
|
||||
if (CompositorBridgeChild* cbc = GetCompositorBridge()) {
|
||||
if (aValue) {
|
||||
cbc->SendBeginRecording(TimeStamp::Now());
|
||||
RefPtr<nsDOMWindowUtils> self = this;
|
||||
cbc->SendBeginRecording(TimeStamp::Now())
|
||||
->Then(
|
||||
GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[self](const bool& aSuccess) {
|
||||
if (!aSuccess) {
|
||||
self->ReportErrorMessageForWindow(
|
||||
NS_LITERAL_STRING(
|
||||
"The composition recorder is already running."),
|
||||
"DOM", true);
|
||||
}
|
||||
},
|
||||
[self](const mozilla::ipc::ResponseRejectReason&) {
|
||||
self->ReportErrorMessageForWindow(
|
||||
NS_LITERAL_STRING(
|
||||
"Could not start the composition recorder."),
|
||||
"DOM", true);
|
||||
});
|
||||
} else {
|
||||
cbc->SendEndRecording();
|
||||
bool success = false;
|
||||
if (!cbc->SendEndRecording(&success)) {
|
||||
ReportErrorMessageForWindow(
|
||||
NS_LITERAL_STRING("Could not stop the composition recorder."),
|
||||
"DOM", true);
|
||||
} else if (!success) {
|
||||
ReportErrorMessageForWindow(
|
||||
NS_LITERAL_STRING("The composition recorder is not running."),
|
||||
"DOM", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsDOMWindowUtils::ReportErrorMessageForWindow(
|
||||
const nsAString& aErrorMessage, const char* aClassification,
|
||||
bool aFromChrome) {
|
||||
bool isPrivateWindow = false;
|
||||
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow)) {
|
||||
if (nsIPrincipal* principal =
|
||||
nsGlobalWindowOuter::Cast(window)->GetPrincipal()) {
|
||||
uint32_t privateBrowsingId = 0;
|
||||
|
||||
if (NS_SUCCEEDED(principal->GetPrivateBrowsingId(&privateBrowsingId))) {
|
||||
isPrivateWindow = !!privateBrowsingId;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsContentUtils::LogSimpleConsoleError(aErrorMessage, aClassification,
|
||||
isPrivateWindow, aFromChrome);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetSystemFont(const nsACString& aFontName) {
|
||||
nsIWidget* widget = GetWidget();
|
||||
@ -4112,3 +4153,9 @@ nsDOMWindowUtils::GetSystemFont(nsACString& aFontName) {
|
||||
aFontName.Assign(fontName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetUsesOverlayScrollbars(bool* aResult) {
|
||||
*aResult = Document::UseOverlayScrollbars(GetDocument());
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -99,6 +99,10 @@ class nsDOMWindowUtils final : public nsIDOMWindowUtils,
|
||||
const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
|
||||
int32_t aModifiers, bool aIgnoreRootScrollFrame, bool aToWindow,
|
||||
bool* aPreventDefault);
|
||||
|
||||
void ReportErrorMessageForWindow(const nsAString& aErrorMessage,
|
||||
const char* aClassification,
|
||||
bool aFromChrome);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3877,6 +3877,11 @@ void nsGlobalWindowOuter::SetCSSViewportWidthAndHeight(nscoord aInnerWidth,
|
||||
shellArea.SetHeight(aInnerHeight);
|
||||
shellArea.SetWidth(aInnerWidth);
|
||||
|
||||
// FIXME(emilio): This doesn't seem to be ok, this doesn't reflow or
|
||||
// anything... Should go through PresShell::ResizeReflow.
|
||||
//
|
||||
// But I don't think this can be reached by content, as we don't allow to set
|
||||
// inner{Width,Height}.
|
||||
presContext->SetVisibleArea(shellArea);
|
||||
}
|
||||
|
||||
|
@ -585,9 +585,12 @@ class nsINode : public mozilla::dom::EventTarget {
|
||||
nsIContent* GetChildAt_Deprecated(uint32_t aIndex) const;
|
||||
|
||||
/**
|
||||
* Get the index of a child within this content
|
||||
* Get the index of a child within this content.
|
||||
*
|
||||
* @param aPossibleChild the child to get the index of.
|
||||
* @return the index of the child, or -1 if not a child
|
||||
* @return the index of the child, or -1 if not a child. Be aware that
|
||||
* anonymous children (e.g. a <div> child of an <input> element) will
|
||||
* result in -1.
|
||||
*
|
||||
* If the return value is not -1, then calling GetChildAt_Deprecated() with
|
||||
* that value will return aPossibleChild.
|
||||
@ -763,6 +766,11 @@ class nsINode : public mozilla::dom::EventTarget {
|
||||
return isShadowRoot;
|
||||
}
|
||||
|
||||
bool IsHTMLHeadingElement() const {
|
||||
return IsAnyOfHTMLElements(nsGkAtoms::h1, nsGkAtoms::h2, nsGkAtoms::h3,
|
||||
nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a content node before another or at the end.
|
||||
* This method handles calling BindToTree on the child appropriately.
|
||||
|
@ -39,8 +39,7 @@ static void SetupCapitalization(const char16_t* aWord, uint32_t aLength,
|
||||
for (uint32_t i = 0; i < aLength; ++i) {
|
||||
uint32_t ch = aWord[i];
|
||||
if (capitalizeNextChar) {
|
||||
if (NS_IS_HIGH_SURROGATE(ch) && i + 1 < aLength &&
|
||||
NS_IS_LOW_SURROGATE(aWord[i + 1])) {
|
||||
if (i + 1 < aLength && NS_IS_SURROGATE_PAIR(ch, aWord[i + 1])) {
|
||||
ch = SURROGATE_TO_UCS4(ch, aWord[i + 1]);
|
||||
}
|
||||
if (nsContentUtils::IsAlphanumeric(ch)) {
|
||||
|
@ -132,7 +132,7 @@ nsICSSDeclaration* nsStyledElement::Style() {
|
||||
|
||||
if (!slots->mStyle) {
|
||||
// Just in case...
|
||||
ReparseStyleAttribute(true, false);
|
||||
ReparseStyleAttribute(/* aForceInDataDoc */ true);
|
||||
|
||||
slots->mStyle = new nsDOMCSSAttributeDeclaration(this, false);
|
||||
SetMayHaveStyle();
|
||||
@ -141,14 +141,12 @@ nsICSSDeclaration* nsStyledElement::Style() {
|
||||
return slots->mStyle;
|
||||
}
|
||||
|
||||
nsresult nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc,
|
||||
bool aForceIfAlreadyParsed) {
|
||||
nsresult nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc) {
|
||||
if (!MayHaveStyle()) {
|
||||
return NS_OK;
|
||||
}
|
||||
const nsAttrValue* oldVal = mAttrs.GetAttr(nsGkAtoms::style);
|
||||
if (oldVal && (aForceIfAlreadyParsed ||
|
||||
oldVal->Type() != nsAttrValue::eCSSDeclaration)) {
|
||||
if (oldVal && oldVal->Type() != nsAttrValue::eCSSDeclaration) {
|
||||
nsAttrValue attrValue;
|
||||
nsAutoString stringValue;
|
||||
oldVal->ToString(stringValue);
|
||||
@ -164,10 +162,6 @@ nsresult nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsStyledElement::NodeInfoChanged(Document* aOldDoc) {
|
||||
nsStyledElementBase::NodeInfoChanged(aOldDoc);
|
||||
}
|
||||
|
||||
nsICSSDeclaration* nsStyledElement::GetExistingStyle() {
|
||||
Element::nsDOMSlots* slots = GetExistingDOMSlots();
|
||||
if (!slots) {
|
||||
|
@ -80,13 +80,9 @@ class nsStyledElement : public nsStyledElementBase {
|
||||
* Create the style struct from the style attr. Used when an element is
|
||||
* first put into a document. Only has an effect if the old value is a
|
||||
* string. If aForceInDataDoc is true, will reparse even if we're in a data
|
||||
* document. If aForceIfAlreadyParsed is set, this will always reparse even
|
||||
* if the value has already been parsed.
|
||||
* document.
|
||||
*/
|
||||
nsresult ReparseStyleAttribute(bool aForceInDataDoc,
|
||||
bool aForceIfAlreadyParsed);
|
||||
|
||||
virtual void NodeInfoChanged(mozilla::dom::Document* aOldDoc) override;
|
||||
nsresult ReparseStyleAttribute(bool aForceInDataDoc);
|
||||
|
||||
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
|
||||
const nsAttrValueOrString* aValue,
|
||||
|
@ -225,8 +225,7 @@ class nsTextFragment final {
|
||||
if (!mState.mIs2b || aIndex + 1 >= mState.mLength) {
|
||||
return false;
|
||||
}
|
||||
return NS_IS_HIGH_SURROGATE(Get2b()[aIndex]) &&
|
||||
NS_IS_LOW_SURROGATE(Get2b()[aIndex + 1]);
|
||||
return NS_IS_SURROGATE_PAIR(Get2b()[aIndex], Get2b()[aIndex + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,8 +238,7 @@ class nsTextFragment final {
|
||||
if (!mState.mIs2b || aIndex <= 0) {
|
||||
return false;
|
||||
}
|
||||
return NS_IS_LOW_SURROGATE(Get2b()[aIndex]) &&
|
||||
NS_IS_HIGH_SURROGATE(Get2b()[aIndex - 1]);
|
||||
return NS_IS_SURROGATE_PAIR(Get2b()[aIndex - 1], Get2b()[aIndex]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,11 @@
|
||||
using namespace mozilla;
|
||||
|
||||
void nsViewportInfo::ConstrainViewportValues() {
|
||||
// Non-positive zoom factors can produce NaN or negative viewport sizes,
|
||||
// so we better be sure our constraints will produce positive zoom factors.
|
||||
MOZ_ASSERT(mMinZoom > CSSToScreenScale(0.0f), "zoom factor must be positive");
|
||||
MOZ_ASSERT(mMaxZoom > CSSToScreenScale(0.0f), "zoom factor must be positive");
|
||||
|
||||
if (mDefaultZoom > mMaxZoom) {
|
||||
mDefaultZoomValid = false;
|
||||
mDefaultZoom = mMaxZoom;
|
||||
|
@ -348,6 +348,11 @@ static void CollectWindowReports(nsGlobalWindowInner* aWindow,
|
||||
"allocated in its arena and not measured elsewhere, "
|
||||
"within a window.");
|
||||
|
||||
REPORT_SIZE("/layout/display-list", mLayoutRetainedDisplayListSize,
|
||||
"Memory used by the retained display list data, "
|
||||
"along with any structures allocated in its arena and not "
|
||||
"measured elsewhere, within a window.");
|
||||
|
||||
REPORT_SIZE("/layout/style-sets/stylist/rule-tree",
|
||||
mLayoutStyleSetsStylistRuleTree,
|
||||
"Memory used by rule trees within style sets within a window.");
|
||||
@ -415,8 +420,52 @@ static void CollectWindowReports(nsGlobalWindowInner* aWindow,
|
||||
"Number of event listeners in a window, including event "
|
||||
"listeners on nodes and other event targets.");
|
||||
|
||||
REPORT_SIZE("/layout/line-boxes", mArenaSizes.mLineBoxes,
|
||||
"Memory used by line boxes within a window.");
|
||||
// There are many different kinds of frames, but it is very likely
|
||||
// that only a few matter. Implement a cutoff so we don't bloat
|
||||
// about:memory with many uninteresting entries.
|
||||
const size_t ARENA_SUNDRIES_THRESHOLD =
|
||||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
size_t presArenaSundriesSize = 0;
|
||||
#define ARENA_OBJECT(name_, sundries_size_, prefix_) \
|
||||
{ \
|
||||
size_t size = windowSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_); \
|
||||
if (size < ARENA_SUNDRIES_THRESHOLD) { \
|
||||
sundries_size_ += size; \
|
||||
} else { \
|
||||
REPORT_SUM_SIZE(prefix_ #name_, size, \
|
||||
"Memory used by objects of type " #name_ \
|
||||
" within a window."); \
|
||||
} \
|
||||
aWindowTotalSizes->mArenaSizes.NS_ARENA_SIZES_FIELD(name_) += size; \
|
||||
}
|
||||
#define PRES_ARENA_OBJECT(name_) \
|
||||
ARENA_OBJECT(name_, presArenaSundriesSize, "/layout/pres-arena/")
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
|
||||
if (presArenaSundriesSize > 0) {
|
||||
REPORT_SUM_SIZE(
|
||||
"/layout/pres-arena/sundries", presArenaSundriesSize,
|
||||
"The sum of all memory used by objects in the arena which were too "
|
||||
"small to be shown individually.");
|
||||
}
|
||||
|
||||
size_t displayListArenaSundriesSize = 0;
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) \
|
||||
ARENA_OBJECT(name_, displayListArenaSundriesSize, \
|
||||
"/layout/display-list-arena/")
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
if (displayListArenaSundriesSize > 0) {
|
||||
REPORT_SUM_SIZE(
|
||||
"/layout/display-list-arena/sundries", displayListArenaSundriesSize,
|
||||
"The sum of all memory used by objects in the DL arena which were too "
|
||||
"small to be shown individually.");
|
||||
}
|
||||
|
||||
#undef ARENA_OBJECT
|
||||
|
||||
// There are many different kinds of style structs, but it is likely that
|
||||
// only a few matter. Implement a cutoff so we don't bloat about:memory with
|
||||
@ -424,38 +473,6 @@ static void CollectWindowReports(nsGlobalWindowInner* aWindow,
|
||||
const size_t STYLE_SUNDRIES_THRESHOLD =
|
||||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
// There are many different kinds of frames, but it is very likely
|
||||
// that only a few matter. Implement a cutoff so we don't bloat
|
||||
// about:memory with many uninteresting entries.
|
||||
const size_t FRAME_SUNDRIES_THRESHOLD =
|
||||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
size_t frameSundriesSize = 0;
|
||||
#define FRAME_ID(classname, ...) \
|
||||
{ \
|
||||
size_t size = windowSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname); \
|
||||
if (size < FRAME_SUNDRIES_THRESHOLD) { \
|
||||
frameSundriesSize += size; \
|
||||
} else { \
|
||||
REPORT_SUM_SIZE("/layout/frames/" #classname, size, \
|
||||
"Memory used by frames of type " #classname \
|
||||
" within a window."); \
|
||||
} \
|
||||
aWindowTotalSizes->mArenaSizes.NS_ARENA_SIZES_FIELD(classname) += size; \
|
||||
}
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
|
||||
if (frameSundriesSize > 0) {
|
||||
REPORT_SUM_SIZE(
|
||||
"/layout/frames/sundries", frameSundriesSize,
|
||||
"The sum of all memory used by frames which were too small to be shown "
|
||||
"individually.");
|
||||
}
|
||||
|
||||
// This is the style structs.
|
||||
size_t styleSundriesSize = 0;
|
||||
#define STYLE_STRUCT(name_) \
|
||||
{ \
|
||||
@ -637,21 +654,26 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
REPORT("window-objects/property-tables", windowTotalSizes.mPropertyTablesSize,
|
||||
"This is the sum of all windows' 'property-tables' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/line-boxes",
|
||||
windowTotalSizes.mArenaSizes.mLineBoxes,
|
||||
"This is the sum of all windows' 'layout/line-boxes' numbers.");
|
||||
size_t presArenaTotal = 0;
|
||||
#define PRES_ARENA_OBJECT(name_) \
|
||||
presArenaTotal += windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_);
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
|
||||
size_t frameTotal = 0;
|
||||
#define FRAME_ID(classname, ...) \
|
||||
frameTotal += windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
REPORT("window-objects/layout/pres-arena", presArenaTotal,
|
||||
"Memory used for the pres arena within windows. "
|
||||
"This is the sum of all windows' 'layout/pres-arena/' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/frames", frameTotal,
|
||||
"Memory used for layout frames within windows. "
|
||||
"This is the sum of all windows' 'layout/frames/' numbers.");
|
||||
size_t displayListArenaTotal = 0;
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) \
|
||||
displayListArenaTotal += \
|
||||
windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_);
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
REPORT("window-objects/layout/display-list-arena", displayListArenaTotal,
|
||||
"Memory used for the display list arena within windows. This is the "
|
||||
"sum of all windows' 'layout/display-list-arena/' numbers.");
|
||||
|
||||
size_t styleTotal = 0;
|
||||
#define STYLE_STRUCT(name_) \
|
||||
|
@ -85,56 +85,49 @@ struct nsStyleSizes {
|
||||
#define NS_ARENA_SIZES_FIELD(classname) mArena##classname
|
||||
|
||||
struct nsArenaSizes {
|
||||
#define FOR_EACH_SIZE(MACRO) MACRO(Other, mLineBoxes)
|
||||
|
||||
nsArenaSizes()
|
||||
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||
#define FRAME_ID(classname, ...) NS_ARENA_SIZES_FIELD(classname)(0),
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
|
||||
dummy() {
|
||||
:
|
||||
#define PRES_ARENA_OBJECT(name_) NS_ARENA_SIZES_FIELD(name_)(0),
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
dummy() {
|
||||
}
|
||||
|
||||
void addToTabSizes(nsTabSizes* aSizes) const {
|
||||
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
||||
|
||||
#define FRAME_ID(classname, ...) \
|
||||
aSizes->add(nsTabSizes::Other, NS_ARENA_SIZES_FIELD(classname));
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
#define PRES_ARENA_OBJECT(name_) \
|
||||
aSizes->add(nsTabSizes::Other, NS_ARENA_SIZES_FIELD(name_));
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
}
|
||||
|
||||
size_t getTotalSize() const {
|
||||
size_t total = 0;
|
||||
|
||||
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
|
||||
|
||||
#define FRAME_ID(classname, ...) total += NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
#define PRES_ARENA_OBJECT(name_) total += NS_ARENA_SIZES_FIELD(name_);
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
FOR_EACH_SIZE(DECL_SIZE)
|
||||
|
||||
#define FRAME_ID(classname, ...) size_t NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
#define PRES_ARENA_OBJECT(name_) size_t NS_ARENA_SIZES_FIELD(name_);
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
// Present just to absorb the trailing comma in the constructor.
|
||||
int dummy;
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
||||
class nsWindowSizes {
|
||||
@ -152,6 +145,7 @@ class nsWindowSizes {
|
||||
MACRO(Style, mLayoutShadowDomStyleSheetsSize) \
|
||||
MACRO(Style, mLayoutShadowDomAuthorStyles) \
|
||||
MACRO(Other, mLayoutPresShellSize) \
|
||||
MACRO(Other, mLayoutRetainedDisplayListSize) \
|
||||
MACRO(Style, mLayoutStyleSetsStylistRuleTree) \
|
||||
MACRO(Style, mLayoutStyleSetsStylistElementAndPseudosMaps) \
|
||||
MACRO(Style, mLayoutStyleSetsStylistInvalidationMap) \
|
||||
|
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=0.5">
|
||||
<style>
|
||||
html {
|
||||
scrollbar-width: none; /* avoid scrollbar width is included in some metrics */
|
||||
}
|
||||
html, body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: none;
|
||||
}
|
||||
#twice-width {
|
||||
width: 200%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
<div id="twice-width"></div>
|
||||
<script>
|
||||
|
||||
const is = opener.is.bind(opener);
|
||||
const todo_is = opener.todo_is.bind(opener);
|
||||
const add_task = opener.add_task.bind(opener);
|
||||
const original_finish = opener.SimpleTest.finish;
|
||||
const SimpleTest = opener.SimpleTest;
|
||||
|
||||
SimpleTest.finish = function finish() {
|
||||
self.close();
|
||||
original_finish();
|
||||
}
|
||||
|
||||
add_task(async () => {
|
||||
// Explicitly set to 0.5x so that this test doesn't need to reply on our
|
||||
// auto initial-scale calculation.
|
||||
SpecialPowers.getDOMWindowUtils(window).setResolutionAndScaleTo(0.5);
|
||||
is(window.visualViewport.scale, 0.5, "The content should be scaled by 0.5x");
|
||||
|
||||
// Now the visual viewport size is same as the layout viewport.
|
||||
const layoutViewportHeight = window.visualViewport.height;
|
||||
|
||||
is(window.innerHeight, layoutViewportHeight,
|
||||
"window.innerHeight should reflect the layout viewport");
|
||||
is(document.documentElement.scrollHeight, layoutViewportHeight,
|
||||
"The root element's scrollHeight should be the layout viewport height");
|
||||
is(document.documentElement.getBoundingClientRect().height,
|
||||
layoutViewportHeight / 2,
|
||||
"The content height should be half of the layout viewport height");
|
||||
|
||||
// Set scale to 1.0x so that the visual viport size becomes 0.5x of the layout
|
||||
// viewport.
|
||||
SpecialPowers.getDOMWindowUtils(window).setResolutionAndScaleTo(1);
|
||||
is(window.visualViewport.scale, 1, "The content should be scaled by 1.0x");
|
||||
is(window.visualViewport.height, layoutViewportHeight / 2,
|
||||
"Now the visual viewport height should be changed to half of the layout " +
|
||||
"viewport height");
|
||||
todo_is(window.innerHeight, layoutViewportHeight,
|
||||
"window.innerHeight shouldn't be changed (Bug 1514429)");
|
||||
is(document.documentElement.scrollHeight, layoutViewportHeight,
|
||||
"The root element's scrollHeight shouldn't be changed");
|
||||
});
|
||||
</script>
|
||||
</html>
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/dom/SimpleGlobalObject.h"
|
||||
|
||||
|
@ -837,6 +837,9 @@ support-files = file_title.xul
|
||||
[test_treewalker_nextsibling.xml]
|
||||
[test_user_select.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_viewport_metrics_on_landscape_content.html]
|
||||
support-files =
|
||||
file_viewport_metrics_on_landscape_content.html
|
||||
[test_viewport_scroll.html]
|
||||
[test_viewsource_forbidden_in_object.html]
|
||||
[test_w3element_traversal.html]
|
||||
|
@ -60,19 +60,19 @@ function checkIndividualResults(testname, expected) {
|
||||
testname + " test: some image loads required in results object."
|
||||
);
|
||||
is(
|
||||
results["img"].count,
|
||||
results.img.count,
|
||||
2,
|
||||
testname + " Test: Expected 2 loads for image requests."
|
||||
);
|
||||
|
||||
expected.forEach(function(ref) {
|
||||
ok(
|
||||
results["img"].referrers.includes(ref),
|
||||
results.img.referrers.includes(ref),
|
||||
testname +
|
||||
" Test: Expected " +
|
||||
ref +
|
||||
" referrer policy in test, results were " +
|
||||
JSON.stringify(results["img"].referrers) +
|
||||
JSON.stringify(results.img.referrers) +
|
||||
"."
|
||||
);
|
||||
});
|
||||
@ -100,7 +100,7 @@ function checkExpectedGlobalResults(testName) {
|
||||
for (policy in response[type][scheme]) {
|
||||
var expectedResult =
|
||||
EXPECTED_RESULTS[type] === undefined
|
||||
? EXPECTED_RESULTS["default"][scheme][policy]
|
||||
? EXPECTED_RESULTS.default[scheme][policy]
|
||||
: EXPECTED_RESULTS[type][scheme][policy];
|
||||
is(
|
||||
response[type][scheme][policy],
|
||||
|
@ -54,7 +54,7 @@ function testCancelPreloadNotCrash(url) {
|
||||
|
||||
// Not actually verifying any value, just to ensure cancelPrefetchPreload
|
||||
// won't cause crash.
|
||||
prefetch.cancelPrefetchPreloadURI(ios.newURI(url, null, null), link);
|
||||
prefetch.cancelPrefetchPreloadURI(ios.newURI(url), link);
|
||||
}
|
||||
|
||||
function testChangePrefetchToPreload(url) {
|
||||
|
@ -66,7 +66,7 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||
s = document.createElement('script');
|
||||
s.src="file_bug28293.sjs?res+='M';";
|
||||
document.body.appendChild(s);
|
||||
}, false);
|
||||
});
|
||||
res += 'G';
|
||||
</script>
|
||||
<script defer="defer">
|
||||
|
@ -52,6 +52,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=320799
|
||||
<select id="s3">
|
||||
<option>x</option>
|
||||
</select>
|
||||
<select id="s4" style="width: 100px; box-sizing: border-box; border: 0; margin: 10px">
|
||||
<option>This is a test, it really is a test I tell you</option>
|
||||
</select>
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
@ -63,6 +66,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=320799
|
||||
is($("s").scrollWidth, 100, "Scroll width should not include dropdown contents");
|
||||
is($("s2").clientWidth, $("s3").clientWidth,
|
||||
"Client width should not depend on the dropdown's vertical scrollbar");
|
||||
|
||||
is($("s4").scrollWidth, 100, "Scroll width should not include dropdown contents");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
@ -76,17 +76,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
function fn_onmessage(e) {
|
||||
if (e.currentTarget == e.target && e.target.hits != null)
|
||||
e.target.hits['fn_onmessage']++;
|
||||
e.target.hits.fn_onmessage++;
|
||||
}
|
||||
|
||||
function fn_event_listener_message(e) {
|
||||
if (e.currentTarget == e.target && e.target.hits != null)
|
||||
e.target.hits['fn_event_listener_message']++;
|
||||
e.target.hits.fn_event_listener_message++;
|
||||
}
|
||||
|
||||
function fn_other_event_name(e) {
|
||||
if (e.currentTarget == e.target && e.target.hits != null)
|
||||
e.target.hits['fn_other_event_name']++;
|
||||
e.target.hits.fn_other_event_name++;
|
||||
}
|
||||
|
||||
var gEventSourceObj1 = null, gEventSourceObj1_e, gEventSourceObj1_f;
|
||||
@ -105,9 +105,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
// the test when running in slow machines
|
||||
|
||||
function hasBeenHitFor1And2(obj, min) {
|
||||
if (obj.hits['fn_onmessage'] < min ||
|
||||
obj.hits['fn_event_listener_message'] < min ||
|
||||
obj.hits['fn_other_event_name'] < min)
|
||||
if (obj.hits.fn_onmessage < min ||
|
||||
obj.hits.fn_event_listener_message < min ||
|
||||
obj.hits.fn_other_event_name < min)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -130,11 +130,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
function doTest1_b(test_id) {
|
||||
gEventSourceObj1.hits = [];
|
||||
gEventSourceObj1.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj1.hits.fn_onmessage = 0;
|
||||
gEventSourceObj1.onmessage = fn_onmessage;
|
||||
gEventSourceObj1.hits['fn_event_listener_message'] = 0;
|
||||
gEventSourceObj1.hits.fn_event_listener_message = 0;
|
||||
gEventSourceObj1.addEventListener('message', fn_event_listener_message, true);
|
||||
gEventSourceObj1.hits['fn_other_event_name'] = 0;
|
||||
gEventSourceObj1.hits.fn_other_event_name = 0;
|
||||
gEventSourceObj1.addEventListener('other_event_name', fn_other_event_name, true);
|
||||
|
||||
// the eventsources.res always use a retry of 0.5 second, so for four hits a timeout of 6 seconds is enough
|
||||
@ -154,9 +154,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
}
|
||||
|
||||
function doTest1_d(test_id) {
|
||||
gEventSourceObj1.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj1.hits['fn_event_listener_message'] = 0;
|
||||
gEventSourceObj1.hits['fn_other_event_name'] = 0;
|
||||
gEventSourceObj1.hits.fn_onmessage = 0;
|
||||
gEventSourceObj1.hits.fn_event_listener_message = 0;
|
||||
gEventSourceObj1.hits.fn_other_event_name = 0;
|
||||
|
||||
setTimeout(function(){
|
||||
bhits = hasBeenHitFor1And2(gEventSourceObj1, 1);
|
||||
@ -237,10 +237,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_a.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_a.hits = [];
|
||||
gEventSourceObj3_a.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_a.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_a.hits['fn_onmessage'] == 0, "Test 3.a failed");
|
||||
ok(gEventSourceObj3_a.hits.fn_onmessage == 0, "Test 3.a failed");
|
||||
gEventSourceObj3_a.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(1500*stress_factor));
|
||||
@ -262,10 +262,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_b.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_b.hits = [];
|
||||
gEventSourceObj3_b.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_b.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_b.hits['fn_onmessage'] == 0, "Test 3.b failed");
|
||||
ok(gEventSourceObj3_b.hits.fn_onmessage == 0, "Test 3.b failed");
|
||||
gEventSourceObj3_b.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(1500*stress_factor));
|
||||
@ -282,10 +282,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_c.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_c.hits = [];
|
||||
gEventSourceObj3_c.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_c.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_c.hits['fn_onmessage'] == 0, "Test 3.c failed");
|
||||
ok(gEventSourceObj3_c.hits.fn_onmessage == 0, "Test 3.c failed");
|
||||
gEventSourceObj3_c.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(1500*stress_factor));
|
||||
@ -296,10 +296,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_d.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_d.hits = [];
|
||||
gEventSourceObj3_d.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_d.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_d.hits['fn_onmessage'] == 0, "Test 3.d failed");
|
||||
ok(gEventSourceObj3_d.hits.fn_onmessage == 0, "Test 3.d failed");
|
||||
gEventSourceObj3_d.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(1500*stress_factor));
|
||||
@ -310,10 +310,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_e.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_e.hits = [];
|
||||
gEventSourceObj3_e.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_e.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_e.hits['fn_onmessage'] == 0, "Test 3.e failed");
|
||||
ok(gEventSourceObj3_e.hits.fn_onmessage == 0, "Test 3.e failed");
|
||||
gEventSourceObj3_e.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(1500*stress_factor));
|
||||
@ -324,10 +324,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_f.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_f.hits = [];
|
||||
gEventSourceObj3_f.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_f.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_f.hits['fn_onmessage'] == 0, "Test 3.f failed");
|
||||
ok(gEventSourceObj3_f.hits.fn_onmessage == 0, "Test 3.f failed");
|
||||
gEventSourceObj3_f.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(1500*stress_factor));
|
||||
@ -342,10 +342,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_g.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_g.hits = [];
|
||||
gEventSourceObj3_g.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_g.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_g.hits['fn_onmessage'] == 0, "Test 3.g failed");
|
||||
ok(gEventSourceObj3_g.hits.fn_onmessage == 0, "Test 3.g failed");
|
||||
gEventSourceObj3_g.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(1500*stress_factor));
|
||||
@ -365,11 +365,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj3_h.onmessage = fn_onmessage;
|
||||
gEventSourceObj3_h.hits = [];
|
||||
gEventSourceObj3_h.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj3_h.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj3_h.hits['fn_onmessage'] > 1, "Test 3.h.1 failed");
|
||||
if (gEventSourceObj3_h.hits['fn_onmessage'] > 1) {
|
||||
ok(gEventSourceObj3_h.hits.fn_onmessage > 1, "Test 3.h.1 failed");
|
||||
if (gEventSourceObj3_h.hits.fn_onmessage > 1) {
|
||||
ok(fnMessageListenerTest3h.msg_ok, "Test 3.h.2 failed");
|
||||
ok(fnMessageListenerTest3h.id_ok, "Test 3.h.3 failed");
|
||||
}
|
||||
@ -438,10 +438,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj5_a.onmessage = fn_onmessage;
|
||||
gEventSourceObj5_a.hits = [];
|
||||
gEventSourceObj5_a.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj5_a.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj5_a.hits['fn_onmessage'] != 0, "Test 5.a failed");
|
||||
ok(gEventSourceObj5_a.hits.fn_onmessage != 0, "Test 5.a failed");
|
||||
gEventSourceObj5_a.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(3000*stress_factor));
|
||||
@ -453,10 +453,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
|
||||
gEventSourceObj5_b.onmessage = fn_onmessage;
|
||||
gEventSourceObj5_b.hits = [];
|
||||
gEventSourceObj5_b.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj5_b.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj5_b.hits['fn_onmessage'] == 0, "Test 5.b failed");
|
||||
ok(gEventSourceObj5_b.hits.fn_onmessage == 0, "Test 5.b failed");
|
||||
gEventSourceObj5_b.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(3000*stress_factor));
|
||||
@ -481,10 +481,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
fn_onmessage(e);
|
||||
};
|
||||
gEventSourceObj5_c.hits = [];
|
||||
gEventSourceObj5_c.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj5_c.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj5_c.hits['fn_onmessage'] > 0, "Test 5.c failed");
|
||||
ok(gEventSourceObj5_c.hits.fn_onmessage > 0, "Test 5.c failed");
|
||||
gEventSourceObj5_c.close();
|
||||
doTest5_d(test_id);
|
||||
}, parseInt(3000*stress_factor));
|
||||
@ -507,10 +507,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
fn_onmessage(e);
|
||||
};
|
||||
gEventSourceObj5_d.hits = [];
|
||||
gEventSourceObj5_d.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj5_d.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj5_d.hits['fn_onmessage'] == 0, "Test 5.d failed");
|
||||
ok(gEventSourceObj5_d.hits.fn_onmessage == 0, "Test 5.d failed");
|
||||
gEventSourceObj5_d.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(3000*stress_factor));
|
||||
@ -535,10 +535,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
fn_onmessage(e);
|
||||
};
|
||||
gEventSourceObj5_e.hits = [];
|
||||
gEventSourceObj5_e.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj5_e.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj5_e.hits['fn_onmessage'] > 0, "Test 5.e failed");
|
||||
ok(gEventSourceObj5_e.hits.fn_onmessage > 0, "Test 5.e failed");
|
||||
gEventSourceObj5_e.close();
|
||||
doTest5_f(test_id);
|
||||
}, parseInt(5000*stress_factor));
|
||||
@ -562,10 +562,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=338583
|
||||
fn_onmessage(e);
|
||||
};
|
||||
gEventSourceObj5_f.hits = [];
|
||||
gEventSourceObj5_f.hits['fn_onmessage'] = 0;
|
||||
gEventSourceObj5_f.hits.fn_onmessage = 0;
|
||||
|
||||
setTimeout(function() {
|
||||
ok(gEventSourceObj5_f.hits['fn_onmessage'] == 0, "Test 5.f failed");
|
||||
ok(gEventSourceObj5_f.hits.fn_onmessage == 0, "Test 5.f failed");
|
||||
gEventSourceObj5_f.close();
|
||||
setTestHasFinished(test_id);
|
||||
}, parseInt(3000*stress_factor));
|
||||
|
@ -23,15 +23,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=339494
|
||||
|
||||
d.setAttribute("hhh", "testvalue");
|
||||
|
||||
document.addEventListener("DOMAttrModified", removeItAgain, false);
|
||||
document.addEventListener("DOMAttrModified", removeItAgain);
|
||||
d.removeAttribute("hhh");
|
||||
document.removeEventListener("DOMAttrModified", removeItAgain, false);
|
||||
document.removeEventListener("DOMAttrModified", removeItAgain);
|
||||
|
||||
function removeItAgain()
|
||||
{
|
||||
ok(!d.hasAttribute("hhh"), "Value check 1, there should be no value");
|
||||
isnot(d.getAttribute("hhh"), "testvalue", "Value check 2");
|
||||
document.removeEventListener("DOMAttrModified", removeItAgain, false);
|
||||
document.removeEventListener("DOMAttrModified", removeItAgain);
|
||||
d.removeAttribute("hhh");
|
||||
ok(true, "Reachability, We shouldn't have crashed");
|
||||
}
|
||||
@ -40,9 +40,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=339494
|
||||
|
||||
s.setAttribute("ggg", "testvalue");
|
||||
|
||||
document.addEventListener("DOMAttrModified", compareVal, false);
|
||||
document.addEventListener("DOMAttrModified", compareVal);
|
||||
s.setAttribute("ggg", "othervalue");
|
||||
document.removeEventListener("DOMAttrModified", compareVal, false);
|
||||
document.removeEventListener("DOMAttrModified", compareVal);
|
||||
|
||||
function compareVal()
|
||||
{
|
||||
|
@ -157,7 +157,7 @@ function request_document() {
|
||||
// GeckoView shows an error page for CSP errors, which breaks this test, so just skip in that case.
|
||||
try {
|
||||
if (!SpecialPowers.Cc["@mozilla.org/android/bridge;1"].getService(SpecialPowers.Ci.nsIAndroidBridge).isFennec) {
|
||||
lastContentType = Ci.nsIContentPolicy["TYPE_DOCUMENT"];
|
||||
lastContentType = Ci.nsIContentPolicy.TYPE_DOCUMENT;
|
||||
return;
|
||||
}
|
||||
} catch (e){}
|
||||
|
@ -39,7 +39,7 @@ function logEvent(evt) {
|
||||
uploadTotal = evt.total
|
||||
} else {
|
||||
if (evt.type == "progress") {
|
||||
is(evt.lengthComputable, evt.total != 0, "event(" + evt.type + ").lengthComputable should be " + (evt.total != 0 ? true : false) + ".");
|
||||
is(evt.lengthComputable, evt.total != 0, "event(" + evt.type + ").lengthComputable should be " + (evt.total != 0) + ".");
|
||||
}
|
||||
if (evt.total != uploadTotal && evt.total != 0) {
|
||||
ok(false, "event(" + evt.type + ").total should not change during upload except to become 0 on error/abort/timeout.");
|
||||
|
@ -50,7 +50,7 @@ function mousedown(event) {
|
||||
|
||||
function selectByMouseThenClick(elm,startx,starty) {
|
||||
// select some text
|
||||
var ctrl = navigator.platform.indexOf("Linux") ? true : false;
|
||||
var ctrl = !!navigator.platform.indexOf("Linux");
|
||||
var alt = true;
|
||||
var x = startx;
|
||||
synthesizeMouse(elm, x, starty, { type:"mousedown", ctrlKey:ctrl, altKey:alt });
|
||||
|
@ -23,10 +23,10 @@ SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
is(xhr.response["foo"], "bar", "Should have gotten bar on baseline");
|
||||
is(xhr.response.foo, "bar", "Should have gotten bar on baseline");
|
||||
|
||||
xhr.onload = function() {
|
||||
is(xhr.response["foo"], "bar", "Should have gotten bar with BOM");
|
||||
is(xhr.response.foo, "bar", "Should have gotten bar with BOM");
|
||||
|
||||
xhr.onload = function() {
|
||||
is(xhr.response, null, "Should have gotten null response with UTF-16 JSON");
|
||||
|
@ -14,7 +14,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=891952
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
var all = document.all;
|
||||
is(all["content"], $("content"), "Should find the content");
|
||||
is(all.content, $("content"), "Should find the content");
|
||||
ok(!("" in all), "Should not have an empty string prop on document.all");
|
||||
is(all[""], undefined, "Should not get empty string on document.all");
|
||||
is(all.namedItem(""), null,
|
||||
|
@ -122,6 +122,14 @@ let runTests = t.step_func_done(function() {
|
||||
input.value = "foo";
|
||||
document.documentElement.appendChild(input);
|
||||
}, "Native anonymous content isn't exposed in window.find");
|
||||
|
||||
testFindable(false, "\0", `
|
||||
�
|
||||
`);
|
||||
|
||||
testFindable(true, "\0", function(document) {
|
||||
document.documentElement.appendChild(document.createTextNode("\0"));
|
||||
}, "Inserted null characters are findable");
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
|
@ -50,7 +50,7 @@ addLoadEvent(function() {
|
||||
is(bod.getBoundingClientRect().width, 50, "Width of body should still be 50px");
|
||||
window.requestAnimationFrame(function() {
|
||||
is(resizeHandlerRan, true, "Resize handler should have run");
|
||||
win.removeEventListener("resize", handleResize, false);
|
||||
win.removeEventListener("resize", handleResize);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script>
|
||||
'use strict';
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["apz.allow_zooming", true],
|
||||
["dom.meta-viewport.enabled", true],
|
||||
["layout.viewport_contains_no_contents_area", true],
|
||||
]
|
||||
}, () => {
|
||||
// We need to open a new window to avoid running tests in an iframe since
|
||||
// we want to test metrics on the root document.
|
||||
window.open("file_viewport_metrics_on_landscape_content.html");
|
||||
});
|
||||
</script>
|
@ -817,117 +817,117 @@ DOMInterfaces = {
|
||||
},
|
||||
|
||||
'SVGPathSeg': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSeg',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSeg',
|
||||
'headerFile': 'DOMSVGPathSeg.h',
|
||||
},
|
||||
|
||||
'SVGPathSegClosePath': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegClosePath',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegClosePath',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegMovetoAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegMovetoAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegMovetoAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegMovetoRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegMovetoRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegMovetoRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegLinetoAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegLinetoRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoCubicAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoCubicRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoQuadraticAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoQuadraticRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegArcAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegArcAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegArcAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegArcRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegArcRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegArcRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoHorizontalAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegLinetoHorizontalAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoHorizontalAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoHorizontalRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegLinetoHorizontalRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoHorizontalRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoVerticalAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegLinetoVerticalAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoVerticalAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegLinetoVerticalRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegLinetoVerticalRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegLinetoVerticalRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicSmoothAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoCubicSmoothAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicSmoothAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoCubicSmoothRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoCubicSmoothRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoCubicSmoothRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticSmoothAbs': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoQuadraticSmoothAbs',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticSmoothAbs',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegCurvetoQuadraticSmoothRel': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegCurvetoQuadraticSmoothRel',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegCurvetoQuadraticSmoothRel',
|
||||
'headerFile': 'DOMSVGPathSeg.h'
|
||||
},
|
||||
|
||||
'SVGPathSegList': {
|
||||
'nativeType': 'mozilla::DOMSVGPathSegList',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPathSegList',
|
||||
'headerFile': 'DOMSVGPathSegList.h'
|
||||
},
|
||||
|
||||
'SVGPoint': {
|
||||
'nativeType': 'mozilla::nsISVGPoint',
|
||||
'nativeType': 'mozilla::dom::nsISVGPoint',
|
||||
'headerFile': 'nsISVGPoint.h'
|
||||
},
|
||||
|
||||
'SVGPointList': {
|
||||
'nativeType': 'mozilla::DOMSVGPointList',
|
||||
'nativeType': 'mozilla::dom::DOMSVGPointList',
|
||||
'headerFile': 'DOMSVGPointList.h'
|
||||
},
|
||||
|
||||
@ -940,12 +940,8 @@ DOMInterfaces = {
|
||||
'headerFile': 'mozilla/dom/SVGGradientElement.h',
|
||||
},
|
||||
|
||||
'SVGRect': {
|
||||
'nativeType': 'mozilla::dom::SVGIRect'
|
||||
},
|
||||
|
||||
'SVGStringList': {
|
||||
'nativeType': 'mozilla::DOMSVGStringList',
|
||||
'nativeType': 'mozilla::dom::DOMSVGStringList',
|
||||
'headerFile': 'DOMSVGStringList.h',
|
||||
},
|
||||
|
||||
@ -955,7 +951,7 @@ DOMInterfaces = {
|
||||
},
|
||||
|
||||
'SVGTransformList': {
|
||||
'nativeType': 'mozilla::DOMSVGTransformList',
|
||||
'nativeType': 'mozilla::dom::DOMSVGTransformList',
|
||||
'headerFile': 'DOMSVGTransformList.h'
|
||||
},
|
||||
|
||||
|
@ -37,7 +37,8 @@ class BasicRenderingContext2D {
|
||||
virtual void Transform(double aM11, double aM12, double aM21, double aM22,
|
||||
double aDx, double aDy,
|
||||
mozilla::ErrorResult& aError) = 0;
|
||||
virtual already_AddRefed<DOMMatrix> GetTransform(mozilla::ErrorResult& aError) = 0;
|
||||
virtual already_AddRefed<DOMMatrix> GetTransform(
|
||||
mozilla::ErrorResult& aError) = 0;
|
||||
virtual void SetTransform(double aM11, double aM12, double aM21, double aM22,
|
||||
double aDx, double aDy,
|
||||
mozilla::ErrorResult& aError) = 0;
|
||||
|
@ -3953,6 +3953,9 @@ gfxFontGroup* CanvasRenderingContext2D::GetCurrentFontStyle() {
|
||||
NS_ERROR("Default canvas font is invalid");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The fontgroup needs to check if its cached families/faces are valid.
|
||||
CurrentState().fontGroup->CheckForUpdatedPlatformList();
|
||||
}
|
||||
|
||||
return CurrentState().fontGroup;
|
||||
|
@ -94,7 +94,8 @@ class CanvasRenderingContext2D final : public nsICanvasRenderingContextInternal,
|
||||
void Translate(double aX, double aY, mozilla::ErrorResult& aError) override;
|
||||
void Transform(double aM11, double aM12, double aM21, double aM22, double aDx,
|
||||
double aDy, mozilla::ErrorResult& aError) override;
|
||||
already_AddRefed<DOMMatrix> GetTransform(mozilla::ErrorResult& aError) override;
|
||||
already_AddRefed<DOMMatrix> GetTransform(
|
||||
mozilla::ErrorResult& aError) override;
|
||||
void SetTransform(double aM11, double aM12, double aM21, double aM22,
|
||||
double aDx, double aDy,
|
||||
mozilla::ErrorResult& aError) override;
|
||||
|
@ -47,7 +47,7 @@ load 1305312-1.html
|
||||
load 1305850.html
|
||||
load 1334366-1.html
|
||||
load 1334647-1.html
|
||||
load 1349067.html
|
||||
skip-if(geckoview&&webrender) load 1349067.html # Bug 1563214 for GV+WR
|
||||
pref(gfx.offscreencanvas.enabled,true) load 1348976-1.html
|
||||
load 1357092.html
|
||||
load 1441613.html
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
WEBGL_TYPES = {};
|
||||
WEBGL_TYPES['experimental-webgl'] = true;
|
||||
WEBGL_TYPES['webgl'] = true;
|
||||
WEBGL_TYPES.webgl = true;
|
||||
|
||||
function AreBothIn(a, b, set) {
|
||||
return (a in set) && (b in set);
|
||||
@ -73,7 +73,7 @@ if (IsWebGLFunctional())
|
||||
functionalTypeSet['experimental-webgl'] = true;
|
||||
|
||||
if (IsWebGLConformant())
|
||||
functionalTypeSet['webgl'] = true;
|
||||
functionalTypeSet.webgl = true;
|
||||
|
||||
for (var i in typeList) {
|
||||
var creationType = typeList[i];
|
||||
|
@ -4,6 +4,7 @@
|
||||
#ifndef _mozilla_dom_Client_h
|
||||
#define _mozilla_dom_Client_h
|
||||
|
||||
#include "X11UndefineNone.h"
|
||||
#include "mozilla/dom/ClientBinding.h"
|
||||
#include "mozilla/StorageAccess.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user