Blame view

lib/jsdom/living/file-api/Blob-impl.js 2.41 KB
858f2bdf5   Boyan Georgiev   fixes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  "use strict";
  const Blob = require("../generated/Blob");
  const { isArrayBuffer } = require("../generated/utils");
  
  function convertLineEndingsToNative(s) {
    // jsdom always pretends to be *nix, for consistency.
    // See also https://github.com/jsdom/jsdom/issues/2396.
    return s.replace(/\r
  |\r|
  /g, "
  ");
  }
  
  exports.implementation = class BlobImpl {
    constructor(globalObject, args) {
      const parts = args[0];
      const properties = args[1];
  
      const buffers = [];
  
      if (parts !== undefined) {
        for (const part of parts) {
          let buffer;
          if (isArrayBuffer(part)) {
            buffer = Buffer.from(part);
          } else if (ArrayBuffer.isView(part)) {
            buffer = Buffer.from(part.buffer, part.byteOffset, part.byteLength);
          } else if (Blob.isImpl(part)) {
            buffer = part._buffer;
          } else {
            let s = part;
            if (properties.endings === "native") {
              s = convertLineEndingsToNative(part);
            }
            buffer = Buffer.from(s);
          }
          buffers.push(buffer);
        }
      }
  
      this._buffer = Buffer.concat(buffers);
      this._globalObject = globalObject;
  
      this.type = properties.type;
      if (/[^\u0020-\u007E]/.test(this.type)) {
        this.type = "";
      } else {
        this.type = this.type.toLowerCase();
      }
    }
  
    get size() {
      return this._buffer.length;
    }
  
    slice(start, end, contentType) {
      const { size } = this;
  
      let relativeStart;
      let relativeEnd;
      let relativeContentType;
  
      if (start === undefined) {
        relativeStart = 0;
      } else if (start < 0) {
        relativeStart = Math.max(size + start, 0);
      } else {
        relativeStart = Math.min(start, size);
      }
      if (end === undefined) {
        relativeEnd = size;
      } else if (end < 0) {
        relativeEnd = Math.max(size + end, 0);
      } else {
        relativeEnd = Math.min(end, size);
      }
  
      if (contentType === undefined) {
        relativeContentType = "";
      } else {
        // sanitization (lower case and invalid char check) is done in the
        // constructor
        relativeContentType = contentType;
      }
  
      const span = Math.max(relativeEnd - relativeStart, 0);
  
      const buffer = this._buffer;
      const slicedBuffer = buffer.slice(
        relativeStart,
        relativeStart + span
      );
  
      const blob = Blob.createImpl(this._globalObject, [[], { type: relativeContentType }], {});
      blob._buffer = slicedBuffer;
      return blob;
    }
  };