-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ema/fix mutating forms #358
Conversation
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
… ema/fix-mutating-forms
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
@@ -45,9 +43,6 @@ class Form { | |||
this.form = form | |||
this.matching = matching || createMatching() | |||
this.formAnalyzer = new FormAnalyzer(form, input, matching) | |||
this.isLogin = this.formAnalyzer.isLogin | |||
this.isSignup = this.formAnalyzer.isSignup | |||
this.isHybrid = this.formAnalyzer.isHybrid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These now are all getters, so if we change the formAnalyzer
results, the changes are reflected here.
this.mutObs = new MutationObserver( | ||
(records) => { | ||
const anythingRemoved = records.some(record => record.removedNodes.length > 0) | ||
if (anythingRemoved) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By running only when elements are removed we reduce the overhead.
@@ -9,6 +9,8 @@ const signupRegex = new RegExp( | |||
) | |||
const conservativeSignupRegex = new RegExp(/sign.?up|join|register|enroll|newsletter|subscri(be|ption)|settings|preferences|profile|update/i) | |||
const strictSignupRegex = new RegExp(/sign.?up|join|register|(create|new).+account|enroll|settings|preferences|profile|update/i) | |||
const resetPasswordLink = new RegExp(/(forgot(ten)?|reset|don't remember) (your )?password|password forgotten/i) | |||
const loginProvidersRegex = new RegExp(/ with /i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes here are unrelated to the mutating forms. Just improving accuracy and splitting these two regexes so we can use them independently.
… ema/fix-mutating-forms Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com> # Conflicts: # dist/autofill-debug.js # dist/autofill.js # swift-package/Resources/assets/autofill-debug.js # swift-package/Resources/assets/autofill.js
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
// If the form mutates too much, disconnect to avoid performance issues | ||
if (this.mutObsCount >= MAX_FORM_MUT_OBS_COUNT) { | ||
this.mutObs.disconnect() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this bit to disconnect the observer when form mutations force too many re-scans. This prevents infinite loops and other performance issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
excellent!
@@ -323,8 +362,14 @@ class Form { | |||
if (this.form.matches(selector)) { | |||
this.addInput(this.form) | |||
} else { | |||
this.form.querySelectorAll(selector).forEach(input => this.addInput(input)) | |||
const foundInputs = this.form.querySelectorAll(selector) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a further performance safeguard. If the form contains too many inputs, we stop right away during the initial scan.
if (this.inputs.all.has(input)) return this | ||
|
||
// If the form has too many inputs, destroy everything to avoid performance issues | ||
if (this.inputs.all.size > MAX_INPUTS_PER_FORM) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here we destroy()
the form, removing all listeners and icons, if the form grows over a certain threshold.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
love it!
// Nothing to do with 1-character fields | ||
if (input.maxLength === 1) return this | ||
|
||
if (this.inputs.all.has(input)) return this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to the top to avoid unnecessary work.
maxInputsOnPage: 100 | ||
maxInputsPerPage: MAX_INPUTS_PER_PAGE, | ||
maxFormsPerPage: MAX_FORMS_PER_PAGE, | ||
maxInputsPerForm: MAX_INPUTS_PER_FORM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Centralizing these defaults in the constants.js file.
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
? `transform: translate(${left}px, ${top}px) rotate(180deg); transform-origin: 16px !important;` | ||
: `transform: translate(${left}px, ${top}px) !important;` | ||
? `transform: translate(${Math.floor(left)}px, ${Math.floor(top)}px) rotate(180deg); transform-origin: 18px !important;` | ||
: `transform: translate(${Math.floor(left)}px, ${Math.floor(top)}px) !important;` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this stuff and other CSS changes are of course unrelated. Just squeezing in a 2px reduction in icon size requested by the design folks. The floor
is just to avoid weird artefacts in edge cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great - I think we just need to be conservative with logging, and then this is good to go :)
src/Form/Form.js
Outdated
if (foundInputs.length < MAX_INPUTS_PER_FORM) { | ||
foundInputs.forEach(input => this.addInput(input)) | ||
} else { | ||
console.log('The form has too many inputs, bailing.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs wrapping in a debug check
src/Form/Form.js
Outdated
|
||
// If the form has too many inputs, destroy everything to avoid performance issues | ||
if (this.inputs.all.size > MAX_INPUTS_PER_FORM) { | ||
console.log('The form has too many inputs, destroying.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs wrapping in a debug check?
src/Scanner.js
Outdated
if (this.forms.size < this.options.maxFormsPerPage) { | ||
this.forms.set(parentForm, new Form(parentForm, input, this.device, this.matching, this.shouldAutoprompt)) | ||
} else { | ||
console.log('The page has too many forms, stop adding them.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrap in debug check?
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
Reviewer: @shakyShane
Asana: https://app.asana.com/0/0/1205015898566987/f
Description
Observe form mutations and re-scan the form when input fields are removed. This won't catch all possible forms of mutations, but it's a good first step with reduced overhead.
Steps to test
Test case added. You can test this live on these sites: