Skip to content

Commit

Permalink
Correct autocorrect attribute (empty value, email/password/url inputs)
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=246344
rdar://101036922

Reviewed by NOBODY (OOPS!).

Align with the standardized version of the autocorrect attribute, which
does not support Email, URL, and Password fields and does not treat the
empty string value in a special way. For details see
whatwg/html#5841

Test is upstreamed at
web-platform-tests/wpt@2767f5f

* LayoutTests/imported/w3c/web-platform-tests/html/editing/editing-0/autocorrection/autocorrection-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/html/editing/editing-0/autocorrection/autocorrection.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/html/editing/editing-0/autocorrection/w3c-import.log: Added.
* LayoutTests/platform/glib/imported/w3c/web-platform-tests/html/editing/editing-0/autocorrection/autocorrection-expected.txt: Added.
* Source/WebCore/html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::shouldAutocorrect const):
  • Loading branch information
annevk committed Aug 27, 2024
1 parent ea20b8a commit 6f98299
Show file tree
Hide file tree
Showing 5 changed files with 386 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

PASS Test that the autocorrect attribute is available on HTMLInputElement.
PASS Test that the autocorrect attribute is available on HTMLTextAreaElement.
PASS Test that the autocorrect attribute is available on div.
PASS Test that the autocorrect attribute is available on form.
PASS Test setting the autocorrect IDL attribute.
PASS Test setting the autocorrect attribute using setAttribute.
PASS Test inheriting autocorrection from a form.
PASS Test autocorrection in an editing host.
PASS Test autocorrection in password, URL, and email inputs.

Original file line number Diff line number Diff line change
@@ -0,0 +1,342 @@
<!DOCTYPE html>
<html>
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#autocorrection">
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>

test(() => {
assert_true('autocorrect' in document.createElement('input'));
}, "Test that the autocorrect attribute is available on HTMLInputElement.");

test(() => {
assert_true('autocorrect' in document.createElement('textarea'));
}, "Test that the autocorrect attribute is available on HTMLTextAreaElement.");

test(() => {
assert_true('autocorrect' in document.createElement('div'));
}, "Test that the autocorrect attribute is available on div.");

test(() => {
assert_true('autocorrect' in document.createElement('form'));
}, "Test that the autocorrect attribute is available on form.");

test(() => {
[ document.createElement('input'),
document.createElement('textarea'),
document.createElement('div'),
document.createElement('form') ].forEach(e => {
e.autocorrect = true;
assert_true(e.autocorrect);
assert_equals(e.getAttribute('autocorrect'), 'on');

e.autocorrect = 'hello';
assert_true(e.autocorrect);
assert_equals(e.getAttribute('autocorrect'), 'on');

e.autocorrect = false;
assert_false(e.autocorrect);
assert_equals(e.getAttribute('autocorrect'), 'off');

e.autocorrect = 0;
assert_false(e.autocorrect);
assert_equals(e.getAttribute('autocorrect'), 'off');
});
}, "Test setting the autocorrect IDL attribute.");

test(() => {
[ document.createElement('input'),
document.createElement('textarea'),
document.createElement('div'),
document.createElement('form') ].forEach(e => {
e.setAttribute('autocorrect', 'on');
assert_equals(e.getAttribute('autocorrect'), 'on');
assert_true(e.autocorrect);

e.setAttribute('autocorrect', 'ON');
assert_equals(e.getAttribute('autocorrect'), 'ON');
assert_true(e.autocorrect);

e.setAttribute('autocorrect', 'off');
assert_equals(e.getAttribute('autocorrect'), 'off');
assert_false(e.autocorrect);

e.setAttribute('autocorrect', 'OFF');
assert_equals(e.getAttribute('autocorrect'), 'OFF');
assert_false(e.autocorrect);

e.setAttribute('autocorrect', 'invalid_value');
assert_equals(e.getAttribute('autocorrect'), 'invalid_value');
assert_true(e.autocorrect);

e.setAttribute('autocorrect', '');
assert_equals(e.getAttribute('autocorrect'), '');
assert_true(e.autocorrect);

e.removeAttribute('autocorrect');
assert_false(e.hasAttribute('autocorrect'));
assert_true(e.autocorrect);
});
}, "Test setting the autocorrect attribute using setAttribute.");

test(t => {
const testData = [
{
formValue: null,
formElementValue: null,
inheritedResult: true,
uninheritedResult: true
},
{
formValue: null,
formElementValue: 'on',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'on',
formElementValue: null,
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'on',
formElementValue: 'on',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: null,
formElementValue: 'off',
inheritedResult: false,
uninheritedResult: false
},
{
formValue: 'off',
formElementValue: null,
inheritedResult: false,
uninheritedResult: true
},
{
formValue: 'off',
formElementValue: 'off',
inheritedResult: false,
uninheritedResult: false
},
{
formValue: 'on',
formElementValue: 'off',
inheritedResult: false,
uninheritedResult: false
},
{
formValue: 'off',
formElementValue: 'on',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'off',
formElementValue: 'foo',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'off',
formElementValue: 'bar',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'off',
formElementValue: '',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'off',
formElementValue: '',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'on',
formElementValue: 'foo',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'on',
formElementValue: 'bar',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'on',
formElementValue: '',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'on',
formElementValue: '',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'foo',
formElementValue: 'off',
inheritedResult: false,
uninheritedResult: false
},
{
formValue: 'bar',
formElementValue: 'off',
inheritedResult: false,
uninheritedResult: false
},
{
formValue: '',
formElementValue: 'off',
inheritedResult: false,
uninheritedResult: false
},
{
formValue: '',
formElementValue: 'off',
inheritedResult: false,
uninheritedResult: false
},
{
formValue: 'foo',
formElementValue: 'on',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: 'bar',
formElementValue: 'on',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: '',
formElementValue: 'on',
inheritedResult: true,
uninheritedResult: true
},
{
formValue: '',
formElementValue: 'on',
inheritedResult: true,
uninheritedResult: true
}
];

const formElements = [
{element: 'button', inherits: true},
{element: 'fieldset', inherits: true},
{element: 'img', inherits: false},
{element: 'input', inherits: true},
{element: 'object', inherits: false},
{element: 'output', inherits: true},
{element: 'select', inherits: true},
{element: 'textarea', inherits: true},
];

const form = document.createElement('form');
form.id = 'form';
document.body.appendChild(form);
t.add_cleanup(() => form.remove());

testData.forEach(data => {
form.removeAttribute('autocorrect');

if (data.formValue !== null) {
form.setAttribute('autocorrect', data.formValue);
}

formElements.forEach(elementData => {
const element = document.createElement(elementData.element);
form.appendChild(element);

const element2 = document.createElement(elementData.element);
element2.setAttribute('form', 'form');
document.body.appendChild(element2);
t.add_cleanup(() => element2.remove());

if (data.formElementValue !== null) {
element.setAttribute('autocorrect', data.formElementValue);
element2.setAttribute('autocorrect', data.formElementValue);
}

const descriptionSuffix = 'with "' + data.formValue
+ '" and form element with "'+ data.formElementValue + '"';

if (elementData.inherits) {
assert_equals(element.autocorrect, data.inheritedResult,
`${elementData.element} element with form parent `
+ `${descriptionSuffix}`);
assert_equals(element2.autocorrect, data.inheritedResult,
`${elementData.element} element with form owner attribute`
+ ` set ${descriptionSuffix}`);
} else {
assert_equals(element.autocorrect, data.uninheritedResult,
`${elementData.element} element with form parent `
+ `${descriptionSuffix}`);
assert_equals(element2.autocorrect, data.uninheritedResult,
`${elementData.element} element with form owner attribute`
+ `set ${descriptionSuffix}`);
}
});
});
}, "Test inheriting autocorrection from a form.")

test(t => {
const editingHost = document.createElement("div");
const container = document.createElement("br");
editingHost.contentEditable = true;
editingHost.appendChild(container);
document.body.appendChild(editingHost);
t.add_cleanup(() => editingHost.remove());

editingHost.autocorrect = false;
container.autocorrect = true;

assert_false(editingHost.autocorrect);
assert_true(container.autocorrect);

editingHost.autocorrect = true;
container.autocorrect = false;

assert_true(editingHost.autocorrect);
assert_false(container.autocorrect);
}, "Test autocorrection in an editing host.")

test(t => {
const form = document.createElement("form");
const passwordInput = document.createElement("input");
const emailInput = document.createElement("input");
const urlInput = document.createElement("input");
const textInput = document.createElement("input");
passwordInput.type = "password";
emailInput.type = "email";
urlInput.type = "url";

form.setAttribute("autocorrect", "on");

document.body.appendChild(form);
t.add_cleanup(() => form.remove());
for (const input of [passwordInput, emailInput, urlInput, textInput])
form.appendChild(input);

assert_false(passwordInput.autocorrect, `Input of type ${passwordInput.type}`);
assert_false(emailInput.autocorrect, `Input of type ${emailInput.type}`);
assert_false(urlInput.autocorrect, `Input of type ${urlInput.type}`);
assert_true(textInput.autocorrect, `Input of type ${textInput.type}`);
}, "Test autocorrection in password, URL, and email inputs.")

</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
The tests in this directory were imported from the W3C repository.
Do NOT modify these tests directly in WebKit.
Instead, create a pull request on the WPT github:
https://github.com/web-platform-tests/wpt

Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport

Do NOT modify or remove this file.

------------------------------------------------------------------------
Properties requiring vendor prefixes:
None
Property values requiring vendor prefixes:
None
------------------------------------------------------------------------
List of files:
/LayoutTests/imported/w3c/web-platform-tests/html/editing/editing-0/autocorrection/autocorrection.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

FAIL Test that the autocorrect attribute is available on HTMLInputElement. assert_true: expected true got false
FAIL Test that the autocorrect attribute is available on HTMLTextAreaElement. assert_true: expected true got false
FAIL Test that the autocorrect attribute is available on div. assert_true: expected true got false
FAIL Test that the autocorrect attribute is available on form. assert_true: expected true got false
FAIL Test setting the autocorrect IDL attribute. assert_equals: expected (string) "on" but got (object) null
FAIL Test setting the autocorrect attribute using setAttribute. assert_true: expected true got undefined
FAIL Test inheriting autocorrection from a form. assert_equals: button element with form parent with "null" and form element with "null" expected (boolean) true but got (undefined) undefined
PASS Test autocorrection in an editing host.
FAIL Test autocorrection in password, URL, and email inputs. assert_false: Input of type password expected false got undefined

6 changes: 5 additions & 1 deletion Source/WebCore/html/HTMLFormControlElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,12 @@ void HTMLFormControlElement::dispatchBlurEvent(RefPtr<Element>&& newFocusedEleme

bool HTMLFormControlElement::shouldAutocorrect() const
{
if (RefPtr input = dynamicDowncast<HTMLInputElement>(*this); input
&& (input->isPasswordField() || input->isEmailField() || input->isURLField())) {
return false;
}
const AtomString& autocorrectValue = attributeWithoutSynchronization(autocorrectAttr);
if (!autocorrectValue.isEmpty())
if (!autocorrectValue.isNull())
return !equalLettersIgnoringASCIICase(autocorrectValue, "off"_s);
if (RefPtr<HTMLFormElement> form = this->form())
return form->shouldAutocorrect();
Expand Down

0 comments on commit 6f98299

Please sign in to comment.