4

I want to detach arbitrarily ArrayBuffer.
In d8(v8), i can detach ArrayBuffer using %ArrayBufferNeuter(array.buffer);.
But, i don't know how to do it without debugging option like above.
Is there some generic method to detach ArrayBuffer?

5
  • 3
    What do you mean by "detach"? Commented Mar 19, 2019 at 14:51
  • @Bergi That means free the current ArrayBuffer's backing_store Commented Mar 19, 2019 at 16:01
  • Ah, you mean detach the backing store from the buffer instance. No, there is no generic method to do that in the standards. You just let the buffer get garbage-collected. Commented Mar 19, 2019 at 17:19
  • @Bergi I heard somewhere that transferring ArrayBuffer from main thread to worker thread is one way to detach main thread's ArrayBuffer. Does it right? Commented Mar 20, 2019 at 10:25
  • Hm, I guess so, but that's also transferring the buffer to another thread. I don't think there's a way to detach it when you just want to dispose of it. Or what are you actually looking for? What is the problem that you need to solve? Commented Mar 20, 2019 at 10:43

4 Answers 4

2

To detach an ArrayBuffer you can use ArrayBuffer.prototype.transfer()

The transfer() method of ArrayBuffer instances creates a new ArrayBuffer with the same byte content as this buffer, then detaches this buffer.

const buffer = new ArrayBuffer(8);
console.log(buffer.detached); // false
const newBuffer = buffer.transfer();
console.log(buffer.detached); // true
console.log(newBuffer.detached); // false

Old answer / Alternative for browsers that do not support .transfer()

You can now detach an ArrayBuffer by using structuredClone with transferables argument.

An array of transferable objects in value that will be moved rather than cloned to the returned object.

// this detaches the buffer
structuredClone(arrayBuffer, { transfer: [arrayBuffer] });

function moveBuffer(arrayBuffer) {
  return structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
}

const buffer = new Uint8Array([1]).buffer;
const moved = moveBuffer(buffer);
console.log(buffer.byteLength === 0); // detached
console.log(moved.byteLength === 1);

Sign up to request clarification or add additional context in comments.

I'd name that function moveBuffer though. If its purpose was to only detach the buffer, it shouldn't return a new one.
You're right :)
1

Not yet, but there is a proposal to introduce such a method.

update: proposal withdrawn
@BlobKat Updated the answer. It appears that Domenic's proposal was withdrawn in favour of the resizeable buffers proposal which is now completed, but transfer() got spun out into a new proposal which is alive and kicking in stage 3 currently.
0
function detachBuffer(buffer) {
  try {
    postMessage('', '', [buffer]);
  } catch { }
}

You could use a MessageChannel to avoid tripping out any message event listener: new MessageChannel().port1.postMessage("", [buffer])
0

Many of the solutions here have the problem of creating a new backed ArrayBuffer. However, you can use structuredClone in an unusual way to accomplish this:

function detachBuffer(arrayBuffer) {
  structuredClone(null, { transfer: [arrayBuffer] });
}

The docs for transferable objects notes:

For both postMessage() and structuredClone(), transferred resources have to be attached to the data object, otherwise they would not be available on the receiving end, because the transferable array only indicates how certain resources should be sent, but does not actually send them (although they would always be detached).

In our case, this is exactly what we want - the resource being detached without being cloned. This is also why the .transfer() method is not helpful in this case.

Comments

Your Answer

Draft saved
Draft discarded

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.