Skip to content
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

Merged
merged 8 commits into from
Jul 21, 2023
Merged

Ema/fix mutating forms #358

merged 8 commits into from
Jul 21, 2023

Conversation

GioSensation
Copy link
Member

@GioSensation GioSensation commented Jul 12, 2023

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:

Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
Signed-off-by: Emanuele Feliziani <feliziani.emanuele@gmail.com>
@GioSensation GioSensation self-assigned this Jul 12, 2023
@@ -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
Copy link
Member Author

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) {
Copy link
Member Author

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)
Copy link
Member Author

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.

@GioSensation GioSensation marked this pull request as ready for review July 12, 2023 09:56
… 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()
}
Copy link
Member Author

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.

Copy link
Collaborator

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)
Copy link
Member Author

@GioSensation GioSensation Jul 21, 2023

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) {
Copy link
Member Author

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.

Copy link
Collaborator

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
Copy link
Member Author

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
Copy link
Member Author

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;`
Copy link
Member Author

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.

Copy link
Collaborator

@shakyShane shakyShane left a 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.')
Copy link
Collaborator

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.')
Copy link
Collaborator

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.')
Copy link
Collaborator

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants