calebdwilliams/element-internals-polyfill

FormData values polyfilled in reverse order

ale-cci opened this issue ยท 2 comments

Hi! ๐Ÿ‘‹

Firstly, thanks for your work on this project!

It seems that when a custom-element internals are of type FormData, the value are attached in the page in the opposite order.

The probelm is probably caused by createHiddenInput that directly appends the input tag below the custom element.
When the function is called multiple times with the "formdata order" the elements are appended in reverse.

Here is a code snippet to reproduce the issue:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://unpkg.com/element-internals-polyfill@1.1.6/dist/index.js"></script>
  </head>
  <body>
    <form>
      <sample-element></sample-element>
      <input type="submit">
    </form>

    <script>
      class SampleElement extends HTMLElement {
        static formAssociated = true

        constructor() {
          super()
          this.attachShadow({mode: 'open'})
          this._internals = this.attachInternals()
        }

        connectedCallback() {
          this._internals.setFormValue(this._formValue())
          this.shadowRoot.innerHTML = '<span> Test </span>'
        }

        _formValue() {
          const formData = new FormData()
          formData.append('one', 1)
          formData.append('two', 2)
          formData.append('three', 3)
          return formData
        }
      }

      window.customElements.define('sample-element', SampleElement)
    </script>
  </body>
</html>

When submitted on a browser that does not support attachInternals the resulting querystring is: ?three=3&two=2&one=1, instead of the expected ?one=1&two=2&three=3.

Using patch-package, here is is the diff that solved my problem:

diff --git a/node_modules/element-internals-polyfill/dist/index.js b/node_modules/element-internals-polyfill/dist/index.js
index 83f2d1c..debf61b 100644
--- a/node_modules/element-internals-polyfill/dist/index.js
+++ b/node_modules/element-internals-polyfill/dist/index.js
@@ -479,7 +479,7 @@
                 }
             }
             else if (value != null && value instanceof FormData) {
-                value.forEach((formDataValue, formDataKey) => {
+                Array.from(value).reverse().forEach(([formDataKey, formDataValue]) => {
                     if (typeof formDataValue === 'string') {
                         const hiddenInput = createHiddenInput(ref, this);
                         hiddenInput.name = formDataKey;

Nice catch. Iโ€™m away from my computer right now but will get this merged/released ASAP.

Fixed in element-internals-polyfill@1.1.7