wp/wp-includes/js/dist/vendor/wp-polyfill-formdata.js
changeset 19 3d72ae0968f4
parent 18 be944660c56a
--- a/wp/wp-includes/js/dist/vendor/wp-polyfill-formdata.js	Wed Sep 21 18:19:35 2022 +0200
+++ b/wp/wp-includes/js/dist/vendor/wp-polyfill-formdata.js	Tue Sep 27 16:37:53 2022 +0200
@@ -1,3 +1,5 @@
+/* formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
+
 /* global FormData self Blob File */
 /* eslint-disable no-inner-declarations */
 
@@ -40,16 +42,13 @@
     new File([], '') // eslint-disable-line
   } catch (a) {
     global.File = function File (b, d, c) {
-      const blob = new Blob(b, c)
+      const blob = new Blob(b, c || {})
       const t = c && void 0 !== c.lastModified ? new Date(c.lastModified) : new Date()
 
       Object.defineProperties(blob, {
         name: {
           value: d
         },
-        lastModifiedDate: {
-          value: t
-        },
         lastModified: {
           value: +t
         },
@@ -70,50 +69,52 @@
     }
   }
 
-  function normalizeValue ([name, value, filename]) {
-    if (value instanceof Blob) {
-      // Should always returns a new File instance
-      // console.assert(fd.get(x) !== fd.get(x))
-      value = new File([value], filename, {
-        type: value.type,
-        lastModified: value.lastModified
-      })
-    }
-
-    return [name, value]
-  }
-
   function ensureArgs (args, expected) {
     if (args.length < expected) {
       throw new TypeError(`${expected} argument required, but only ${args.length} present.`)
     }
   }
 
+  /**
+   * @param {string} name
+   * @param {string | undefined} filename
+   * @returns {[string, File|string]}
+   */
   function normalizeArgs (name, value, filename) {
-    return value instanceof Blob
-      // normalize name and filename if adding an attachment
-      ? [String(name), value, filename !== undefined
-        ? filename + '' // Cast filename to string if 3th arg isn't undefined
-        : typeof value.name === 'string' // if name prop exist
-          ? value.name // Use File.name
-          : 'blob'] // otherwise fallback to Blob
+    if (value instanceof Blob) {
+      filename = filename !== undefined
+      ? String(filename + '')
+      : typeof value.name === 'string'
+      ? value.name
+      : 'blob'
 
-      // If no attachment, just cast the args to strings
-      : [String(name), String(value)]
+      if (value.name !== filename || Object.prototype.toString.call(value) === '[object Blob]') {
+        value = new File([value], filename)
+      }
+      return [String(name), value]
+    }
+    return [String(name), String(value)]
   }
 
-  // normalize linefeeds for textareas
+  // normalize line feeds for textarea
   // https://html.spec.whatwg.org/multipage/form-elements.html#textarea-line-break-normalisation-transformation
   function normalizeLinefeeds (value) {
-    return value.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n')
+    return value.replace(/\r?\n|\r/g, '\r\n')
   }
 
+  /**
+   * @template T
+   * @param {ArrayLike<T>} arr
+   * @param {{ (elm: T): void; }} cb
+   */
   function each (arr, cb) {
     for (let i = 0; i < arr.length; i++) {
       cb(arr[i])
     }
   }
 
+  const escape = str => str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22')
+
   /**
    * @implements {Iterable}
    */
@@ -121,14 +122,14 @@
     /**
      * FormData class
      *
-     * @param {HTMLElement=} form
+     * @param {HTMLFormElement=} form
      */
     constructor (form) {
+      /** @type {[string, string|File][]} */
       this._data = []
 
       const self = this
-
-      form && each(form.elements, elm => {
+      form && each(form.elements, (/** @type {HTMLInputElement} */ elm) => {
         if (
           !elm.name ||
           elm.disabled ||
@@ -196,7 +197,7 @@
      */
     * entries () {
       for (var i = 0; i < this._data.length; i++) {
-        yield normalizeValue(this._data[i])
+        yield this._data[i]
       }
     }
 
@@ -205,7 +206,6 @@
      *
      * @param   {Function}  callback  Executed for each item with parameters (value, name, thisArg)
      * @param   {Object=}   thisArg   `this` context for callback function
-     * @return  {undefined}
      */
     forEach (callback, thisArg) {
       ensureArgs(arguments, 1)
@@ -216,7 +216,7 @@
 
     /**
      * Return first field value given name
-     * or null if non existen
+     * or null if non existent
      *
      * @param   {string}  name      Field name
      * @return  {string|File|null}  value Fields value
@@ -227,7 +227,7 @@
       name = String(name)
       for (let i = 0; i < entries.length; i++) {
         if (entries[i][0] === name) {
-          return normalizeValue(entries[i])[1]
+          return entries[i][1]
         }
       }
       return null
@@ -244,7 +244,7 @@
       const result = []
       name = String(name)
       each(this._data, data => {
-        data[0] === name && result.push(normalizeValue(data)[1])
+        data[0] === name && result.push(data[1])
       })
 
       return result
@@ -284,17 +284,17 @@
      * @param   {string}    name      Filed name
      * @param   {string}    value     Field value
      * @param   {string=}   filename  Filename (optional)
-     * @return  {undefined}
      */
     set (name, value, filename) {
       ensureArgs(arguments, 2)
       name = String(name)
+      /** @type {[string, string|File][]} */
       const result = []
       const args = normalizeArgs(name, value, filename)
       let replace = true
 
       // - replace the first occurrence with same name
-      // - discards the remaning with same name
+      // - discards the remaining with same name
       // - while keeping the same order items where added
       each(this._data, data => {
         data[0] === name
@@ -340,38 +340,23 @@
      * @return {Blob} [description]
      */
     ['_blob'] () {
-      const boundary = '----formdata-polyfill-' + Math.random()
-      const chunks = []
-
-      for (const [name, value] of this) {
-        chunks.push(`--${boundary}\r\n`)
-
-        if (value instanceof Blob) {
-          chunks.push(
-            `Content-Disposition: form-data; name="${name}"; filename="${value.name}"\r\n` +
-            `Content-Type: ${value.type || 'application/octet-stream'}\r\n\r\n`,
-            value,
-            '\r\n'
-          )
-        } else {
-          chunks.push(
-            `Content-Disposition: form-data; name="${name}"\r\n\r\n${value}\r\n`
-          )
-        }
-      }
-
-      chunks.push(`--${boundary}--`)
-
-      return new Blob(chunks, {
-        type: 'multipart/form-data; boundary=' + boundary
-      })
+        const boundary = '----formdata-polyfill-' + Math.random(),
+          chunks = [],
+          p = `--${boundary}\r\nContent-Disposition: form-data; name="`
+        this.forEach((value, name) => typeof value == 'string'
+          ? chunks.push(p + escape(normalizeLinefeeds(name)) + `"\r\n\r\n${normalizeLinefeeds(value)}\r\n`)
+          : chunks.push(p + escape(normalizeLinefeeds(name)) + `"; filename="${escape(value.name)}"\r\nContent-Type: ${value.type||"application/octet-stream"}\r\n\r\n`, value, `\r\n`))
+        chunks.push(`--${boundary}--`)
+        return new Blob(chunks, {
+          type: "multipart/form-data; boundary=" + boundary
+        })
     }
 
     /**
      * The class itself is iterable
      * alias for formdata.entries()
      *
-     * @return  {Iterator}
+     * @return {Iterator}
      */
     [Symbol.iterator] () {
       return this.entries()