Bug 1828408 - Use WeakRef instead of Cu.getWeakReference. r=credential-management-reviewers,dimi

Differential Revision: https://phabricator.services.mozilla.com/D179722
This commit is contained in:
Issam Mani 2023-07-11 15:34:26 +00:00
Родитель b5828473c9
Коммит 6f728cec9e
15 изменённых файлов: 49 добавлений и 72 удалений

Просмотреть файл

@ -918,7 +918,7 @@ function do_test(testcases, testFn) {
}
handler.activeSection.fieldDetails.forEach(field => {
let element = field.elementWeakRef.get();
let element = field.element;
if (!testcase.profileData[field.fieldName]) {
// Avoid waiting for `change` event of a input with a blank value to
// be filled.

Просмотреть файл

@ -104,7 +104,7 @@ add_task(async function do_test() {
handler.activeSection.clearPopulatedForm();
handler.activeSection.fieldDetails.forEach(detail => {
let element = detail.elementWeakRef.get();
let element = detail.element;
let id = element.id;
Assert.equal(
element.value,

Просмотреть файл

@ -585,8 +585,8 @@ function verifyDetails(handlerDetails, testCaseDetails) {
"contactType"
);
Assert.equal(
detail.elementWeakRef.get(),
testCaseDetails[index].elementWeakRef.get(),
detail.element,
testCaseDetails[index].elementWeakRef.deref(),
"DOM reference"
);
});
@ -610,7 +610,7 @@ for (let tc of TESTCASES) {
let elementRef = doc.getElementById(
testcase.ids?.[idx] ?? field.fieldName
);
field.elementWeakRef = Cu.getWeakReference(elementRef);
field.elementWeakRef = new WeakRef(elementRef);
});
let form = doc.querySelector("form");

Просмотреть файл

@ -1303,7 +1303,7 @@ for (let testcase of TESTCASES) {
let value = testcase.profileData[i][field];
let cache =
handler.activeSection._cacheValue.matchingSelectOption.get(select);
let targetOption = cache[value] && cache[value].get();
let targetOption = cache[value] && cache[value].deref();
Assert.notEqual(targetOption, null);
Assert.equal(targetOption, expectedOption);

Просмотреть файл

@ -260,7 +260,7 @@ for (let localeTests of TESTCASES) {
handler.activeSection._cacheValue.matchingSelectOption.get(
select
);
let targetOption = cache[value] && cache[value].get();
let targetOption = cache[value] && cache[value].deref();
Assert.notEqual(targetOption, null);
Assert.equal(targetOption, expectedOption);

Просмотреть файл

@ -154,7 +154,7 @@ function inputDetailAssertion(detail, expected) {
Assert.equal(detail.addressType, expected.addressType);
Assert.equal(detail.contactType, expected.contactType);
Assert.equal(detail.fieldName, expected.fieldName);
Assert.equal(detail.elementWeakRef.get(), expected.elementWeakRef.get());
Assert.equal(detail.element, expected.elementWeakRef.deref());
}
TESTCASES.forEach(testcase => {
@ -173,8 +173,7 @@ TESTCASES.forEach(testcase => {
// Put the input element reference to `element` to make sure the result of
// `activeFieldDetail` contains the same input element.
testcase.expectedResult[i].input.elementWeakRef =
Cu.getWeakReference(input);
testcase.expectedResult[i].input.elementWeakRef = new WeakRef(input);
inputDetailAssertion(
FormAutofillContent.activeFieldDetail,
@ -191,9 +190,7 @@ TESTCASES.forEach(testcase => {
" > *[autocomplete=" +
formDetail.fieldName +
"]";
formDetail.elementWeakRef = Cu.getWeakReference(
doc.querySelector(queryString)
);
formDetail.elementWeakRef = new WeakRef(doc.querySelector(queryString));
}
FormAutofillContent.activeFormDetails.forEach((detail, index) => {

Просмотреть файл

@ -181,9 +181,7 @@ function run_tests(testcases) {
await handler.activeSection.previewFormFields(adaptedProfile);
for (let field of handler.fieldDetails) {
let actual = handler.getFilledStateByElement(
field.elementWeakRef.get()
);
let actual = handler.getFilledStateByElement(field.element);
let expected = testcase.expectedResultState[field.fieldName];
info(`Checking ${field.fieldName} state`);
Assert.equal(

Просмотреть файл

@ -66,7 +66,7 @@ class AutofillTelemetryBase {
let extra = this.#initFormEventExtra("unavailable");
for (let fieldDetail of section.fieldDetails) {
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
let state = profile[fieldDetail.fieldName] ? "filled" : "not_filled";
if (
section.handler.getFilledStateByElement(element) ==
@ -364,7 +364,7 @@ class CreditCardTelemetry extends AutofillTelemetryBase {
};
for (let fieldDetail of section.fieldDetails) {
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
let state = profile[fieldDetail.fieldName] ? "filled" : "not_filled";
if (
section.handler.getFilledStateByElement(element) ==

Просмотреть файл

@ -26,11 +26,11 @@ export class FormAutofillChild {
this.fieldDetailsManager.identifyAutofillFields(element);
// Only ping swift if current field is a cc field
if (validDetails?.find(field => field.elementWeakRef.get() === element)) {
if (validDetails?.find(field => field.element === element)) {
const fieldNamesWithValues = validDetails?.reduce(
(acc, field) => ({
...acc,
[field.fieldName]: field.elementWeakRef.get().value,
[field.fieldName]: field.element.value,
}),
{}
);

Просмотреть файл

@ -282,9 +282,7 @@ export var FormAutofillContent = {
const validDetails =
this._fieldDetailsManager.identifyAutofillFields(element);
validDetails?.forEach(detail =>
this._markAsAutofillField(detail.elementWeakRef.get())
);
validDetails?.forEach(detail => this._markAsAutofillField(detail.element));
},
clearForm() {

Просмотреть файл

@ -17,17 +17,6 @@ HTMLInputElement.prototype.setUserInput = function (value) {
this.dispatchEvent(new Event("input", { bubbles: true }));
};
// TODO: Bug 1828408.
// Use WeakRef API directly in our codebase instead of legacy Cu.getWeakReference.
window.Cu = class {
static getWeakReference(elements) {
const elementsWeakRef = new WeakRef(elements);
return {
get: () => elementsWeakRef.deref(),
};
}
};
// Mimic the behavior of .getAutocompleteInfo()
// It should return an object with a fieldName property matching the autocomplete attribute
// only if it's a valid value from this list https://searchfox.org/mozilla-central/source/dom/base/AutocompleteFieldList.h#89-149

Просмотреть файл

@ -47,7 +47,7 @@ export class FieldDetail {
fieldName = null,
{ autocompleteInfo = {}, confidence = null } = {}
) {
this.elementWeakRef = Cu.getWeakReference(element);
this.elementWeakRef = new WeakRef(element);
this.identifier = `${element.id}/${element.name}`;
this.fieldName = fieldName;
@ -65,7 +65,7 @@ export class FieldDetail {
}
get element() {
return this.elementWeakRef.get();
return this.elementWeakRef.deref();
}
get sectionName() {
@ -98,12 +98,12 @@ export class FieldScanner {
* The callback function that is used to infer the field info of a given element
*/
constructor(elements, inferFieldInfoFn) {
this.#elementsWeakRef = Cu.getWeakReference(elements);
this.#elementsWeakRef = new WeakRef(elements);
this.#inferFieldInfoFn = inferFieldInfoFn;
}
get #elements() {
return this.#elementsWeakRef.get();
return this.#elementsWeakRef.deref();
}
/**

Просмотреть файл

@ -130,9 +130,7 @@ export class FormAutofillHandler {
}
this.changeFieldState(targetFieldDetail, FIELD_STATES.NORMAL);
const section = this.getSectionByElement(
targetFieldDetail.elementWeakRef.get()
);
const section = this.getSectionByElement(targetFieldDetail.element);
section?.clearFilled(targetFieldDetail);
}
}
@ -293,7 +291,7 @@ export class FormAutofillHandler {
* Used to determine the next state
*/
changeFieldState(fieldDetail, nextState) {
const element = fieldDetail.elementWeakRef.get();
const element = fieldDetail.element;
if (!element) {
this.log.warn(
fieldDetail.fieldName,

Просмотреть файл

@ -164,9 +164,7 @@ export class FormAutofillSection {
}
getFieldDetailByElement(element) {
return this.fieldDetails.find(
detail => detail.elementWeakRef.get() == element
);
return this.fieldDetails.find(detail => detail.element == element);
}
getFieldDetailByName(fieldName) {
@ -193,14 +191,14 @@ export class FormAutofillSection {
continue;
}
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
if (!HTMLSelectElement.isInstance(element)) {
continue;
}
let cache = this._cacheValue.matchingSelectOption.get(element) || {};
let value = profile[fieldName];
if (cache[value] && cache[value].get()) {
if (cache[value] && cache[value].deref()) {
continue;
}
@ -210,7 +208,7 @@ export class FormAutofillSection {
fieldName
);
if (option) {
cache[value] = Cu.getWeakReference(option);
cache[value] = new WeakRef(option);
this._cacheValue.matchingSelectOption.set(element, cache);
} else {
if (cache[value]) {
@ -231,7 +229,7 @@ export class FormAutofillSection {
continue;
}
let element = detail.elementWeakRef.get();
let element = detail.element;
if (!element) {
continue;
}
@ -347,7 +345,7 @@ export class FormAutofillSection {
// 2. the invalid value set
// 3. value already chosen in select element
const element = fieldDetail.elementWeakRef.get();
const element = fieldDetail.element;
// Skip the field if it is null or readonly or disabled
if (!FormAutofillUtils.isFieldAutofillable(element)) {
continue;
@ -379,7 +377,7 @@ export class FormAutofillSection {
}
} else if (HTMLSelectElement.isInstance(element)) {
let cache = this._cacheValue.matchingSelectOption.get(element) || {};
let option = cache[value] && cache[value].get();
let option = cache[value] && cache[value].deref();
if (!option) {
continue;
}
@ -412,7 +410,7 @@ export class FormAutofillSection {
this.preparePreviewProfile(profile);
for (const fieldDetail of this.fieldDetails) {
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
// Skip the field if it is null or readonly or disabled
if (!FormAutofillUtils.isFieldAutofillable(element)) {
continue;
@ -428,7 +426,7 @@ export class FormAutofillSection {
if (value) {
const cache =
this._cacheValue.matchingSelectOption.get(element) ?? {};
const option = cache[value]?.get();
const option = cache[value]?.deref();
value = option?.text ?? "";
}
} else if (element.value && element.value != element.defaultValue) {
@ -454,7 +452,7 @@ export class FormAutofillSection {
let isAutofilled = false;
const dimFieldDetails = [];
for (const fieldDetail of this.fieldDetails) {
const element = fieldDetail.elementWeakRef.get();
const element = fieldDetail.element;
if (HTMLSelectElement.isInstance(element)) {
// Dim fields are those we don't attempt to revert their value
@ -471,7 +469,7 @@ export class FormAutofillSection {
// that user had intention to clear the filled form manually.
for (const fieldDetail of dimFieldDetails) {
// If we can't find a selected option, then we should just reset to the first option's value
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
this._resetSelectElementValue(element);
this.handler.changeFieldState(fieldDetail, FIELD_STATES.NORMAL);
}
@ -486,7 +484,7 @@ export class FormAutofillSection {
this.log.debug("clear previewed fields");
for (const fieldDetail of this.fieldDetails) {
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
if (!element) {
this.log.warn(fieldDetail.fieldName, "is unreachable");
continue;
@ -512,7 +510,7 @@ export class FormAutofillSection {
*/
clearPopulatedForm() {
for (let fieldDetail of this.fieldDetails) {
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
if (!element) {
this.log.warn(fieldDetail.fieldName, "is unreachable");
continue;
@ -534,7 +532,7 @@ export class FormAutofillSection {
resetFieldStates() {
for (const fieldDetail of this.fieldDetails) {
const element = fieldDetail.elementWeakRef.get();
const element = fieldDetail.element;
element.removeEventListener("input", this, { mozSystemGroup: true });
this.handler.changeFieldState(fieldDetail, FIELD_STATES.NORMAL);
}
@ -563,10 +561,10 @@ export class FormAutofillSection {
if (countOfCCNumbers == 4) {
countOfCCNumbers = 0;
condensedDetails[i].fieldValue =
condensedDetails[i].elementWeakRef.get()?.value +
condensedDetails[i + 1].elementWeakRef.get()?.value +
condensedDetails[i + 2].elementWeakRef.get()?.value +
condensedDetails[i + 3].elementWeakRef.get()?.value;
condensedDetails[i].element?.value +
condensedDetails[i + 1].element?.value +
condensedDetails[i + 2].element?.value +
condensedDetails[i + 3].element?.value;
condensedDetails.splice(i + 1, 3);
}
} else {
@ -606,7 +604,7 @@ export class FormAutofillSection {
this._condenseMultipleCCNumberFields(condensedDetails);
condensedDetails.forEach(detail => {
const element = detail.elementWeakRef.get();
const element = detail.element;
// Remove the unnecessary spaces
let value = detail.fieldValue ?? (element && element.value.trim());
value = this.computeFillingValue(value, detail, element);
@ -748,7 +746,7 @@ export class FormAutofillAddressSection extends FormAutofillSection {
let streetAddressDetail = this.getFieldDetailByName("street-address");
if (
streetAddressDetail &&
HTMLInputElement.isInstance(streetAddressDetail.elementWeakRef.get())
HTMLInputElement.isInstance(streetAddressDetail.element)
) {
profile["street-address"] = profile["-moz-street-address-one-line"];
}
@ -783,7 +781,7 @@ export class FormAutofillAddressSection extends FormAutofillSection {
return;
}
let element = detail.elementWeakRef.get();
let element = detail.element;
let _pattern;
let testPattern = str => {
if (!_pattern) {
@ -985,7 +983,7 @@ export class FormAutofillCreditCardSection extends FormAutofillSection {
// when determining whether a form has only a high-confidence cc-* field a valid
// credit card section. We can remove this restriction once we are confident
// about only using fathom.
const element = highConfidenceField.elementWeakRef.get();
const element = highConfidenceField.element;
const root = element.form || element.ownerDocument;
const inputs = root.querySelectorAll("input:not([type=hidden])");
if (inputs.length == 1 && inputs[0] == element) {
@ -1111,7 +1109,7 @@ export class FormAutofillCreditCardSection extends FormAutofillSection {
if (!detail) {
return null;
}
let element = detail.elementWeakRef.get();
let element = detail.element;
return element.tagName === "INPUT" ? element : null;
};
let month = getInputElementByField("cc-exp-month", this);
@ -1142,7 +1140,7 @@ export class FormAutofillCreditCardSection extends FormAutofillSection {
// Get the window for the form field.
let window;
for (let fieldDetail of this.fieldDetails) {
let element = fieldDetail.elementWeakRef.get();
let element = fieldDetail.element;
if (element) {
window = element.ownerGlobal;
break;

Просмотреть файл

@ -41,7 +41,7 @@ export class FormStateManager {
return null;
}
for (let detail of formDetails) {
let detailElement = detail.elementWeakRef.get();
let detailElement = detail.element;
if (detailElement && this.activeInput == detailElement) {
this._activeItems.fieldDetail = detail;
break;
@ -66,8 +66,7 @@ export class FormStateManager {
}
get activeInput() {
let elementWeakRef = this._activeItems.elementWeakRef;
return elementWeakRef ? elementWeakRef.get() : null;
return this._activeItems.elementWeakRef?.deref();
}
get activeHandler() {
@ -131,7 +130,7 @@ export class FormStateManager {
return;
}
this._activeItems = {
elementWeakRef: Cu.getWeakReference(element),
elementWeakRef: new WeakRef(element),
fieldDetail: null,
};
}