Bug 1454053 - re-record tp6 pages for raptor (wip)
MozReview-Commit-ID: JdSmYZkMPpn
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -2896,31 +2896,85 @@ nsGenericHTMLElement::NewURIFromString(c
NS_RELEASE(*aURI);
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
return NS_OK;
}
static bool
-IsOrHasAncestorWithDisplayNone(Element* aElement, nsIPresShell* aPresShell)
+IsOrHasAncestorWithDisplayNone(Element* aElement)
{
return !aElement->HasServoData() || Servo_Element_IsDisplayNone(aElement);
}
void
nsGenericHTMLElement::GetInnerText(mozilla::dom::DOMString& aValue,
mozilla::ErrorResult& aError)
{
- if (!GetPrimaryFrame(FlushType::Layout)) {
- nsIPresShell* presShell = nsContentUtils::GetPresShellForContent(this);
+ // innerText depends on layout. For example, white space processing is
+ // something that happens during reflow and which must be reflected by
+ // innerText. So for:
+ //
+ // <div style="white-space:normal"> A B C </div>
+ //
+ // innerText should give "A B C".
+ //
+ // The approach taken here to avoid the expense of reflow is to flush style
+ // and then see whether it's necessary to flush layout afterwards. Flushing
+ // layout can be skipped if we can detect that the element or its descendants
+ // are not dirty.
+
+ // Obtain the composed doc to handle elements in Shadow DOM.
+ nsIDocument* doc = GetComposedDoc();
+ if (doc) {
+ doc->FlushPendingNotifications(FlushType::Style);
+ }
+
+ // Elements with `display: content` will not have a frame. To handle Shadow
+ // DOM, walk the flattened tree looking for parent frame.
+ nsIFrame* frame = GetPrimaryFrame();
+ if (IsDisplayContents()) {
+ for (Element* parent = GetFlattenedTreeParentElement();
+ parent;
+ parent = parent->GetFlattenedTreeParentElement())
+ {
+ frame = parent->GetPrimaryFrame();
+ if (frame) {
+ break;
+ }
+ }
+ }
+
+ // Check for dirty reflow roots in the subtree from targetFrame; this requires
+ // a reflow flush.
+ nsIPresShell* presShell = nsContentUtils::GetPresShellForContent(this);
+ bool dirty = presShell && presShell->FrameIsAncestorOfDirtyRoot(frame);
+
+ // The way we do that is by checking whether the element has either of the two
+ // dirty bits (NS_FRAME_IS_DIRTY or NS_FRAME_HAS_DIRTY_DESCENDANTS) or if any
+ // ancestor has NS_FRAME_IS_DIRTY. We need to check for NS_FRAME_IS_DIRTY on
+ // ancestors since that is something that implies NS_FRAME_IS_DIRTY on all
+ // descendants.
+ dirty |= frame && frame->HasAnyStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
+ while (!dirty && frame) {
+ dirty |= frame->HasAnyStateBits(NS_FRAME_IS_DIRTY);
+ frame = frame->GetInFlowParent();
+ }
+
+ // Flush layout if we determined a reflow is required.
+ if (dirty && doc) {
+ doc->FlushPendingNotifications(FlushType::Layout);
+ }
+
+ if (!GetPrimaryFrame()) {
// NOTE(emilio): We need to check the presshell is initialized in order to
// ensure the document is styled.
if (!presShell || !presShell->DidInitialize() ||
- IsOrHasAncestorWithDisplayNone(this, presShell)) {
+ IsOrHasAncestorWithDisplayNone(this)) {
GetTextContentInternal(aValue, aError);
return;
}
}
nsRange::GetInnerTextNoFlush(aValue, aError, this);
}
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -4558,16 +4558,36 @@ PresShell::ContentRemoved(nsIContent* aC
void
PresShell::NotifyCounterStylesAreDirty()
{
nsAutoCauseReflowNotifier reflowNotifier(this);
mFrameConstructor->NotifyCounterStylesAreDirty();
}
+bool
+PresShell::FrameIsAncestorOfDirtyRoot(nsIFrame* aFrame) {
+ MOZ_ASSERT(aFrame);
+
+ // Look for a path from any dirty roots to aFrame, following GetParent().
+ // This check mirrors what FrameNeedsReflow() would have done if the reflow
+ // root didn't get in the way.
+ for (nsIFrame* dirtyFrame : mDirtyRoots) {
+ while (dirtyFrame) {
+ if (dirtyFrame == aFrame) {
+ return true;
+ }
+
+ dirtyFrame = dirtyFrame->GetParent();
+ }
+ }
+
+ return false;
+}
+
void
PresShell::ReconstructFrames()
{
MOZ_ASSERT(!mFrameConstructor->GetRootFrame() || mDidInitialize,
"Must not have root frame before initial reflow");
if (!mDidInitialize || mIsDestroying) {
// Nothing to do here
return;
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -174,16 +174,18 @@ public:
nsIContent* aOverrideClickTarget = nullptr)
override;
nsIFrame* GetEventTargetFrame() override;
already_AddRefed<nsIContent>
GetEventTargetContent(WidgetEvent* aEvent) override;
void NotifyCounterStylesAreDirty() override;
+ bool FrameIsAncestorOfDirtyRoot(nsIFrame* aFrame) override;
+
void ReconstructFrames(void) override;
void Freeze() override;
void Thaw() override;
void FireOrClearDelayedEvents(bool aFireEvents) override;
nsresult RenderDocument(const nsRect& aRect,
uint32_t aFlags,
nscolor aBackgroundColor,
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -499,16 +499,21 @@ public:
*/
virtual void FrameNeedsToContinueReflow(nsIFrame *aFrame) = 0;
virtual void CancelAllPendingReflows() = 0;
virtual void NotifyCounterStylesAreDirty() = 0;
/**
+ * Deterimine if aFrame is an ancestor of any dirty roots.
+ */
+ virtual bool FrameIsAncestorOfDirtyRoot(nsIFrame* aFrame) = 0;
+
+ /**
* Destroy the frames for aElement, and reconstruct them asynchronously if
* needed.
*
* Note that this may destroy frames for an ancestor instead.
*/
void DestroyFramesForAndRestyle(mozilla::dom::Element* aElement);
/**
--- a/testing/raptor/raptor/manifest.py
+++ b/testing/raptor/raptor/manifest.py
@@ -13,18 +13,17 @@ from utils import transform_platform
here = os.path.abspath(os.path.dirname(__file__))
raptor_ini = os.path.join(here, 'raptor.ini')
tests_dir = os.path.join(here, 'tests')
LOG = get_proxy_logger(component="raptor-manifest")
required_settings = ['apps', 'type', 'page_cycles', 'test_url', 'measure',
'unit', 'lower_is_better', 'alert_threshold']
-playback_settings = ['playback_binary_manifest', 'playback_binary_zip_mac',
- 'playback_pageset_manifest', 'playback_pageset_zip_mac',
+playback_settings = ['playback_binary_manifest', 'playback_pageset_manifest',
'playback_recordings', 'python3_win_manifest']
def filter_app(tests, values):
for test in tests:
if values["app"] in test['apps']:
yield test
rename from testing/raptor/raptor/playback/mitmproxy-playback-set.manifest
rename to testing/raptor/raptor/playback/mitmproxy-pagesets-raptor-tp6.manifest
--- a/testing/raptor/raptor/playback/mitmproxy-playback-set.manifest
+++ b/testing/raptor/raptor/playback/mitmproxy-pagesets-raptor-tp6.manifest
@@ -1,9 +1,9 @@
[
{
- "filename": "mitmproxy-recording-set-win10.zip",
- "size": 9189938,
- "digest": "e904917ed6bf1cef7201284385dc603a283e8e22f992876f17edcf0f1f20db95b609f0d8c7f593b4a0a6c20957dcb6a4d502c562ed74fb6cf4bc255c2f691f32",
+ "filename": "mitmproxy-recordings-raptor-tp6.zip",
+ "size": 8767174,
+ "digest": "3343f54b6c727a2061534872888da4e3aa647e81903c675dc318c717ed0c93f6ce4e2b98c66eb4128376cf8507590531283c95f3951259607edaaae28944d9a5",
"algorithm": "sha512",
"unpack": true
}
]
\ No newline at end of file
--- a/testing/raptor/raptor/playback/mitmproxy.py
+++ b/testing/raptor/raptor/playback/mitmproxy.py
@@ -144,17 +144,17 @@ class Mitmproxy(Playback, Python3Virtual
LOG.info("python3 path is: %s" % self.py3_path)
else:
# on osx and linux we use pre-built binaries
LOG.info("downloading mitmproxy binary")
_manifest = os.path.join(here, self.config['playback_binary_manifest'])
transformed_manifest = transform_platform(_manifest, self.config['platform'])
self._tooltool_fetch(transformed_manifest)
- # we use one pageset for all platforms (pageset was recorded on win10)
+ # we use one pageset for all platforms
LOG.info("downloading mitmproxy pageset")
_manifest = os.path.join(here, self.config['playback_pageset_manifest'])
transformed_manifest = transform_platform(_manifest, self.config['platform'])
self._tooltool_fetch(transformed_manifest)
return
def fetch_python3(self):
"""Mitmproxy on windows needs Python 3.x"""
--- a/testing/raptor/raptor/tests/raptor-tp6.ini
+++ b/testing/raptor/raptor/tests/raptor-tp6.ini
@@ -3,66 +3,70 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# raptor tp6
[DEFAULT]
type = pageload
playback = mitmproxy
playback_binary_manifest = mitmproxy-rel-bin-{platform}.manifest
-playback_binary_zip_mac = mitmproxy-2.0.2-{platform}.tar.gz
python3_win_manifest = python3{x64}.manifest
-playback_pageset_manifest = mitmproxy-playback-set.manifest
-playback_pageset_zip_mac = mitmproxy-recording-set-win10.zip
+playback_pageset_manifest = mitmproxy-recordings-raptor-tp6.manifest
page_cycles = 25
unit = ms
lower_is_better = true
alert_threshold = 2.0
[raptor-firefox-tp6-amazon]
apps = firefox
test_url = https://www.amazon.com/s/url=search-alias%3Daps&field-keywords=laptop
-playback_recordings = mitmproxy-recording-amazon.mp
-measure = fnbpaint
+playback_recordings = amazon.mp
+measure = fnbpaint, hero
+hero = hero1
[raptor-firefox-tp6-facebook]
apps = firefox
test_url = https://www.facebook.com
-playback_recordings = mitmproxy-recording-facebook.mp
-measure = fnbpaint
+playback_recordings = facebook.mp
+measure = fnbpaint, hero
+hero = hero1
[raptor-firefox-tp6-google]
apps = firefox
test_url = https://www.google.com/#hl=en&q=barack+obama
-playback_recordings = mitmproxy-recording-google.mp
+playback_recordings = google-search.mp
measure = fnbpaint, hero
-hero = hero
+hero = hero1
[raptor-firefox-tp6-youtube]
apps = firefox
test_url = https://www.youtube.com
-playback_recordings = mitmproxy-recording-youtube.mp
-measure = fnbpaint
+playback_recordings = youtube.mp
+measure = fnbpaint, hero
+hero = hero1
[raptor-chrome-tp6-amazon]
apps = chrome
test_url = https://www.amazon.com/s/url=search-alias%3Daps&field-keywords=laptop
-playback_recordings = mitmproxy-recording-amazon.mp
-measure = fcp
+playback_recordings = amazon.mp
+measure = fcp, hero
+hero = hero1
[raptor-chrome-tp6-facebook]
apps = chrome
test_url = https://www.facebook.com
-playback_recordings = mitmproxy-recording-facebook.mp
-measure = fcp
+playback_recordings = facebook.mp
+measure = fcp, hero
+hero = hero1
[raptor-chrome-tp6-google]
apps = chrome
test_url = https://www.google.com/#hl=en&q=barack+obama
-playback_recordings = mitmproxy-recording-google.mp
+playback_recordings = google-search.mp
measure = fcp, hero
-hero = hero
+hero = hero1
[raptor-chrome-tp6-youtube]
apps = chrome
test_url = https://www.youtube.com
-playback_recordings = mitmproxy-recording-youtube.mp
-measure = fcp
+playback_recordings = youtube.mp
+measure = fcp, hero
+hero = hero1
--- a/testing/raptor/test/test_playback.py
+++ b/testing/raptor/test/test_playback.py
@@ -18,19 +18,17 @@ def test_get_playback(get_binary):
config['platform'] = mozinfo.os
if 'win' in config['platform']:
# this test is not yet supported on windows
assert True
return
config['obj_path'] = os.path.dirname(get_binary('firefox'))
config['playback_tool'] = 'mitmproxy'
config['playback_binary_manifest'] = 'mitmproxy-rel-bin-osx.manifest'
- config['playback_binary_zip_mac'] = 'mitmproxy-2.0.2-osx.tar.gz'
config['playback_pageset_manifest'] = 'mitmproxy-playback-set.manifest'
- config['playback_pageset_zip_mac'] = 'mitmproxy-recording-set-win10.zip'
config['playback_recordings'] = 'mitmproxy-recording-amazon.mp'
config['binary'] = get_binary('firefox')
playback = get_playback(config)
assert isinstance(playback, Mitmproxy)
playback.stop()
def test_get_unsupported_playback():
--- a/testing/talos/talos/tests/perf-reftest/perf_reftest.manifest
+++ b/testing/talos/talos/tests/perf-reftest/perf_reftest.manifest
@@ -15,8 +15,10 @@
& http://localhost/tests/perf-reftest/dep-check-1.html, http://localhost/tests/perf-reftest/dep-check-1-ref.html
& http://localhost/tests/perf-reftest/slow-selector-1.html, http://localhost/tests/perf-reftest/slow-selector-1-ref.html
& http://localhost/tests/perf-reftest/slow-selector-2.html, http://localhost/tests/perf-reftest/slow-selector-2-ref.html
& http://localhost/tests/perf-reftest/style-attr-1.html, http://localhost/tests/perf-reftest/style-attr-1-ref.html
& http://localhost/tests/perf-reftest/stop-cascade-1.html, http://localhost/tests/perf-reftest/stop-cascade-ref.html
& http://localhost/tests/perf-reftest/stop-cascade-2.html, http://localhost/tests/perf-reftest/stop-cascade-ref.html
& http://localhost/tests/perf-reftest/bidi-resolution-1.html, http://localhost/tests/perf-reftest/bidi-resolution-1-ref.html
+
+& http://localhost/tests/perf-reftest/innertext-1.html, http://localhost/tests/perf-reftest/innertext-1-ref.html
\ No newline at end of file
--- a/testing/talos/talos/tests/perf-reftest/util.js
+++ b/testing/talos/talos/tests/perf-reftest/util.js
@@ -29,16 +29,37 @@ function build_dom(n, elemName, options)
function build_rule(selector, selectorRepeat, declaration, ruleRepeat) {
ruleRepeat = ruleRepeat || 1;
var s = document.createElement("style");
var rule = Array(selectorRepeat).fill(selector).join(", ") + declaration;
s.textContent = Array(ruleRepeat).fill(rule).join("\n\n");
return s;
}
+function build_table(rows, cols, text) {
+ rows = rows || 1;
+ cols = cols || 1;
+ text = text || "";
+ var tbody = document.createElement("tbody");
+ for (j = 0; j < rows; j++) {
+ var row = document.createElement("tr");
+ for (i = 0; i < cols; i++) {
+ var col = document.createElement("td");
+ if (text) {
+ col.textContent = build_text(TEST_WORDS);
+ }
+ row.appendChild(col);
+ }
+ tbody.appendChild(row);
+ }
+ var table = document.createElement("table");
+ table.append(tbody);
+ return table;
+}
+
function build_text(word, wordRepeat, paraRepeat) {
wordRepeat = wordRepeat || 1;
paraRepeat = paraRepeat || 1;
let para = Array(wordRepeat).fill(word).join(" ");
return Array(paraRepeat).fill(para).join("\n");
}
function flush_style(element) {
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -342491,16 +342491,22 @@
]
],
"html/dom/elements/global-attributes/the-translate-attribute-012.html": [
[
"/html/dom/elements/global-attributes/the-translate-attribute-012.html",
{}
]
],
+ "html/dom/elements/the-innertext-idl-attribute/dynamic-getter.html": [
+ [
+ "/html/dom/elements/the-innertext-idl-attribute/dynamic-getter.html",
+ {}
+ ]
+ ],
"html/dom/elements/the-innertext-idl-attribute/getter.html": [
[
"/html/dom/elements/the-innertext-idl-attribute/getter.html",
{}
]
],
"html/dom/elements/the-innertext-idl-attribute/multiple-text-nodes.window.js": [
[
@@ -576686,16 +576692,20 @@
"html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/reference/dir-isolation-009b-ref.html": [
"355953f8ebb44f79bfe3cad728bcaaa3ec04e4bb",
"support"
],
"html/dom/elements/the-innertext-idl-attribute/META.yml": [
"45472ac8906e7b383d80ab0b92ecddd6b900f726",
"support"
],
+ "html/dom/elements/the-innertext-idl-attribute/dynamic-getter.html": [
+ "12b095d1076d9081266dd3c4437c96c287838cb4",
+ "testharness"
+ ],
"html/dom/elements/the-innertext-idl-attribute/getter-tests.js": [
"0ffc6d2bf3011a376f85b45090c63de07ac023d5",
"support"
],
"html/dom/elements/the-innertext-idl-attribute/getter.html": [
"bfcd91955e1645278f7825d472bcce03dbc8f773",
"testharness"
],