Commit 96555335 authored by Sahir Vellani's avatar Sahir Vellani Committed by Commit Bot

Resize Observer - Simple content-box and border-box observations

It is possible to now observe changes to content box and border box of
an element that is being observed. However, changes to an element's
content box without a change in its border box can not be observed yet,
and will be addressed in a subsequent change.

Bug: 1042537
Change-Id: I6415fc4f5cec783cc717051c11b2fdd95d3a28e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2004051Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Reviewed-by: default avatarDaniel Libby <dlibby@microsoft.com>
Commit-Queue: Sahir Vellani <sahir.vellani@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#737369}
parent cfc72663
......@@ -3,20 +3,23 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_box_options.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
namespace blink {
ResizeObservation::ResizeObservation(Element* target, ResizeObserver* observer)
ResizeObservation::ResizeObservation(Element* target,
ResizeObserver* observer,
ResizeObserverBoxOptions observed_box)
: target_(target),
observer_(observer),
observation_size_(0, 0),
element_size_changed_(true) {
element_size_changed_(true),
observed_box_(observed_box) {
DCHECK(target_);
observer_->ElementSizeChanged();
}
......@@ -55,25 +58,29 @@ size_t ResizeObservation::TargetDepth() {
LayoutSize ResizeObservation::ComputeTargetSize() const {
if (target_) {
if (LayoutObject* layout_object = target_->GetLayoutObject()) {
// https://drafts.csswg.org/resize-observer/#calculate-box-size states
// that the bounding box should be used for SVGGraphicsElements regardless
// of the observed box.
if (auto* svg_graphics_element =
DynamicTo<SVGGraphicsElement>(target_.Get())) {
return LayoutSize(svg_graphics_element->GetBBox().Size());
}
if (layout_object->IsBox())
return ToLayoutBox(layout_object)->ContentSize();
if (!layout_object->IsBox())
return LayoutSize();
switch (observed_box_) {
case ResizeObserverBoxOptions::BorderBox:
return ToLayoutBox(layout_object)->BorderBoxRect().Size();
case ResizeObserverBoxOptions::ContentBox:
return ToLayoutBox(layout_object)->ContentSize();
default:
NOTREACHED();
}
}
}
return LayoutSize();
}
LayoutPoint ResizeObservation::ComputeTargetLocation() const {
if (target_ && !target_->IsSVGElement()) {
if (LayoutBox* layout = target_->GetLayoutBox())
return LayoutPoint(layout->PaddingLeft(), layout->PaddingTop());
}
return LayoutPoint();
}
void ResizeObservation::ElementSizeChanged() {
element_size_changed_ = true;
observer_->ElementSizeChanged();
......
......@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_RESIZE_OBSERVER_RESIZE_OBSERVATION_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_box_options.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
......@@ -13,14 +14,15 @@
namespace blink {
class Element;
class LayoutPoint;
class ResizeObserver;
// ResizeObservation represents an element that is being observed.
class CORE_EXPORT ResizeObservation final
: public GarbageCollected<ResizeObservation> {
public:
ResizeObservation(Element* target, ResizeObserver*);
ResizeObservation(Element* target,
ResizeObserver*,
ResizeObserverBoxOptions observed_box);
Element* Target() const { return target_; }
size_t TargetDepth();
......@@ -28,9 +30,9 @@ class CORE_EXPORT ResizeObservation final
bool ObservationSizeOutOfSync();
void SetObservationSize(const LayoutSize&);
void ElementSizeChanged();
ResizeObserverBoxOptions observedBox() const { return observed_box_; }
LayoutSize ComputeTargetSize() const;
LayoutPoint ComputeTargetLocation() const;
void Trace(blink::Visitor*);
......@@ -40,6 +42,7 @@ class CORE_EXPORT ResizeObservation final
// Target size sent in last observation notification.
LayoutSize observation_size_;
bool element_size_changed_;
ResizeObserverBoxOptions observed_box_;
};
} // namespace blink
......
......@@ -12,9 +12,13 @@
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_options.h"
namespace blink {
constexpr const char* kBoxOptionBorderBox = "border-box";
constexpr const char* kBoxOptionContentBox = "content-box";
ResizeObserver* ResizeObserver::Create(Document& document,
V8ResizeObserverCallback* callback) {
return MakeGarbageCollected<ResizeObserver>(callback, document);
......@@ -45,12 +49,38 @@ ResizeObserver::ResizeObserver(Delegate* delegate, Document& document)
controller_->AddObserver(*this);
}
void ResizeObserver::observe(Element* target) {
ResizeObserverBoxOptions ResizeObserver::ParseBoxOptions(
const String& box_options) {
if (box_options == kBoxOptionBorderBox)
return ResizeObserverBoxOptions::BorderBox;
if (box_options == kBoxOptionContentBox)
return ResizeObserverBoxOptions::ContentBox;
return ResizeObserverBoxOptions::ContentBox;
}
void ResizeObserver::observeInternal(Element* target,
ResizeObserverBoxOptions box_option) {
auto& observer_map = target->EnsureResizeObserverData();
if (observer_map.Contains(this))
return; // Already registered.
auto* observation = MakeGarbageCollected<ResizeObservation>(target, this);
if (observer_map.Contains(this)) {
auto observation = observer_map.find(this);
if ((*observation).value->observedBox() == box_option)
return;
// Unobserve target if box_option has changed and target already existed. If
// there is an existing observation of a different box, this new observation
// takes precedence. See:
// https://drafts.csswg.org/resize-observer/#processing-model
observations_.erase((*observation).value);
auto index = active_observations_.Find((*observation).value);
if (index != kNotFound) {
active_observations_.EraseAt(index);
}
observer_map.erase(observation);
}
auto* observation =
MakeGarbageCollected<ResizeObservation>(target, this, box_option);
observations_.insert(observation);
observer_map.Set(this, observation);
......@@ -58,6 +88,16 @@ void ResizeObserver::observe(Element* target) {
frame_view->ScheduleAnimation();
}
void ResizeObserver::observe(Element* target,
const ResizeObserverOptions* options) {
ResizeObserverBoxOptions box_option = ParseBoxOptions(options->box());
observeInternal(target, box_option);
}
void ResizeObserver::observe(Element* target) {
observeInternal(target, ResizeObserverBoxOptions::ContentBox);
}
void ResizeObserver::unobserve(Element* target) {
auto* observer_map = target ? target->ResizeObserverData() : nullptr;
if (!observer_map)
......@@ -123,26 +163,9 @@ void ResizeObserver::DeliverObservations() {
if (!execution_context || execution_context->IsContextDestroyed())
continue;
LayoutPoint location = observation->ComputeTargetLocation();
LayoutSize size = observation->ComputeTargetSize();
observation->SetObservationSize(size);
LayoutRect content_rect(location, size);
if (observation->Target()->GetLayoutObject()) {
// Must adjust for zoom in order to report non-zoomed size.
const ComputedStyle& style =
observation->Target()->GetLayoutObject()->StyleRef();
content_rect.SetX(
AdjustForAbsoluteZoom::AdjustLayoutUnit(content_rect.X(), style));
content_rect.SetY(
AdjustForAbsoluteZoom::AdjustLayoutUnit(content_rect.Y(), style));
content_rect.SetWidth(
AdjustForAbsoluteZoom::AdjustLayoutUnit(content_rect.Width(), style));
content_rect.SetHeight(AdjustForAbsoluteZoom::AdjustLayoutUnit(
content_rect.Height(), style));
}
auto* entry = MakeGarbageCollected<ResizeObserverEntry>(
observation->Target(), content_rect);
observation->SetObservationSize(observation->ComputeTargetSize());
auto* entry =
MakeGarbageCollected<ResizeObserverEntry>(observation->Target());
entries.push_back(entry);
}
......
......@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_box_options.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
......@@ -19,6 +20,7 @@ class ResizeObserverController;
class ResizeObserverEntry;
class ResizeObservation;
class V8ResizeObserverCallback;
class ResizeObserverOptions;
// ResizeObserver represents ResizeObserver javascript api:
// https://github.com/WICG/ResizeObserver/
......@@ -47,6 +49,7 @@ class CORE_EXPORT ResizeObserver final
~ResizeObserver() override = default;
// API methods
void observe(Element*, const ResizeObserverOptions* options);
void observe(Element*);
void unobserve(Element*);
void disconnect();
......@@ -59,12 +62,16 @@ class CORE_EXPORT ResizeObserver final
void ElementSizeChanged();
bool HasElementSizeChanged() { return element_size_changed_; }
ResizeObserverBoxOptions ParseBoxOptions(const String& box_options);
// ScriptWrappable override:
bool HasPendingActivity() const override;
void Trace(blink::Visitor*) override;
private:
void observeInternal(Element* target, ResizeObserverBoxOptions box_option);
using ObservationList = HeapLinkedHashSet<WeakMember<ResizeObservation>>;
// Either of |callback_| and |delegate_| should be non-null.
......
......@@ -13,7 +13,7 @@ callback ResizeObserverCallback = void (sequence<ResizeObserverEntry> entries, R
ActiveScriptWrappable
] interface ResizeObserver {
[CallWith=Document, MeasureAs=ResizeObserver_Constructor] constructor(ResizeObserverCallback callback);
void observe(Element target);
void observe(Element target, optional ResizeObserverOptions options);
void unobserve(Element target);
void disconnect();
};
......@@ -5,7 +5,6 @@ namespace blink {
enum class ResizeObserverBoxOptions {
BorderBox,
ContentBox,
DevicePixelContentBox
};
}
......
......@@ -3,24 +3,88 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_size.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
ResizeObserverEntry::ResizeObserverEntry(Element* target,
const LayoutRect& content_rect)
: target_(target) {
content_rect_ = DOMRectReadOnly::FromFloatRect(FloatRect(
DOMRectReadOnly* ResizeObserverEntry::ZoomAdjustedLayoutRect(
LayoutRect content_rect,
const ComputedStyle& style) {
content_rect.SetX(
AdjustForAbsoluteZoom::AdjustLayoutUnit(content_rect.X(), style));
content_rect.SetY(
AdjustForAbsoluteZoom::AdjustLayoutUnit(content_rect.Y(), style));
content_rect.SetWidth(
AdjustForAbsoluteZoom::AdjustLayoutUnit(content_rect.Width(), style));
content_rect.SetHeight(
AdjustForAbsoluteZoom::AdjustLayoutUnit(content_rect.Height(), style));
return DOMRectReadOnly::FromFloatRect(FloatRect(
FloatPoint(content_rect.Location()), FloatSize(content_rect.Size())));
}
ResizeObserverSize* ResizeObserverEntry::ZoomAdjustedSize(
const LayoutSize box_size,
const ComputedStyle& style) {
return ResizeObserverSize::Create(
AdjustForAbsoluteZoom::AdjustLayoutUnit(box_size.Width(), style),
AdjustForAbsoluteZoom::AdjustLayoutUnit(box_size.Height(), style));
}
ResizeObserverEntry::ResizeObserverEntry(Element* target) : target_(target) {
if (LayoutObject* layout_object = target->GetLayoutObject()) {
const ComputedStyle& style = layout_object->StyleRef();
// SVG box properties are always based on bounding box
if (auto* svg_graphics_element = DynamicTo<SVGGraphicsElement>(target)) {
LayoutSize bounding_box_size =
LayoutSize(svg_graphics_element->GetBBox().Size());
LayoutRect content_rect(LayoutPoint(), bounding_box_size);
content_rect_ = ZoomAdjustedLayoutRect(content_rect, style);
if (RuntimeEnabledFeatures::ResizeObserverUpdatesEnabled()) {
content_box_size_ = ZoomAdjustedSize(bounding_box_size, style);
border_box_size_ = ZoomAdjustedSize(bounding_box_size, style);
}
} else {
LayoutBox* layout_box = target->GetLayoutBox();
LayoutRect content_rect(
LayoutPoint(layout_box->PaddingLeft(), layout_box->PaddingTop()),
layout_box->ContentSize());
content_rect_ = ZoomAdjustedLayoutRect(content_rect, style);
if (RuntimeEnabledFeatures::ResizeObserverUpdatesEnabled()) {
LayoutSize content_box_size =
LayoutSize(layout_box->ContentLogicalWidth(),
layout_box->ContentLogicalHeight());
LayoutSize border_box_size =
LayoutSize(layout_box->LogicalWidth(), layout_box->LogicalHeight());
content_box_size_ = ZoomAdjustedSize(content_box_size, style);
border_box_size_ = ZoomAdjustedSize(border_box_size, style);
}
}
} else {
content_rect_ = DOMRectReadOnly::FromFloatRect(
FloatRect(FloatPoint(LayoutPoint()), FloatSize(LayoutSize())));
content_box_size_ = ResizeObserverSize::Create(0, 0);
border_box_size_ = ResizeObserverSize::Create(0, 0);
}
}
void ResizeObserverEntry::Trace(blink::Visitor* visitor) {
visitor->Trace(target_);
visitor->Trace(content_rect_);
visitor->Trace(content_box_size_);
visitor->Trace(border_box_size_);
ScriptWrappable::Trace(visitor);
}
......
......@@ -13,22 +13,34 @@ namespace blink {
class Element;
class DOMRectReadOnly;
class LayoutSize;
class ComputedStyle;
class ResizeObserverSize;
class LayoutRect;
class CORE_EXPORT ResizeObserverEntry final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
ResizeObserverEntry(Element* target, const LayoutRect& content_rect);
ResizeObserverEntry(Element* target);
Element* target() const { return target_; }
DOMRectReadOnly* contentRect() const { return content_rect_; }
ResizeObserverSize* contentBoxSize() const { return content_box_size_; }
ResizeObserverSize* borderBoxSize() const { return border_box_size_; }
void Trace(blink::Visitor*) override;
private:
Member<Element> target_;
Member<DOMRectReadOnly> content_rect_;
Member<ResizeObserverSize> content_box_size_;
Member<ResizeObserverSize> border_box_size_;
static DOMRectReadOnly* ZoomAdjustedLayoutRect(LayoutRect content_rect,
const ComputedStyle& style);
static ResizeObserverSize* ZoomAdjustedSize(const LayoutSize box_size,
const ComputedStyle& style);
};
} // namespace blink
......
......@@ -8,4 +8,6 @@
interface ResizeObserverEntry {
readonly attribute Element target;
readonly attribute DOMRectReadOnly contentRect;
[RuntimeEnabled=ResizeObserverUpdates] readonly attribute ResizeObserverSize contentBoxSize;
[RuntimeEnabled=ResizeObserverUpdates] readonly attribute ResizeObserverSize borderBoxSize;
};
......@@ -5,7 +5,7 @@
// https://drafts.csswg.org/resize-observer/#enumdef-resizeobserverboxoptions
enum ResizeObserverBoxOptions {
"border-box", "content-box", "device-pixel-content-box"
"border-box", "content-box"
};
// https://drafts.csswg.org/resize-observer/#dictdef-resizeobserveroptions
......
......@@ -11,7 +11,9 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_box_options.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_options.h"
#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
......@@ -60,6 +62,7 @@ TEST_F(ResizeObserverUnitTest, ResizeObservationSize) {
main_resource.Write(R"HTML(
<div id='domTarget' style='width:100px;height:100px'>yo</div>
<div id='domBorderTarget' style='width:100px;height:100px;padding:5px'>yoyo</div>
<svg height='200' width='200'>
<circle id='svgTarget' cx='100' cy='100' r='100'/>
</svg>
......@@ -70,14 +73,19 @@ TEST_F(ResizeObserverUnitTest, ResizeObservationSize) {
MakeGarbageCollected<TestResizeObserverDelegate>(GetDocument());
ResizeObserver* observer = ResizeObserver::Create(GetDocument(), delegate);
Element* dom_target = GetDocument().getElementById("domTarget");
Element* dom_border_target = GetDocument().getElementById("domBorderTarget");
Element* svg_target = GetDocument().getElementById("svgTarget");
ResizeObservation* dom_observation =
MakeGarbageCollected<ResizeObservation>(dom_target, observer);
ResizeObservation* svg_observation =
MakeGarbageCollected<ResizeObservation>(svg_target, observer);
ResizeObservation* dom_observation = MakeGarbageCollected<ResizeObservation>(
dom_target, observer, ResizeObserverBoxOptions::ContentBox);
ResizeObservation* dom_border_observation =
MakeGarbageCollected<ResizeObservation>(
dom_border_target, observer, ResizeObserverBoxOptions::BorderBox);
ResizeObservation* svg_observation = MakeGarbageCollected<ResizeObservation>(
svg_target, observer, ResizeObserverBoxOptions::ContentBox);
// Initial observation is out of sync
ASSERT_TRUE(dom_observation->ObservationSizeOutOfSync());
ASSERT_TRUE(dom_border_observation->ObservationSizeOutOfSync());
ASSERT_TRUE(svg_observation->ObservationSizeOutOfSync());
// Target size is correct
......@@ -86,6 +94,11 @@ TEST_F(ResizeObserverUnitTest, ResizeObservationSize) {
ASSERT_EQ(size.Height(), 100);
dom_observation->SetObservationSize(size);
size = dom_border_observation->ComputeTargetSize();
ASSERT_EQ(size.Width(), 110);
ASSERT_EQ(size.Height(), 110);
dom_border_observation->SetObservationSize(size);
size = svg_observation->ComputeTargetSize();
ASSERT_EQ(size.Width(), 200);
ASSERT_EQ(size.Height(), 200);
......@@ -93,12 +106,47 @@ TEST_F(ResizeObserverUnitTest, ResizeObservationSize) {
// Target size is in sync
ASSERT_FALSE(dom_observation->ObservationSizeOutOfSync());
ASSERT_FALSE(dom_border_observation->ObservationSizeOutOfSync());
// Target depths
ASSERT_EQ(svg_observation->TargetDepth() - dom_observation->TargetDepth(),
(size_t)1);
}
// Test whether a new observation is created when an observation's
// observed box is changed
TEST_F(ResizeObserverUnitTest, TestBoxOverwrite) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Write(R"HTML(
<div id='domTarget' style='width:100px;height:100px'>yo</div>
<svg height='200' width='200'>
<circle id='svgTarget' cx='100' cy='100' r='100'/>
</svg>
)HTML");
main_resource.Finish();
ResizeObserverOptions* border_box_option = ResizeObserverOptions::Create();
border_box_option->setBox("border-box");
ResizeObserver::Delegate* delegate =
MakeGarbageCollected<TestResizeObserverDelegate>(GetDocument());
ResizeObserver* observer = ResizeObserver::Create(GetDocument(), delegate);
Element* dom_target = GetDocument().getElementById("domTarget");
// Assert no observations (depth returned is kDepthBottom)
size_t min_observed_depth = ResizeObserverController::kDepthBottom;
ASSERT_EQ(observer->GatherObservations(0), min_observed_depth);
observer->observe(dom_target);
// 3 is Depth of observed element
ASSERT_EQ(observer->GatherObservations(0), (size_t)3);
observer->observe(dom_target, border_box_option);
// Active observations should be empty and GatherObservations should run
ASSERT_EQ(observer->GatherObservations(0), (size_t)3);
}
TEST_F(ResizeObserverUnitTest, TestMemoryLeaks) {
ResizeObserverController& controller =
GetDocument().EnsureResizeObserverController();
......
......@@ -9,12 +9,12 @@ PASS test4: unobserve target stops notifications, unobserve non-observed does no
PASS test5: observe img
PASS test6: iframe notifications
PASS test7: callback.this
FAIL test8: simple content-box observation Cannot read property 'inlineSize' of undefined
FAIL test9: simple content-box observation but keep border-box size unchanged Cannot read property 'inlineSize' of undefined
FAIL test10: simple border-box observation Cannot read property 'inlineSize' of undefined
FAIL test11: simple observation with vertical writing mode Cannot read property 'inlineSize' of undefined
FAIL test12: no observation is fired after the change of writing mode when box's specified size comes from logical size properties. Cannot read property 'inlineSize' of undefined
FAIL test13: an observation is fired after the change of writing mode when box's specified size comes from physical size properties. Cannot read property 'inlineSize' of undefined
FAIL test14: observe the same target but using a different box should override the previous one Cannot read property 'inlineSize' of undefined
PASS test8: simple content-box observation
FAIL test9: simple content-box observation but keep border-box size unchanged assert_unreached: Timed out waiting for notification. (100ms) Reached unreachable code
PASS test10: simple border-box observation
PASS test11: simple observation with vertical writing mode
FAIL test12: no observation is fired after the change of writing mode when box's specified size comes from logical size properties. assert_unreached: the logical size of content-box doesn't change Reached unreachable code
FAIL test13: an observation is fired after the change of writing mode when box's specified size comes from physical size properties. assert_unreached: Timed out waiting for notification. (100ms) Reached unreachable code
PASS test14: observe the same target but using a different box should override the previous one
Harness: the test ran to completion.
......@@ -104,7 +104,9 @@ ResizeTestHelper.prototype = {
this._currentStep.timeout();
}
else {
assert_unreached("Timed out waiting for notification. (" + ResizeTestHelper.TIMEOUT + "ms)");
this._harnessTest.step(() => {
assert_unreached("Timed out waiting for notification. (" + ResizeTestHelper.TIMEOUT + "ms)");
});
}
this._nextStep();
});
......
......@@ -19,6 +19,9 @@
<polyline points="0,300 100,300 50,350" style="fill:orange;stroke:black;stroke-width:1"/>
<rect x="0" y="380" width="10" height="10" style="fill:orange; stroke:black; stroke-width:1" />
<text x="0" y="400" font-size="20">svg text tag</text>
<g fill="white" stroke="green" stroke-width="5">
<rect x="0" y="380" width="50" height="20" id="g_rect" />
</g>
</svg>
<script>
'use strict';
......@@ -363,6 +366,105 @@ function test11() {
return helper.start(() => svg.remove());
}
function test12() {
let target = document.querySelector('rect');
let helper = new ResizeTestHelper(
"test12: observe svg:rect content box",
[
{
setup: observer => {
observer.observe(target);
},
notify: (entries, observer) => {
return true; // Delay next step
}
},
{
setup: observer => {
target.setAttribute('width', 45);
},
notify: (entries, observer) => {
assert_equals(entries.length, 1);
assert_equals(entries[0].contentRect.width, 45);
assert_equals(entries[0].contentRect.height, 10);
assert_equals(entries[0].contentBoxSize.inlineSize, 45);
assert_equals(entries[0].contentBoxSize.blockSize, 10);
}
}
]);
return helper.start();
}
function test13() {
let target = document.querySelector('rect');
let helper = new ResizeTestHelper(
"test13: observe svg:circle border box",
[
{
setup: observer => {
observer.observe(target);
},
notify: (entries, observer) => {
return true; // Delay next step
}
},
{
setup: observer => {
target.setAttribute('width', 20);
target.setAttribute('height', 20);
},
notify: (entries, observer) => {
assert_equals(entries.length, 1);
assert_equals(entries[0].contentRect.width, 20);
assert_equals(entries[0].contentRect.height, 20);
assert_equals(entries[0].contentBoxSize.inlineSize, 20);
assert_equals(entries[0].contentBoxSize.blockSize, 20);
assert_equals(entries[0].borderBoxSize.inlineSize, 20);
assert_equals(entries[0].borderBoxSize.blockSize, 20);
}
}
]);
return helper.start();
}
function test14() {
let target = document.querySelector('#g_rect');
let helper = new ResizeTestHelper(
"test14: observe g:rect content and border box",
[
{
setup: observer => {
observer.observe(target);
},
notify: (entries, observer) => {
assert_equals(entries.length, 1);
assert_equals(entries[0].contentRect.width, 50);
assert_equals(entries[0].contentRect.height, 20);
assert_equals(entries[0].contentBoxSize.inlineSize, 50);
assert_equals(entries[0].contentBoxSize.blockSize, 20);
assert_equals(entries[0].borderBoxSize.inlineSize, 50);
assert_equals(entries[0].borderBoxSize.blockSize, 20);
return true; // Delay next step
}
},
{
setup: observer => {
target.setAttribute('width', 15);
},
notify: (entries, observer) => {
assert_equals(entries.length, 1);
assert_equals(entries[0].contentRect.width, 15);
assert_equals(entries[0].contentRect.height, 20);
assert_equals(entries[0].contentBoxSize.inlineSize, 15);
assert_equals(entries[0].contentBoxSize.blockSize, 20);
assert_equals(entries[0].borderBoxSize.inlineSize, 15);
assert_equals(entries[0].borderBoxSize.blockSize, 20);
}
}
]);
return helper.start();
}
let guard;
test(_ => {
assert_own_property(window, "ResizeObserver");
......@@ -381,6 +483,9 @@ test0()
.then(() => { return test9(); })
.then(() => { return test10(); })
.then(() => { return test11(); })
.then(() => { return test12(); })
.then(() => { return test13(); })
.then(() => { return test14(); })
.then(() => { guard.done(); });
</script>
......@@ -6634,6 +6634,8 @@ interface ResizeObserver
method unobserve
interface ResizeObserverEntry
attribute @@toStringTag
getter borderBoxSize
getter contentBoxSize
getter contentRect
getter target
method constructor
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment