diff --git a/packages/@react-aria/form/src/useFormValidation.ts b/packages/@react-aria/form/src/useFormValidation.ts index b4699bf8046..707984cbdac 100644 --- a/packages/@react-aria/form/src/useFormValidation.ts +++ b/packages/@react-aria/form/src/useFormValidation.ts @@ -145,7 +145,7 @@ function getNativeValidity(input: ValidatableElement): ValidationResult { function getFirstInvalidInput(form: HTMLFormElement): ValidatableElement | null { for (let i = 0; i < form.elements.length; i++) { let element = form.elements[i] as ValidatableElement; - if (!element.validity.valid) { + if (element.validity?.valid === false) { return element; } } diff --git a/packages/react-aria-components/test/Form.test.js b/packages/react-aria-components/test/Form.test.js index ad0d3642f91..b2b931f2e11 100644 --- a/packages/react-aria-components/test/Form.test.js +++ b/packages/react-aria-components/test/Form.test.js @@ -188,4 +188,50 @@ describe('Form', () => { let form = getByTestId('form'); expect(form).toHaveAttribute('data-custom', 'true'); }); + + it('should not throw when form contains elements without validity property', async () => { + function Test() { + return ( +
+ + + + + + +
+ ); + } + + let {getByTestId, getByRole} = render(); + let form = getByTestId('form'); + let input = getByRole('textbox'); + + // Mock form.elements to include an element without validity property (simulates Web Component) + let originalElements = form.elements; + let mockElement = {name: 'custom-element'}; // No validity property + Object.defineProperty(form, 'elements', { + get: () => ({ + length: originalElements.length + 1, + [Symbol.iterator]: function* () { + yield mockElement; + yield* originalElements; + }, + 0: mockElement, + ...Array.from(originalElements).reduce((acc, el, i) => ({...acc, [i + 1]: el}), {}) + }), + configurable: true + }); + + // Should not throw when iterating form.elements with element lacking validity + await user.click(getByRole('button')); + + expect(document.activeElement).toBe(input); + + // Restore original elements + Object.defineProperty(form, 'elements', { + get: () => originalElements, + configurable: true + }); + }); });