Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

normative: sync CompareTypedArrayElements with main spec #102

Merged
merged 1 commit into from
Nov 23, 2022

Conversation

acutmore
Copy link
Collaborator

Fixes #100

Updates sort and toSorted on TypedArrays to match the new 262 behavior: tc39/ecma262#2723

cc: @syg

@acutmore acutmore added the spec label Nov 15, 2022
@acutmore acutmore requested review from syg and rricard November 15, 2022 11:10
@acutmore
Copy link
Collaborator Author

acutmore commented Nov 15, 2022

My understanding of the change is that even though the buffer is copied before we sort it, the previous check for isDetached would mean that if the buffer, that has already been copied, was detached by the _comparefn_ callback then a TypeError would be thrown, which is a bit of an overreaction as it doesn't matter that it was detached after it was read.

So the normative change is:

let detached = new WeakSet();
function detach(ab) {
  if (detached.has(ab)) return;
                                                                                                                                                                                                                                
  if (ArrayBuffer.transfer) {                                                                                                                                                                                                                                               
    ArrayBuffer.transfer(ab);  detached.add(ab);                                                                                                                                                                                                                                
  } else if (ArrayBuffer.detach) {                                                                                                                                                                                                                                          
    ArrayBuffer.detach(ab); detached.add(ab);                                                                                                                                                                                                                                     
  } else if (typeof detachArrayBuffer === "function") {                                                                                                                                                                                                                     
    detachArrayBuffer(ab);  detached.add(ab);                                                                                                                                                                                                                                            
  } else if (typeof transferArrayBuffer === "function") {                                                                                                                                                                                                                   
    transferArrayBuffer(ab); detached.add(ab);                                                                                                                                                                                                                                          
  } else if (typeof Worker === "function") {                                                                                                                                                                                                                                
    try { eval("%ArrayBufferDetach(ab)") } catch (e) {                                                                                                                                                                                                                      
      var w = new Worker('data:application/javascript,');                                                                                                                                                                                                                           
      w.postMessage(ab, [ab]);                                                                                                                                                                                                                                              
      w.terminate();                                                                                                                                                                                                                                                        
    }
    detached.add(ab);                                                                                                                                                                                                                                                                  
  } else {                                                                                                                                                                                                                                
    throw new TypeError("cannot detach array buffer");                                                                                                                                                                                                                      
  }                                                                                                                                                                                                                                                                         
}   

let ta = new Uint32Array([4, 3, 2, 1]);
let compare = (a, b) => {
  detach(ta.buffer);
  return a - b;
};

// before:
ta.toSorted(compare); // TypeError

// after:
ta.toSorted(compare); // Uint32Array [1, 2, 3, 4]

@acutmore
Copy link
Collaborator Author

With @rricard 's help. Have checked Chrome Nightly and latest Safari. And both already implement this behavior, which is great.

@rricard
Copy link
Member

rricard commented Nov 15, 2022

Additional bit of precision here: Safari Version 16.1 (17614.2.9.1.13, 17614)

@acutmore acutmore merged commit 17d8b54 into main Nov 23, 2022
@acutmore acutmore deleted the ac/remove-detached-buffer-check branch November 23, 2022 07:17
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CompareTypedArrayElements needs to be sync'ed with main spec
2 participants