1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-14 07:23:45 +00:00

[PM-29516] Remove ts strict ignore in utils index (#18047)

* use type safe generics for throttle and debounce, account for the change were event isn't passed

* read gloabl once

* check for styles before setting

* narrow keywords index

* narrow bitwardenAutofillInit for callback

* nullish coalescing operator on value for prop attributes
This commit is contained in:
Daniel Riera
2026-01-07 09:59:33 -05:00
committed by GitHub
parent 54b42001d2
commit c85e66f563
2 changed files with 39 additions and 26 deletions

View File

@@ -1659,17 +1659,19 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
return false;
};
const scrollHandler = this.useEventHandlersMemo(
throttle(async (event) => {
throttle(async (event: Event) => {
const scrollY = globalThis.scrollY;
const scrollX = globalThis.scrollX;
if (
currentScrollY !== globalThis.scrollY ||
currentScrollX !== globalThis.scrollX ||
eventTargetContainsFocusedField(event.target)
currentScrollY !== scrollY ||
currentScrollX !== scrollX ||
(event.target instanceof Element && eventTargetContainsFocusedField(event.target))
) {
repositionHandler(event);
}
currentScrollY = globalThis.scrollY;
currentScrollX = globalThis.scrollX;
currentScrollY = scrollY;
currentScrollX = scrollX;
}, 50),
AUTOFILL_OVERLAY_HANDLE_SCROLL,
);

View File

@@ -1,5 +1,3 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { FieldRect } from "../background/abstractions/overlay.background";
import { AutofillPort } from "../enums/autofill-port.enum";
import { FillableFormFieldElement, FormElementWithAttribute, FormFieldElement } from "../types";
@@ -144,11 +142,14 @@ export function setElementStyles(
}
for (const styleProperty in styles) {
element.style.setProperty(
styleProperty.replace(/([a-z])([A-Z])/g, "$1-$2"), // Convert camelCase to kebab-case
styles[styleProperty],
priority ? "important" : undefined,
);
const styleValue = styles[styleProperty];
if (styleValue !== undefined) {
element.style.setProperty(
styleProperty.replace(/([a-z])([A-Z])/g, "$1-$2"), // Convert camelCase to kebab-case
styleValue,
priority ? "important" : undefined,
);
}
}
}
@@ -175,12 +176,13 @@ export function setupExtensionDisconnectAction(callback: (port: chrome.runtime.P
* @param windowContext - The global window context
*/
export function setupAutofillInitDisconnectAction(windowContext: Window) {
if (!windowContext.bitwardenAutofillInit) {
const bitwardenAutofillInit = windowContext.bitwardenAutofillInit;
if (!bitwardenAutofillInit) {
return;
}
const onDisconnectCallback = () => {
windowContext.bitwardenAutofillInit.destroy();
bitwardenAutofillInit.destroy();
delete windowContext.bitwardenAutofillInit;
};
setupExtensionDisconnectAction(onDisconnectCallback);
@@ -357,7 +359,7 @@ export function getAttributeBoolean(
*/
export function getPropertyOrAttribute(element: HTMLElement, attributeName: string): string | null {
if (attributeName in element) {
return (element as FormElementWithAttribute)[attributeName];
return (element as FormElementWithAttribute)[attributeName] ?? null;
}
return element.getAttribute(attributeName);
@@ -369,9 +371,12 @@ export function getPropertyOrAttribute(element: HTMLElement, attributeName: stri
* @param callback - The callback function to throttle.
* @param limit - The time in milliseconds to throttle the callback.
*/
export function throttle(callback: (_args: any) => any, limit: number) {
export function throttle<FunctionType extends (...args: unknown[]) => unknown>(
callback: FunctionType,
limit: number,
): (this: ThisParameterType<FunctionType>, ...args: Parameters<FunctionType>) => void {
let waitingDelay = false;
return function (...args: unknown[]) {
return function (this: ThisParameterType<FunctionType>, ...args: Parameters<FunctionType>) {
if (!waitingDelay) {
callback.apply(this, args);
waitingDelay = true;
@@ -387,9 +392,14 @@ export function throttle(callback: (_args: any) => any, limit: number) {
* @param delay - The time in milliseconds to debounce the callback.
* @param immediate - Determines whether the callback should run immediately.
*/
export function debounce(callback: (_args: any) => any, delay: number, immediate?: boolean) {
let timeout: NodeJS.Timeout;
return function (...args: unknown[]) {
export function debounce<FunctionType extends (...args: unknown[]) => unknown>(
callback: FunctionType,
delay: number,
immediate?: boolean,
): (this: ThisParameterType<FunctionType>, ...args: Parameters<FunctionType>) => void {
let timeout: ReturnType<typeof setTimeout> | null = null;
return function (this: ThisParameterType<FunctionType>, ...args: Parameters<FunctionType>) {
const callImmediately = !!immediate && !timeout;
if (timeout) {
@@ -430,16 +440,17 @@ export function getSubmitButtonKeywordsSet(element: HTMLElement): Set<string> {
const keywordsSet = new Set<string>();
for (let i = 0; i < keywords.length; i++) {
if (typeof keywords[i] === "string") {
const keyword = keywords[i];
if (typeof keyword === "string") {
// Iterate over all keywords metadata and split them by non-letter characters.
// This ensures we check against individual words and not the entire string.
keywords[i]
keyword
.toLowerCase()
.replace(/[-\s]/g, "")
.split(/[^\p{L}]+/gu)
.forEach((keyword) => {
if (keyword) {
keywordsSet.add(keyword);
.forEach((splitKeyword) => {
if (splitKeyword) {
keywordsSet.add(splitKeyword);
}
});
}