summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Casonato <lucacasonato@yahoo.com>2021-02-04 15:05:36 +0100
committerGitHub <noreply@github.com>2021-02-04 15:05:36 +0100
commit25b35be50dd59d00e126591dd24d06824e2c50cf (patch)
tree0708d2b8883be98c5c349bfad2d4225f02d8c6ab
parent79fa7e0e96ed8261360b90fedcd795ad3a405e44 (diff)
refactor: rewrite File implementation (#9334)
-rw-r--r--op_crates/fetch/21_file.js (renamed from op_crates/fetch/21_blob.js)53
-rw-r--r--op_crates/fetch/26_fetch.js36
-rw-r--r--op_crates/fetch/internal.d.ts7
-rw-r--r--op_crates/fetch/lib.rs4
-rw-r--r--runtime/js/99_main.js6
m---------test_util/wpt0
-rw-r--r--tools/wpt/expectation.json3
7 files changed, 70 insertions, 39 deletions
diff --git a/op_crates/fetch/21_blob.js b/op_crates/fetch/21_file.js
index 552441b21..d5160ece2 100644
--- a/op_crates/fetch/21_blob.js
+++ b/op_crates/fetch/21_file.js
@@ -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);
diff --git a/op_crates/fetch/26_fetch.js b/op_crates/fetch/26_fetch.js
index 47d701f3c..52ae91e83 100644
--- a/op_crates/fetch/26_fetch.js
+++ b/op_crates/fetch/26_fetch.js
@@ -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,
diff --git a/op_crates/fetch/internal.d.ts b/op_crates/fetch/internal.d.ts
index 5fb30f503..a474d499c 100644
--- a/op_crates/fetch/internal.d.ts
+++ b/op_crates/fetch/internal.d.ts
@@ -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: {
diff --git a/op_crates/fetch/lib.rs b/op_crates/fetch/lib.rs
index 23f356a96..157ce2fb2 100644
--- a/op_crates/fetch/lib.rs
+++ b/op_crates/fetch/lib.rs
@@ -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",
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index c3ca7b772..c6cc99dd2 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.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),
diff --git a/test_util/wpt b/test_util/wpt
-Subproject 4e9ee672edb2764c51904739bf8397b959b3a85
+Subproject 81837c9a0fb4a11a7bc3b062219c758b238f1b3
diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json
index 307021cd8..72416736b 100644
--- a/tools/wpt/expectation.json
+++ b/tools/wpt/expectation.json
@@ -1030,6 +1030,9 @@
],
"Blob-slice-overflow.any.js": true,
"Blob-slice.any.js": true
+ },
+ "file": {
+ "File-constructor.any.js": true
}
}
} \ No newline at end of file