1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -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

@ -141,7 +141,7 @@
/** @type {Uint8Array} */
[_byteSequence];
/**
/**
* @param {BlobPart[]} [blobParts]
* @param {BlobPropertyBag} [options]
*/
@ -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,
_byteSequence,
File,
};
})(this);

View file

@ -21,7 +21,7 @@
window.__bootstrap.streams;
const { DomIterableMixin } = window.__bootstrap.domIterable;
const { Headers } = window.__bootstrap.headers;
const { Blob, _byteSequence } = window.__bootstrap.blob;
const { Blob, _byteSequence, File } = window.__bootstrap.file;
const MAX_SIZE = 2 ** 32 - 2;
@ -226,42 +226,19 @@
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 {string | undefined} filename
* @returns {FormDataEntryValue}
*/
function parseFormDataValue(value, filename) {
if (value instanceof DomFile) {
return new DomFile([value], filename || value.name, {
if (value instanceof File) {
return new File([value], filename || value.name, {
type: value.type,
lastModified: value.lastModified,
});
} else if (value instanceof Blob) {
return new DomFile([value], filename || "blob", {
return new File([value], filename || "blob", {
type: value.type,
});
} else {
@ -408,7 +385,7 @@
*/
getBody() {
for (const [fieldName, fieldValue] of this.formData.entries()) {
if (fieldValue instanceof DomFile) {
if (fieldValue instanceof File) {
this.#writeFile(fieldName, fieldValue);
} else this.#writeField(fieldName, fieldValue);
}
@ -487,7 +464,7 @@
/**
* @param {string} field
* @param {DomFile} value
* @param {File} value
* @returns {void}
*/
#writeFile = (field, value) => {
@ -1493,7 +1470,6 @@
}
window.__bootstrap.fetch = {
File: DomFile,
FormData,
setBaseUrl,
fetch,

View file

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

View file

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

View file

@ -27,7 +27,7 @@ delete Object.prototype.__proto__;
const streams = window.__bootstrap.streams;
const fileReader = window.__bootstrap.fileReader;
const webSocket = window.__bootstrap.webSocket;
const blob = window.__bootstrap.blob;
const file = window.__bootstrap.file;
const fetch = window.__bootstrap.fetch;
const prompt = window.__bootstrap.prompt;
const denoNs = window.__bootstrap.denoNs;
@ -198,7 +198,7 @@ delete Object.prototype.__proto__;
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope
const windowOrWorkerGlobalScope = {
Blob: util.nonEnumerable(blob.Blob),
Blob: util.nonEnumerable(file.Blob),
ByteLengthQueuingStrategy: util.nonEnumerable(
streams.ByteLengthQueuingStrategy,
),
@ -211,7 +211,7 @@ delete Object.prototype.__proto__;
ErrorEvent: util.nonEnumerable(ErrorEvent),
Event: util.nonEnumerable(Event),
EventTarget: util.nonEnumerable(EventTarget),
File: util.nonEnumerable(fetch.File),
File: util.nonEnumerable(file.File),
FileReader: util.nonEnumerable(fileReader.FileReader),
FormData: util.nonEnumerable(fetch.FormData),
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.any.js": true
},
"file": {
"File-constructor.any.js": true
}
}
}