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:
parent
79fa7e0e96
commit
25b35be50d
7 changed files with 71 additions and 40 deletions
|
@ -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);
|
|
@ -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,
|
||||
|
|
7
op_crates/fetch/internal.d.ts
vendored
7
op_crates/fetch/internal.d.ts
vendored
|
@ -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: {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
|
@ -1030,6 +1030,9 @@
|
|||
],
|
||||
"Blob-slice-overflow.any.js": true,
|
||||
"Blob-slice.any.js": true
|
||||
},
|
||||
"file": {
|
||||
"File-constructor.any.js": true
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue