diff options
author | Luca Casonato <lucacasonato@yahoo.com> | 2021-02-04 15:05:36 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-04 15:05:36 +0100 |
commit | 25b35be50dd59d00e126591dd24d06824e2c50cf (patch) | |
tree | 0708d2b8883be98c5c349bfad2d4225f02d8c6ab | |
parent | 79fa7e0e96ed8261360b90fedcd795ad3a405e44 (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.js | 36 | ||||
-rw-r--r-- | op_crates/fetch/internal.d.ts | 7 | ||||
-rw-r--r-- | op_crates/fetch/lib.rs | 4 | ||||
-rw-r--r-- | runtime/js/99_main.js | 6 | ||||
m--------- | test_util/wpt | 0 | ||||
-rw-r--r-- | tools/wpt/expectation.json | 3 |
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 |