Dactyloidae/browser/internaluserscripts/bundled-scripts/elementfrompoint-finite-polyfill.user.js
2026-07-13 08:48:40 -07:00

93 lines
2.5 KiB
JavaScript

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// ==UserScript==
// @name elementFromPoint finite-args shim
// @namespace internal-userscripts
// @description Prevents throws when Document.elementFromPoint / elementsFromPoint receives non-finite coordinates.
// @match *://*/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function () {
"use strict";
var global = typeof window !== "undefined" ? window : null;
if (!global || !global.Document || !global.Document.prototype) {
return;
}
var patched = false;
function toFiniteNumber(value) {
var number = Number(value);
if (number !== number || number === Infinity || number === -Infinity) {
return null;
}
return number;
}
function fallbackValue(methodName) {
return methodName === "elementsFromPoint" ? [] : null;
}
function wrapMethod(proto, methodName) {
var nativeMethod = proto[methodName];
if (typeof nativeMethod !== "function") {
return;
}
if (nativeMethod.__internalUserscriptsFinitePointShim) {
return;
}
function wrappedMethod(x, y) {
var finiteX = toFiniteNumber(x);
var finiteY = toFiniteNumber(y);
if (finiteX === null || finiteY === null) {
return fallbackValue(methodName);
}
try {
return nativeMethod.call(this, finiteX, finiteY);
} catch (e) {
var message = e && e.message ? String(e.message) : "";
if (message.indexOf("not a finite floating-point value") !== -1 ||
message.indexOf("is not finite") !== -1) {
return fallbackValue(methodName);
}
throw e;
}
}
try {
Object.defineProperty(wrappedMethod, "__internalUserscriptsFinitePointShim", {
value: true
});
} catch (e) {}
try {
Object.defineProperty(proto, methodName, {
value: wrappedMethod,
writable: true,
configurable: true
});
} catch (e) {
try {
proto[methodName] = wrappedMethod;
} catch (ignore) {}
}
if (proto[methodName] === wrappedMethod) {
patched = true;
}
}
wrapMethod(global.Document.prototype, "elementFromPoint");
wrapMethod(global.Document.prototype, "elementsFromPoint");
if (patched) {
try {
global.__internalUserscriptsElementFromPointFinitePolyfill = true;
} catch (e) {}
}
})();