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:
parent
79fa7e0e96
commit
25b35be50d
7 changed files with 71 additions and 40 deletions
|
@ -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);
|
|
@ -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,
|
||||||
|
|
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;
|
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: {
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue