| 1 | 'use strict'
|
|---|
| 2 | const Minipass = require('minipass')
|
|---|
| 3 | const TYPE = Symbol('type')
|
|---|
| 4 | const BUFFER = Symbol('buffer')
|
|---|
| 5 |
|
|---|
| 6 | class Blob {
|
|---|
| 7 | constructor (blobParts, options) {
|
|---|
| 8 | this[TYPE] = ''
|
|---|
| 9 |
|
|---|
| 10 | const buffers = []
|
|---|
| 11 | let size = 0
|
|---|
| 12 |
|
|---|
| 13 | if (blobParts) {
|
|---|
| 14 | const a = blobParts
|
|---|
| 15 | const length = Number(a.length)
|
|---|
| 16 | for (let i = 0; i < length; i++) {
|
|---|
| 17 | const element = a[i]
|
|---|
| 18 | const buffer = element instanceof Buffer ? element
|
|---|
| 19 | : ArrayBuffer.isView(element)
|
|---|
| 20 | ? Buffer.from(element.buffer, element.byteOffset, element.byteLength)
|
|---|
| 21 | : element instanceof ArrayBuffer ? Buffer.from(element)
|
|---|
| 22 | : element instanceof Blob ? element[BUFFER]
|
|---|
| 23 | : typeof element === 'string' ? Buffer.from(element)
|
|---|
| 24 | : Buffer.from(String(element))
|
|---|
| 25 | size += buffer.length
|
|---|
| 26 | buffers.push(buffer)
|
|---|
| 27 | }
|
|---|
| 28 | }
|
|---|
| 29 |
|
|---|
| 30 | this[BUFFER] = Buffer.concat(buffers, size)
|
|---|
| 31 |
|
|---|
| 32 | const type = options && options.type !== undefined
|
|---|
| 33 | && String(options.type).toLowerCase()
|
|---|
| 34 | if (type && !/[^\u0020-\u007E]/.test(type)) {
|
|---|
| 35 | this[TYPE] = type
|
|---|
| 36 | }
|
|---|
| 37 | }
|
|---|
| 38 |
|
|---|
| 39 | get size () {
|
|---|
| 40 | return this[BUFFER].length
|
|---|
| 41 | }
|
|---|
| 42 |
|
|---|
| 43 | get type () {
|
|---|
| 44 | return this[TYPE]
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | text () {
|
|---|
| 48 | return Promise.resolve(this[BUFFER].toString())
|
|---|
| 49 | }
|
|---|
| 50 |
|
|---|
| 51 | arrayBuffer () {
|
|---|
| 52 | const buf = this[BUFFER]
|
|---|
| 53 | const off = buf.byteOffset
|
|---|
| 54 | const len = buf.byteLength
|
|---|
| 55 | const ab = buf.buffer.slice(off, off + len)
|
|---|
| 56 | return Promise.resolve(ab)
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | stream () {
|
|---|
| 60 | return new Minipass().end(this[BUFFER])
|
|---|
| 61 | }
|
|---|
| 62 |
|
|---|
| 63 | slice (start, end, type) {
|
|---|
| 64 | const size = this.size
|
|---|
| 65 | const relativeStart = start === undefined ? 0
|
|---|
| 66 | : start < 0 ? Math.max(size + start, 0)
|
|---|
| 67 | : Math.min(start, size)
|
|---|
| 68 | const relativeEnd = end === undefined ? size
|
|---|
| 69 | : end < 0 ? Math.max(size + end, 0)
|
|---|
| 70 | : Math.min(end, size)
|
|---|
| 71 | const span = Math.max(relativeEnd - relativeStart, 0)
|
|---|
| 72 |
|
|---|
| 73 | const buffer = this[BUFFER]
|
|---|
| 74 | const slicedBuffer = buffer.slice(
|
|---|
| 75 | relativeStart,
|
|---|
| 76 | relativeStart + span
|
|---|
| 77 | )
|
|---|
| 78 | const blob = new Blob([], { type })
|
|---|
| 79 | blob[BUFFER] = slicedBuffer
|
|---|
| 80 | return blob
|
|---|
| 81 | }
|
|---|
| 82 |
|
|---|
| 83 | get [Symbol.toStringTag] () {
|
|---|
| 84 | return 'Blob'
|
|---|
| 85 | }
|
|---|
| 86 |
|
|---|
| 87 | static get BUFFER () {
|
|---|
| 88 | return BUFFER
|
|---|
| 89 | }
|
|---|
| 90 | }
|
|---|
| 91 |
|
|---|
| 92 | Object.defineProperties(Blob.prototype, {
|
|---|
| 93 | size: { enumerable: true },
|
|---|
| 94 | type: { enumerable: true },
|
|---|
| 95 | })
|
|---|
| 96 |
|
|---|
| 97 | module.exports = Blob
|
|---|