1

I am trying to create Blob from ArrayBuffer using .slice(), because I need to copy ArrayBuffer since I know that it will be changed in future (its byteLength will be 0) by code which I don't have control/want to change.

new Blob([data2.payload.slice()], {type: "video/MP2T"})

And I get error

Cannot perform ArrayBuffer.prototype.slice on a detached ArrayBuffer

on

Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36

on Windows 7 x64.

Is there any other ways to copy ArrayBuffer? This way not does actual copy, other ways does not seems to be pretty straightforward.

ArrayBuffer.transfer() looks good, but theirs polyfill produce error

Source and destination must be ArrayBuffer instances
galeksandrp
  • 766
  • 8
  • 17

2 Answers2

2

It's my fault, I has been confused by unclear error message, in this situation nothing can be done since at the moment of Blob creating data2.payload is already have byteLength: 0.

While in usual case with

var from = new ArrayBuffer(0);
var to = from.slice();
var to = from.slice(0);

to will be ArrayBuffer with byteLength: 0, in this case it's trigger error, because before data2.payload passed to my code it is modified in web worker, in order to avoid copying the fragment between main thread and web worker, data2.payload ownership is transferred to the worker.

galeksandrp
  • 766
  • 8
  • 17
0

Try using new Blob([new Uint8Array(data2.payload.slice(0))], {type: "video/MP2T"})

See it in this fiddle

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://fiddle.jshell.net/img/logo.png", true);
xhr.responseType = "arraybuffer";
xhr.onload = function(e) {
  var binaryArray = new Uint8Array(this.response.slice(0)); // use UInt8Array for binary
  var blob = new Blob([binaryArray], { type: "image/png" });
  var URL = window.URL || window.webkitURL;
  var imageUrl = URL.createObjectURL(blob); // create url
  document.getElementById("image").src = imageUrl;
};
xhr.send();
Sen Jacob
  • 3,384
  • 3
  • 35
  • 61
  • Tried, same result. – galeksandrp Dec 11 '16 at 02:44
  • Try using UInt8Array to create Blob. That worked for me before. – Sen Jacob Dec 11 '16 at 02:46
  • Tried, it does not copy `ArrayBuffer` now. – galeksandrp Dec 11 '16 at 02:57
  • 2
    Naaa, ["*6. Let relativeStart be ToInteger(start).*"](http://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer.prototype.slice) and in [ToInteger(argument)](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger) "*1. Let number be ToNumber(argument). [...] 3. If number is NaN, return +0.*" and `Number(undefined)` returns `NaN`, thus `+0` in `ToInteger`, and `Number(null)` returns `0`, so you can also omit the `begin` parameter of `slice(begin [, end])`, it will just default to `0`. – Kaiido Dec 11 '16 at 03:36
  • Yeah, I thought it should default to zero. But I could think of just those two reasons only, which have the slightest chances to go wrong. Nice citation.. – Sen Jacob Dec 11 '16 at 03:40