From c0572ba4c0fbd44521895d67381b86e5643c1a35 Mon Sep 17 00:00:00 2001
From: TheCymaera <69355340+TheCymaera@users.noreply.github.com>
Date: Fri, 11 Nov 2022 18:25:48 +0800
Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Simplified=20resize=20observer?=
=?UTF-8?q?=20singleton?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../render_dom/wrappers/Element/Binding.ts | 4 +-
.../render_dom/wrappers/Element/index.ts | 12 ++++--
src/compiler/utils/patterns.ts | 3 +-
.../internal/ResizeObserverSingleton.ts | 38 ++++++-------------
src/runtime/internal/dom.ts | 14 +++++--
5 files changed, 34 insertions(+), 37 deletions(-)
diff --git a/src/compiler/compile/render_dom/wrappers/Element/Binding.ts b/src/compiler/compile/render_dom/wrappers/Element/Binding.ts
index 46f1cfc043..cb5a159ffe 100644
--- a/src/compiler/compile/render_dom/wrappers/Element/Binding.ts
+++ b/src/compiler/compile/render_dom/wrappers/Element/Binding.ts
@@ -416,12 +416,12 @@ function get_value_from_dom(
//
if (regex_box_size.test(name)) {
- const functionName = {
+ const functionName = ({
"contentRect": "get_content_rect",
"contentBoxSize": "get_content_box_size",
"borderBoxSize": "get_border_box_size",
"devicePixelContentBoxSize": "get_device_pixel_content_box_size",
- }
+ })[name];
return x`@${functionName}(this)`;
}
diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts
index 8418cd9531..09b9f4aaa6 100644
--- a/src/compiler/compile/render_dom/wrappers/Element/index.ts
+++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts
@@ -12,7 +12,7 @@ import { namespaces } from '../../../../utils/namespaces';
import AttributeWrapper from './Attribute';
import StyleAttributeWrapper from './StyleAttribute';
import SpreadAttributeWrapper from './SpreadAttribute';
-import { regex_dimensions, regex_starts_with_newline, regex_backslashes, regex_border_box_size, regex_content_box_size, regex_device_pixel_content_box_size } from '../../../../utils/patterns';
+import { regex_dimensions, regex_starts_with_newline, regex_backslashes, regex_border_box_size, regex_content_box_size, regex_device_pixel_content_box_size, regex_content_rect } from '../../../../utils/patterns';
import Binding from './Binding';
import add_to_set from '../../../utils/add_to_set';
import { add_event_handler } from '../shared/add_event_handlers';
@@ -71,15 +71,20 @@ const events = [
},
{
- event_names: ['elementresizeobserveborderbox'],
+ event_names: ['elementresizeobservecontentrect'],
filter: (_node: Element, name: string) =>
- regex_border_box_size.test(name)
+ regex_content_rect.test(name)
},
{
event_names: ['elementresizeobservecontentbox'],
filter: (_node: Element, name: string) =>
regex_content_box_size.test(name)
},
+ {
+ event_names: ['elementresizeobserveborderbox'],
+ filter: (_node: Element, name: string) =>
+ regex_border_box_size.test(name)
+ },
{
event_names: ['elementresizeobservedevicepixelcontentbox'],
filter: (_node: Element, name: string) =>
@@ -710,6 +715,7 @@ export default class ElementWrapper extends Wrapper {
const functionName = ({
"elementresize": "add_iframe_resize_listener",
+ "elementresizeobservecontentrect": "add_content_rect_observer",
"elementresizeobservecontentbox": "add_content_box_observer",
"elementresizeobserveborderbox": "add_border_box_observer",
"elementresizeobservedevicepixelcontentbox": "add_device_pixel_content_box_observer",
diff --git a/src/compiler/utils/patterns.ts b/src/compiler/utils/patterns.ts
index 2a19d2d89f..e4cf3a8506 100644
--- a/src/compiler/utils/patterns.ts
+++ b/src/compiler/utils/patterns.ts
@@ -23,7 +23,8 @@ export const regex_invalid_variable_identifier_characters = /[^a-zA-Z0-9_$]/g;
export const regex_dimensions = /^(?:offset|client)(?:Width|Height)$/;
-export const regex_content_box_size = /^(?:contentRect|contentBoxSize)$/;
+export const regex_content_rect = /^(?:contentRect)$/;
+export const regex_content_box_size = /^(?:contentBoxSize)$/;
export const regex_border_box_size = /^(?:borderBoxSize)$/;
export const regex_device_pixel_content_box_size = /^(?:devicePixelContentBoxSize)$/;
export const regex_box_size = /^(?:contentRect|contentBoxSize|borderBoxSize|devicePixelContentBoxSize)$/
\ No newline at end of file
diff --git a/src/runtime/internal/ResizeObserverSingleton.ts b/src/runtime/internal/ResizeObserverSingleton.ts
index beaaeede05..a8e4788e5c 100644
--- a/src/runtime/internal/ResizeObserverSingleton.ts
+++ b/src/runtime/internal/ResizeObserverSingleton.ts
@@ -1,4 +1,4 @@
-const MapImplementation = "WeakMap" in window ? WeakMap : Map;
+const MapImplementation = "WeakMap" in window ? WeakMap : ("Map" in window ? Map : undefined);
/**
* Resize observer singleton
@@ -8,53 +8,37 @@ export class ResizeObserverSingleton {
constructor(readonly options?: ResizeObserverOptions) {}
addListener(element: Element, callback: Callback) {
- if (!this._subscriptions.has(element)) {
- this._subscriptions.set(element, new Subscription(new Set([callback])));
- this._getObserver().observe(element, this.options);
- } else {
- const subscription = this._subscriptions.get(element)!;
- subscription.listeners.add(callback);
- callback.call(element, subscription.lastEntry!);
- }
+ this._subscriptions.set(element, new Subscription(callback));
+ this._getObserver().observe(element, this.options);
}
- removeListener(element: Element, callback: Callback) {
- const subscription = this._subscriptions.get(element);
- if (!subscription) return;
- if (subscription.listeners.size > 1) {
- subscription.listeners.delete(callback);
- } else {
- this._subscriptions.delete(element);
- this._getObserver().unobserve(element);
- }
+ removeListener(element: Element) {
+ this._subscriptions.delete(element);
+ this._getObserver().unobserve(element);
}
getLastEntry(element: Element) {
return this._subscriptions.get(element)?.lastEntry;
}
- private readonly _subscriptions: WeakMap = new MapImplementation();
+ private readonly _subscriptions: WeakMap = MapImplementation ? new MapImplementation() : undefined;
private _observer: ResizeObserver|undefined = undefined;
private _getObserver() {
return this._observer ?? (this._observer = new ResizeObserver((entries)=>{
for (const entry of entries) {
- const element = entry.target;
- const subscription = this._subscriptions.get(element);
- if (!subscription) continue;
+ const subscription = this._subscriptions.get(entry.target)!;
subscription.lastEntry = entry;
- for (const callback of subscription.listeners) callback.call(element, entry);
+ subscription.listener(entry);
}
}));
}
}
-type Callback = (this: Element, entry: ResizeObserverEntry)=>any;
+type Callback = (entry: ResizeObserverEntry)=>any;
class Subscription {
- // TODO: consider using Array instead of Set?
- // If we can guarantee one listener per element, we can simplify even more.
constructor(
- readonly listeners: Set,
+ readonly listener: Callback,
public lastEntry?: ResizeObserverEntry,
) {}
}
\ No newline at end of file
diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts
index 1d2b59bb1a..946dfb97b1 100644
--- a/src/runtime/internal/dom.ts
+++ b/src/runtime/internal/dom.ts
@@ -641,27 +641,33 @@ export function add_iframe_resize_listener(node: HTMLElement, fn: () => void) {
};
}
+const resize_observer_content_rect = new ResizeObserverSingleton({ box: "content-box" });
const resize_observer_content_box = new ResizeObserverSingleton({ box: "content-box" });
const resize_observer_border_box = new ResizeObserverSingleton({ box: "border-box" });
const resize_observer_device_pixel_content_box = new ResizeObserverSingleton({ box: "device-pixel-content-box" });
+export function add_content_rect_observer(node: Element, fn: () => void) {
+ resize_observer_content_rect.addListener(node, fn);
+ return ()=> resize_observer_content_rect.removeListener(node);
+}
+
export function add_content_box_observer(node: Element, fn: () => void) {
resize_observer_content_box.addListener(node, fn);
- return ()=> resize_observer_content_box.removeListener(node, fn);
+ return ()=> resize_observer_content_box.removeListener(node);
}
export function add_border_box_observer(node: Element, fn: () => void) {
resize_observer_border_box.addListener(node, fn);
- return ()=> resize_observer_border_box.removeListener(node, fn);
+ return ()=> resize_observer_border_box.removeListener(node);
}
export function add_device_pixel_content_box_observer(node: Element, fn: () => void) {
resize_observer_device_pixel_content_box.addListener(node, fn);
- return ()=> resize_observer_device_pixel_content_box.removeListener(node, fn);
+ return ()=> resize_observer_device_pixel_content_box.removeListener(node);
}
export function get_content_rect(node: Element) {
- return resize_observer_content_box.getLastEntry(node)?.contentRect;
+ return resize_observer_content_rect.getLastEntry(node)?.contentRect;
}
export function get_content_box_size(node: Element) {