Explorar o código

Update browser.js

Lutz Roeder %!s(int64=2) %!d(string=hai) anos
pai
achega
c680843161
Modificáronse 1 ficheiros con 116 adicións e 7 borrados
  1. 116 7
      source/browser.js

+ 116 - 7
source/browser.js

@@ -631,20 +631,35 @@ host.BrowserHost.BrowserFileContext = class {
         }
         return new Promise((resolve, reject) => {
             const reader = new FileReader();
+            const size = 1024 * 1024 * 1024;
+            let position = 0;
+            const chunks = [];
             reader.onload = (e) => {
                 if (encoding) {
                     resolve(e.target.result);
                 } else {
-                    const base = require('./base');
                     const buffer = new Uint8Array(e.target.result);
-                    const stream = new base.BinaryStream(buffer);
-                    resolve(stream);
+                    if (position === 0 && buffer.length === blob.size) {
+                        const base = require('./base');
+                        const stream = new base.BinaryStream(buffer);
+                        resolve(stream);
+                    } else {
+                        chunks.push(buffer);
+                        position += buffer.length;
+                        if (position < blob.size) {
+                            const slice = blob.slice(position, Math.min(position + size, blob.size));
+                            reader.readAsArrayBuffer(slice);
+                        } else {
+                            const stream = new host.BrowserHost.FileStream(chunks, size, 0, position);
+                            resolve(stream);
+                        }
+                    }
                 }
             };
-            reader.onerror = (e) => {
-                e = e || this.window.event;
+            reader.onerror = (event) => {
+                event = event || this._host.window.event;
                 let message = '';
-                const error = e.target.error;
+                const error = event.target.error;
                 switch (error.code) {
                     case error.NOT_FOUND_ERR:
                         message = "File not found '" + file + "'.";
@@ -664,7 +679,8 @@ host.BrowserHost.BrowserFileContext = class {
             if (encoding === 'utf-8') {
                 reader.readAsText(blob, encoding);
             } else {
-                reader.readAsArrayBuffer(blob);
+                const slice = blob.slice(position, Math.min(position + size, blob.size));
+                reader.readAsArrayBuffer(slice);
             }
         });
     }
@@ -682,6 +698,99 @@ host.BrowserHost.BrowserFileContext = class {
     }
 };
 
+host.BrowserHost.FileStream = class {
+
+    constructor(chunks, size, start, length) {
+        this._chunks = chunks;
+        this._size = size;
+        this._start = start;
+        this._length = length;
+        this._position = 0;
+    }
+
+    get position() {
+        return this._position;
+    }
+
+    get length() {
+        return this._length;
+    }
+
+    stream(length) {
+        const file = new host.BrowserHost.FileStream(this._chunks, this._size, this._position, length);
+        this.skip(length);
+        return file;
+    }
+
+    seek(position) {
+        this._position = position >= 0 ? position : this._length + position;
+    }
+
+    skip(offset) {
+        this._position += offset;
+        if (this._position > this._length) {
+            throw new Error('Expected ' + (this._position - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
+        }
+    }
+
+    peek(length) {
+        length = length !== undefined ? length : this._length - this._position;
+        if (length < 0x10000000) {
+            const position = this._fill(length);
+            this._position -= length;
+            return this._buffer.subarray(position, position + length);
+        }
+        const position = this._position;
+        this.skip(length);
+        this.seek(position);
+        const buffer = new Uint8Array(length);
+        this._read(buffer, position);
+        return buffer;
+    }
+
+    read(length) {
+        length = length !== undefined ? length : this._length - this._position;
+        if (length < 0x10000000) {
+            const position = this._fill(length);
+            return this._buffer.subarray(position, position + length);
+        }
+        const position = this._position;
+        this.skip(length);
+        const buffer = new Uint8Array(length);
+        this._read(buffer, position);
+        return buffer;
+    }
+
+    byte() {
+        const position = this._fill(1);
+        return this._buffer[position];
+    }
+
+    _fill(length) {
+        if (this._position + length > this._length) {
+            throw new Error('Expected ' + (this._position + length - this._length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
+        }
+        if (!this._buffer || this._position < this._offset || this._position + length > this._offset + this._buffer.length) {
+            this._offset = this._position;
+            this._buffer = new Uint8Array(Math.min(0x10000000, this._size, this._length - this._offset));
+            this._read(this._buffer, this._offset);
+        }
+        const position = this._position;
+        this._position += length;
+        return position - this._offset;
+    }
+
+    _read(buffer, offset) {
+        const index = Math.floor(offset / this._size);
+        offset = offset - (index * this._size);
+        const length = Math.min(this._chunks[index].length - offset, buffer.length);
+        buffer.set(this._chunks[index].subarray(offset, offset + length), 0);
+        if (length !== buffer.length) {
+            buffer.set(this._chunks[index + 1].subarray(0, buffer.length - length), length);
+        }
+    }
+};
+
 host.BrowserHost.Context = class {
 
     constructor(host, url, identifier, stream) {