Ver Fonte

added code to intercept IntersectionObserver usage

Gildas há 7 anos atrás
pai
commit
8c53cfadb8
1 ficheiros alterados com 52 adições e 1 exclusões
  1. 52 1
      lib/hooks/hooks.js

+ 52 - 1
lib/hooks/hooks.js

@@ -50,9 +50,9 @@ this.hooks = this.hooks || (() => {
 		};
 
 		const FontFace = window.FontFace;
+		console.warn("SingleFile is hooking the FontFace constructor to get font URLs."); // eslint-disable-line no-console
 		window.__defineGetter__("FontFace", () => new Proxy(FontFace, {
 			construct(FontFace, argumentsList) {
-				console.warn("SingleFile is hooking the FontFace constructor to get font URLs."); // eslint-disable-line no-console
 				const detail = {};
 				detail["font-family"] = argumentsList[0];
 				detail.src = argumentsList[1];
@@ -64,6 +64,57 @@ this.hooks = this.hooks || (() => {
 				return new FontFace(...argumentsList);
 			}
 		}));
+
+		const IntersectionObserver = window.IntersectionObserver;
+		const observeIntersection = IntersectionObserver.prototype.observe;
+		const unobserveIntersection = IntersectionObserver.prototype.unobserve;
+		const observedElements = new Map();
+		const observers = new Map();
+		console.warn("SingleFile is hooking the IntersectionObserver API to detect and load deferred images."); // eslint-disable-line no-console
+		window.__defineGetter__("IntersectionObserver", () => new Proxy(IntersectionObserver, {
+			construct(IntersectionObserver, argumentsList) {
+				const intersectionObserver = new IntersectionObserver(...argumentsList);
+				const callback = argumentsList[0];
+				const options = argumentsList[1];
+				intersectionObserver.observe = function (targetElement) {
+					let targetElements = observedElements.get(intersectionObserver);
+					if (!targetElements) {
+						targetElements = [];
+						observedElements.set(intersectionObserver, targetElements);
+					}
+					targetElements.push(targetElement);
+					return observeIntersection.call(intersectionObserver, targetElement);
+				};
+				intersectionObserver.unobserve = function (targetElement) {
+					let targetElements = observedElements.get(intersectionObserver);
+					if (targetElements) {
+						targetElements = targetElements.filter(element => element <= targetElement);
+						if (targetElements.length) {
+							observedElements.set(intersectionObserver, targetElements);
+						} else {
+							observedElements.delete(intersectionObserver);
+						}
+					}
+					return unobserveIntersection.call(intersectionObserver, targetElement);
+				};
+				observers.set(intersectionObserver, { callback, options });
+				return intersectionObserver;
+			}
+		}));
+		window.__defineSetter__("IntersectionObserver", () => { });
+		addEventListener("single-file-load-observed-elements", () => {
+			Array.from(observers).forEach(([intersectionObserver, observer]) => {
+				observer.callback(observedElements.get(intersectionObserver).map(target => {
+					const boundingClientRect = target.getBoundingClientRect();
+					const intersectionRect = target.getBoundingClientRect();
+					const isIntersecting = true;
+					const intersectionRatio = 1;
+					const rootBounds = observer.options && observer.options.root ? observer.options.root.getBoundingClientRect() : document.documentElement.getBoundingClientRect();
+					const time = 0;
+					return { target, intersectionRatio, boundingClientRect, intersectionRect, isIntersecting, rootBounds, time };
+				}), intersectionObserver);
+			});
+		}, false);
 	}
 
 })();