mirror of
https://github.com/bitwarden/browser
synced 2026-02-08 20:50:28 +00:00
Add dual-index cache for O(1) opid lookups
Implements a reverse index (autofillFieldsByOpid) to enable O(1) lookups by opid instead of iterating through all cached elements. Key changes: - Add autofillFieldsByOpid Map for direct opid → element lookups - Update getAutofillFieldElementByOpid to use dual-index with stale check - Maintain both indices in cacheAutofillFieldElement - Clean up both indices in clear and delete operations Performance: Eliminates O(n) array iteration on every opid lookup.
This commit is contained in:
@@ -45,6 +45,7 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
|
||||
private domRecentlyMutated = true;
|
||||
private _autofillFormElements: AutofillFormElements = new Map();
|
||||
private autofillFieldElements: AutofillFieldElements = new Map();
|
||||
private autofillFieldsByOpid: Map<string, FormFieldElement> = new Map();
|
||||
private currentLocationHref = "";
|
||||
private intersectionObserver: IntersectionObserver;
|
||||
private elementInitializingIntersectionObserver: Set<Element> = new Set();
|
||||
@@ -154,6 +155,19 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
|
||||
* @returns {FormFieldElement | null}
|
||||
*/
|
||||
getAutofillFieldElementByOpid(opid: string): FormFieldElement | null {
|
||||
// O(1): Try dual-index lookup first
|
||||
const cachedElement = this.autofillFieldsByOpid.get(opid);
|
||||
if (cachedElement) {
|
||||
// Validate element is still in DOM (not stale)
|
||||
if (cachedElement.isConnected) {
|
||||
return cachedElement;
|
||||
}
|
||||
// Stale entry - clean it up
|
||||
this.autofillFieldElements.delete(cachedElement);
|
||||
this.autofillFieldsByOpid.delete(opid);
|
||||
}
|
||||
|
||||
// Fallback: No cached element or it was stale, query DOM
|
||||
const cachedFormFieldElements = Array.from(this.autofillFieldElements.keys());
|
||||
const formFieldElements = cachedFormFieldElements?.length
|
||||
? cachedFormFieldElements
|
||||
@@ -466,8 +480,17 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
|
||||
element: ElementWithOpId<FormFieldElement>,
|
||||
autofillFieldData: AutofillField,
|
||||
) {
|
||||
const opid = autofillFieldData.opid;
|
||||
|
||||
// Remove old element with same opid if it exists
|
||||
const oldElement = this.autofillFieldsByOpid.get(opid);
|
||||
if (oldElement && oldElement !== element) {
|
||||
this.autofillFieldElements.delete(oldElement);
|
||||
}
|
||||
|
||||
// Always cache the element, even if index is -1 (for dynamically added fields)
|
||||
this.autofillFieldElements.set(element, autofillFieldData);
|
||||
this.autofillFieldsByOpid.set(opid, element);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1032,6 +1055,7 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
|
||||
|
||||
this._autofillFormElements.clear();
|
||||
this.autofillFieldElements.clear();
|
||||
this.autofillFieldsByOpid.clear();
|
||||
|
||||
// Reset shadow root tracking on navigation
|
||||
this.domQueryService.resetObservedShadowRoots();
|
||||
@@ -1296,7 +1320,12 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
|
||||
}
|
||||
|
||||
if (this.autofillFieldElements.has(element)) {
|
||||
const autofillFieldData = this.autofillFieldElements.get(element);
|
||||
this.autofillFieldElements.delete(element);
|
||||
// Also remove from opid reverse index
|
||||
if (autofillFieldData?.opid) {
|
||||
this.autofillFieldsByOpid.delete(autofillFieldData.opid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user