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
|
---|