diff -r c7c34916027a -r 177826044cd9 wp/wp-includes/js/dist/vendor/wp-polyfill-formdata.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wp/wp-includes/js/dist/vendor/wp-polyfill-formdata.js Mon Oct 14 18:28:13 2019 +0200 @@ -0,0 +1,401 @@ +if (typeof FormData === 'undefined' || !FormData.prototype.keys) { + const global = typeof window === 'object' + ? window : typeof self === 'object' + ? self : this + + // keep a reference to native implementation + const _FormData = global.FormData + + // To be monkey patched + const _send = global.XMLHttpRequest && global.XMLHttpRequest.prototype.send + const _fetch = global.Request && global.fetch + + // Unable to patch Request constructor correctly + // const _Request = global.Request + // only way is to use ES6 class extend + // https://github.com/babel/babel/issues/1966 + + const stringTag = global.Symbol && Symbol.toStringTag + const map = new WeakMap + const wm = o => map.get(o) + const arrayFrom = Array.from || (obj => [].slice.call(obj)) + + // Add missing stringTags to blob and files + if (stringTag) { + if (!Blob.prototype[stringTag]) { + Blob.prototype[stringTag] = 'Blob' + } + + if ('File' in global && !File.prototype[stringTag]) { + File.prototype[stringTag] = 'File' + } + } + + // Fix so you can construct your own File + try { + new File([], '') + } catch (a) { + global.File = function(b, d, 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 + }, + toString: { + value() { + return '[object File]' + } + } + }) + + if (stringTag) { + Object.defineProperty(blob, stringTag, { + value: 'File' + }) + } + + return blob + } + } + + function normalizeValue([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 value + } + + function stringify(name) { + if (!arguments.length) + throw new TypeError('1 argument required, but only 0 present.') + + return [name + ''] + } + + function normalizeArgs(name, value, filename) { + if (arguments.length < 2) + throw new TypeError( + `2 arguments required, but only ${arguments.length} present.` + ) + + return value instanceof Blob + // normalize name and filename if adding an attachment + ? [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 no attachment, just cast the args to strings + : [name + '', value + ''] + } + + function each (arr, cb) { + for (let i = 0; i < arr.length; i++) { + cb(arr[i]) + } + } + + /** + * @implements {Iterable} + */ + class FormDataPolyfill { + + /** + * FormData class + * + * @param {HTMLElement=} form + */ + constructor(form) { + map.set(this, Object.create(null)) + + if (!form) + return this + + const self = this + + each(form.elements, elm => { + if (!elm.name || elm.disabled || elm.type === 'submit' || elm.type === 'button') return + + if (elm.type === 'file') { + each(elm.files || [], file => { + self.append(elm.name, file) + }) + } else if (elm.type === 'select-multiple' || elm.type === 'select-one') { + each(elm.options, opt => { + !opt.disabled && opt.selected && self.append(elm.name, opt.value) + }) + } else if (elm.type === 'checkbox' || elm.type === 'radio') { + if (elm.checked) self.append(elm.name, elm.value) + } else { + self.append(elm.name, elm.value) + } + }) + } + + + /** + * Append a field + * + * @param {String} name field name + * @param {String|Blob|File} value string / blob / file + * @param {String=} filename filename to use with blob + * @return {Undefined} + */ + append(name, value, filename) { + const map = wm(this) + + if (!map[name]) + map[name] = [] + + map[name].push([value, filename]) + } + + + /** + * Delete all fields values given name + * + * @param {String} name Field name + * @return {Undefined} + */ + delete(name) { + delete wm(this)[name] + } + + + /** + * Iterate over all fields as [name, value] + * + * @return {Iterator} + */ + *entries() { + const map = wm(this) + + for (let name in map) + for (let value of map[name]) + yield [name, normalizeValue(value)] + } + + /** + * Iterate over all fields + * + * @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) { + for (let [name, value] of this) + callback.call(thisArg, value, name, this) + } + + + /** + * Return first field value given name + * or null if non existen + * + * @param {String} name Field name + * @return {String|File|null} value Fields value + */ + get(name) { + const map = wm(this) + return map[name] ? normalizeValue(map[name][0]) : null + } + + + /** + * Return all fields values given name + * + * @param {String} name Fields name + * @return {Array} [{String|File}] + */ + getAll(name) { + return (wm(this)[name] || []).map(normalizeValue) + } + + + /** + * Check for field name existence + * + * @param {String} name Field name + * @return {boolean} + */ + has(name) { + return name in wm(this) + } + + + /** + * Iterate over all fields name + * + * @return {Iterator} + */ + *keys() { + for (let [name] of this) + yield name + } + + + /** + * Overwrite all values given name + * + * @param {String} name Filed name + * @param {String} value Field value + * @param {String=} filename Filename (optional) + * @return {Undefined} + */ + set(name, value, filename) { + wm(this)[name] = [[value, filename]] + } + + + /** + * Iterate over all fields + * + * @return {Iterator} + */ + *values() { + for (let [name, value] of this) + yield value + } + + + /** + * Return a native (perhaps degraded) FormData with only a `append` method + * Can throw if it's not supported + * + * @return {FormData} + */ + ['_asNative']() { + const fd = new _FormData + + for (let [name, value] of this) + fd.append(name, value) + + return fd + } + + + /** + * [_blob description] + * + * @return {Blob} [description] + */ + ['_blob']() { + const boundary = '----formdata-polyfill-' + Math.random() + const chunks = [] + + for (let [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}) + } + + + /** + * The class itself is iterable + * alias for formdata.entries() + * + * @return {Iterator} + */ + [Symbol.iterator]() { + return this.entries() + } + + + /** + * Create the default string description. + * + * @return {String} [object FormData] + */ + toString() { + return '[object FormData]' + } + } + + + if (stringTag) { + /** + * Create the default string description. + * It is accessed internally by the Object.prototype.toString(). + * + * @return {String} FormData + */ + FormDataPolyfill.prototype[stringTag] = 'FormData' + } + + const decorations = [ + ['append', normalizeArgs], + ['delete', stringify], + ['get', stringify], + ['getAll', stringify], + ['has', stringify], + ['set', normalizeArgs] + ] + + decorations.forEach(arr => { + const orig = FormDataPolyfill.prototype[arr[0]] + FormDataPolyfill.prototype[arr[0]] = function() { + return orig.apply(this, arr[1].apply(this, arrayFrom(arguments))) + } + }) + + // Patch xhr's send method to call _blob transparently + if (_send) { + XMLHttpRequest.prototype.send = function(data) { + // I would check if Content-Type isn't already set + // But xhr lacks getRequestHeaders functionallity + // https://github.com/jimmywarting/FormData/issues/44 + if (data instanceof FormDataPolyfill) { + const blob = data['_blob']() + this.setRequestHeader('Content-Type', blob.type) + _send.call(this, blob) + } else { + _send.call(this, data) + } + } + } + + // Patch fetch's function to call _blob transparently + if (_fetch) { + const _fetch = global.fetch + + global.fetch = function(input, init) { + if (init && init.body && init.body instanceof FormDataPolyfill) { + init.body = init.body['_blob']() + } + + return _fetch(input, init) + } + } + + global['FormData'] = FormDataPolyfill +}