1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 23:34:47 -05:00

refactor: rewrite File implementation (#9334)

This commit is contained in:
Luca Casonato 2021-02-04 15:05:36 +01:00 committed by GitHub
parent 79fa7e0e96
commit 25b35be50d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 40 deletions

View file

@ -287,8 +287,57 @@
} }
} }
window.__bootstrap.blob = { const _Name = Symbol("[[Name]]");
const _LastModfied = Symbol("[[LastModified]]");
class File extends Blob {
/** @type {string} */
[_Name];
/** @type {number} */
[_LastModfied];
/**
* @param {BlobPart[]} fileBits
* @param {string} fileName
* @param {FilePropertyBag} [options]
*/
constructor(fileBits, fileName, options) {
if (fileBits === undefined) {
throw new TypeError(
"Failed to construct 'File'. 2 arguments required, but first not specified.",
);
}
if (fileName === undefined) {
throw new TypeError(
"Failed to construct 'File'. 2 arguments required, but second not specified.",
);
}
super(fileBits, { endings: options?.endings, type: options?.type });
/** @type {string} */
this[_Name] = String(fileName).replaceAll("/", ":");
if (options?.lastModified === undefined) {
/** @type {number} */
this[_LastModfied] = new Date().getTime();
} else {
/** @type {number} */
this[_LastModfied] = Number(options.lastModified);
}
}
/** @returns {string} */
get name() {
return this[_Name];
}
/** @returns {number} */
get lastModified() {
return this[_LastModfied];
}
}
window.__bootstrap.file = {
Blob, Blob,
_byteSequence, _byteSequence,
File,
}; };
})(this); })(this);

View file

@ -21,7 +21,7 @@
window.__bootstrap.streams; window.__bootstrap.streams;
const { DomIterableMixin } = window.__bootstrap.domIterable; const { DomIterableMixin } = window.__bootstrap.domIterable;
const { Headers } = window.__bootstrap.headers; const { Headers } = window.__bootstrap.headers;
const { Blob, _byteSequence } = window.__bootstrap.blob; const { Blob, _byteSequence, File } = window.__bootstrap.file;
const MAX_SIZE = 2 ** 32 - 2; const MAX_SIZE = 2 ** 32 - 2;
@ -226,42 +226,19 @@
const dataSymbol = Symbol("data"); const dataSymbol = Symbol("data");
class DomFile extends Blob {
/**
* @param {globalThis.BlobPart[]} fileBits
* @param {string} fileName
* @param {FilePropertyBag | undefined} options
*/
constructor(
fileBits,
fileName,
options,
) {
const { lastModified = Date.now(), ...blobPropertyBag } = options ?? {};
super(fileBits, blobPropertyBag);
// 4.1.2.1 Replace any "/" character (U+002F SOLIDUS)
// with a ":" (U + 003A COLON)
this.name = String(fileName).replace(/\u002F/g, "\u003A");
// 4.1.3.3 If lastModified is not provided, set lastModified to the current
// date and time represented in number of milliseconds since the Unix Epoch.
this.lastModified = lastModified;
}
}
/** /**
* @param {Blob | string} value * @param {Blob | string} value
* @param {string | undefined} filename * @param {string | undefined} filename
* @returns {FormDataEntryValue} * @returns {FormDataEntryValue}
*/ */
function parseFormDataValue(value, filename) { function parseFormDataValue(value, filename) {
if (value instanceof DomFile) { if (value instanceof File) {
return new DomFile([value], filename || value.name, { return new File([value], filename || value.name, {
type: value.type, type: value.type,
lastModified: value.lastModified, lastModified: value.lastModified,
}); });
} else if (value instanceof Blob) { } else if (value instanceof Blob) {
return new DomFile([value], filename || "blob", { return new File([value], filename || "blob", {
type: value.type, type: value.type,
}); });
} else { } else {
@ -408,7 +385,7 @@
*/ */
getBody() { getBody() {
for (const [fieldName, fieldValue] of this.formData.entries()) { for (const [fieldName, fieldValue] of this.formData.entries()) {
if (fieldValue instanceof DomFile) { if (fieldValue instanceof File) {
this.#writeFile(fieldName, fieldValue); this.#writeFile(fieldName, fieldValue);
} else this.#writeField(fieldName, fieldValue); } else this.#writeField(fieldName, fieldValue);
} }
@ -487,7 +464,7 @@
/** /**
* @param {string} field * @param {string} field
* @param {DomFile} value * @param {File} value
* @returns {void} * @returns {void}
*/ */
#writeFile = (field, value) => { #writeFile = (field, value) => {
@ -1493,7 +1470,6 @@
} }
window.__bootstrap.fetch = { window.__bootstrap.fetch = {
File: DomFile,
FormData, FormData,
setBaseUrl, setBaseUrl,
fetch, fetch,

View file

@ -19,11 +19,14 @@ declare namespace globalThis {
Headers: typeof Headers; Headers: typeof Headers;
}; };
declare var blob: { declare var file: {
Blob: typeof Blob & { Blob: typeof Blob & {
[globalThis.__bootstrap.blob._byteSequence]: Uint8Array; [globalThis.__bootstrap.file._byteSequence]: Uint8Array;
}; };
_byteSequence: unique symbol; _byteSequence: unique symbol;
File: typeof File & {
[globalThis.__bootstrap.file._byteSequence]: Uint8Array;
};
}; };
declare var streams: { declare var streams: {

View file

@ -67,8 +67,8 @@ pub fn init(isolate: &mut JsRuntime) {
include_str!("20_headers.js"), include_str!("20_headers.js"),
), ),
( (
"deno:op_crates/fetch/21_blob.js", "deno:op_crates/fetch/21_file.js",
include_str!("21_blob.js"), include_str!("21_file.js"),
), ),
( (
"deno:op_crates/fetch/26_fetch.js", "deno:op_crates/fetch/26_fetch.js",

View file

@ -27,7 +27,7 @@ delete Object.prototype.__proto__;
const streams = window.__bootstrap.streams; const streams = window.__bootstrap.streams;
const fileReader = window.__bootstrap.fileReader; const fileReader = window.__bootstrap.fileReader;
const webSocket = window.__bootstrap.webSocket; const webSocket = window.__bootstrap.webSocket;
const blob = window.__bootstrap.blob; const file = window.__bootstrap.file;
const fetch = window.__bootstrap.fetch; const fetch = window.__bootstrap.fetch;
const prompt = window.__bootstrap.prompt; const prompt = window.__bootstrap.prompt;
const denoNs = window.__bootstrap.denoNs; const denoNs = window.__bootstrap.denoNs;
@ -198,7 +198,7 @@ delete Object.prototype.__proto__;
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
const windowOrWorkerGlobalScope = { const windowOrWorkerGlobalScope = {
Blob: util.nonEnumerable(blob.Blob), Blob: util.nonEnumerable(file.Blob),
ByteLengthQueuingStrategy: util.nonEnumerable( ByteLengthQueuingStrategy: util.nonEnumerable(
streams.ByteLengthQueuingStrategy, streams.ByteLengthQueuingStrategy,
), ),
@ -211,7 +211,7 @@ delete Object.prototype.__proto__;
ErrorEvent: util.nonEnumerable(ErrorEvent), ErrorEvent: util.nonEnumerable(ErrorEvent),
Event: util.nonEnumerable(Event), Event: util.nonEnumerable(Event),
EventTarget: util.nonEnumerable(EventTarget), EventTarget: util.nonEnumerable(EventTarget),
File: util.nonEnumerable(fetch.File), File: util.nonEnumerable(file.File),
FileReader: util.nonEnumerable(fileReader.FileReader), FileReader: util.nonEnumerable(fileReader.FileReader),
FormData: util.nonEnumerable(fetch.FormData), FormData: util.nonEnumerable(fetch.FormData),
Headers: util.nonEnumerable(headers.Headers), Headers: util.nonEnumerable(headers.Headers),

@ -1 +1 @@
Subproject commit 4e9ee672edb2764c51904739bf8397b959b3a85c Subproject commit 81837c9a0fb4a11a7bc3b062219c758b238f1b39

View file

@ -1030,6 +1030,9 @@
], ],
"Blob-slice-overflow.any.js": true, "Blob-slice-overflow.any.js": true,
"Blob-slice.any.js": true "Blob-slice.any.js": true
},
"file": {
"File-constructor.any.js": true
} }
} }
} }