diff --git a/.eslintrc b/.eslintrc index ba4ff28..5ec9ea5 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,7 +13,7 @@ "DetachArrayBuffer", "GetIntrinsic", "IsDetachedBuffer", - "IsResizableArrayBuffer", + "IsFixedLengthArrayBuffer", "ToIndex", ], }], diff --git a/aos/ArrayBufferCopyAndDetach.js b/aos/ArrayBufferCopyAndDetach.js index 3cf3aeb..b9c970f 100644 --- a/aos/ArrayBufferCopyAndDetach.js +++ b/aos/ArrayBufferCopyAndDetach.js @@ -9,45 +9,49 @@ var $Uint8Array = GetIntrinsic('%Uint8Array%', true); var callBound = require('call-bind/callBound'); +var byteLength = require('array-buffer-byte-length'); var $maxByteLength = callBound('%ArrayBuffer.prototype.maxByteLength%', true); - -var copyInto = function copyAB(dest, src, start, end) { - var that = new $Uint8Array(src); +var copy = function copyAB(src, start, end) { + /* globals Uint8Array: false */ + var that = new Uint8Array(src); if (typeof end === 'undefined') { end = that.length; // eslint-disable-line no-param-reassign } - var resultArray = new $Uint8Array(dest); + var result = new ArrayBuffer(end - start); + var resultArray = new Uint8Array(result); for (var i = 0; i < resultArray.length; i++) { resultArray[i] = that[i + start]; } - return dest; + return result; }; - -var arrayBufferByteLength = require('array-buffer-byte-length'); -var arrayBufferSlice = require('arraybuffer.prototype.slice'); -var isArrayBuffer = require('is-array-buffer'); -var isSharedArrayBuffer = require('is-shared-array-buffer'); +var $abSlice = callBound('%ArrayBuffer.prototype.slice%', true) + || function slice(ab, a, b) { // in node < 0.11, slice is an own nonconfigurable property + return ab.slice ? ab.slice(a, b) : copy(ab, a, b); // node 0.8 lacks `slice` + }; var DetachArrayBuffer = require('es-abstract/2023/DetachArrayBuffer'); var IsDetachedBuffer = require('es-abstract/2023/IsDetachedBuffer'); var ToIndex = require('es-abstract/2023/ToIndex'); -var IsResizableArrayBuffer = require('./IsResizableArrayBuffer'); +var IsFixedLengthArrayBuffer = require('./IsFixedLengthArrayBuffer'); + +var isArrayBuffer = require('is-array-buffer'); +var isSharedArrayBuffer = require('is-shared-array-buffer'); module.exports = function ArrayBufferCopyAndDetach(arrayBuffer, newLength, preserveResizability) { - if (preserveResizability !== 'preserve-resizability' && preserveResizability !== 'fixed-length') { - throw new $TypeError('`preserveResizability` must be "preserve-resizability" or "fixed-length"'); + if (preserveResizability !== 'PRESERVE-RESIZABILITY' && preserveResizability !== 'FIXED-LENGTH') { + throw new $TypeError('`preserveResizability` must be ~PRESERVE-RESIZABILITY~ or ~FIXED-LENGTH~'); } if (!isArrayBuffer(arrayBuffer) || isSharedArrayBuffer(arrayBuffer)) { - throw new $TypeError('`arrayBuffer` must be an ArrayBuffer'); // step 1 + throw new $TypeError('`arrayBuffer` must be an ArrayBuffer'); // steps 1 - 2 } var abByteLength; var newByteLength; if (typeof newLength === 'undefined') { // step 3 - newByteLength = arrayBufferByteLength(arrayBuffer); // step 3.a + newByteLength = byteLength(arrayBuffer); // step 3.a abByteLength = newByteLength; } else { // step 4 newByteLength = ToIndex(newLength); // step 4.a @@ -58,10 +62,10 @@ module.exports = function ArrayBufferCopyAndDetach(arrayBuffer, newLength, prese } var newMaxByteLength; - if (preserveResizability === 'preserve-resizability' && IsResizableArrayBuffer(arrayBuffer)) { // step 6 + if (preserveResizability === 'PRESERVE-RESIZABILITY' && !IsFixedLengthArrayBuffer(arrayBuffer)) { // step 6 newMaxByteLength = $maxByteLength(arrayBuffer); // step 6.a } else { // step 7 - newMaxByteLength = 'empty'; // step 7.a + newMaxByteLength = 'EMPTY'; // step 7.a } // commented out since there's no way to set or access this key @@ -69,15 +73,20 @@ module.exports = function ArrayBufferCopyAndDetach(arrayBuffer, newLength, prese // 8. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception. // 9. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength). - var newBuffer = newMaxByteLength === 'empty' ? new $ArrayBuffer(newByteLength) : new $ArrayBuffer(newByteLength, { maxByteLength: newMaxByteLength }); + var newBuffer = newMaxByteLength === 'EMPTY' ? new $ArrayBuffer(newByteLength) : new $ArrayBuffer(newByteLength, { maxByteLength: newMaxByteLength }); + if (typeof abByteLength !== 'number') { - abByteLength = arrayBufferByteLength(arrayBuffer); + abByteLength = byteLength(arrayBuffer); } var copyLength = min(newByteLength, abByteLength); // step 10 - if (newByteLength === copyLength) { - newBuffer = arrayBufferSlice(arrayBuffer, 0, copyLength); // ?? + if (newByteLength > copyLength) { + var taNew = new $Uint8Array(newBuffer); + var taOld = new $Uint8Array(arrayBuffer); + for (var i = 0; i < copyLength; i++) { + taNew[i] = taOld[i]; + } } else { - copyInto(newBuffer, arrayBuffer, 0, copyLength); + newBuffer = $abSlice(arrayBuffer, 0, copyLength); // ? optimization for when the new buffer will not be larger than the old one } /* 11. Let fromBlock be arrayBuffer.[[ArrayBufferData]]. diff --git a/aos/IsResizableArrayBuffer.js b/aos/IsFixedLengthArrayBuffer.js similarity index 55% rename from aos/IsResizableArrayBuffer.js rename to aos/IsFixedLengthArrayBuffer.js index 5040b96..0df150e 100644 --- a/aos/IsResizableArrayBuffer.js +++ b/aos/IsFixedLengthArrayBuffer.js @@ -10,29 +10,20 @@ var $sharedArrayGrowable = callBound('%SharedArrayBuffer.prototype.growable%', t var isArrayBuffer = require('is-array-buffer'); var isSharedArrayBuffer = require('is-shared-array-buffer'); -module.exports = function IsResizableArrayBuffer(arrayBuffer) { +// https://262.ecma-international.org/15.0/#sec-isfixedlengtharraybuffer + +module.exports = function IsFixedLengthArrayBuffer(arrayBuffer) { var isAB = isArrayBuffer(arrayBuffer); var isSAB = isSharedArrayBuffer(arrayBuffer); if (!isAB && !isSAB) { throw new $TypeError('Assertion failed: `arrayBuffer` must be an ArrayBuffer or SharedArrayBuffer'); } - // 1. If arrayBuffer has an [[ArrayBufferMaxByteLength]] internal slot, return true. - - // 2. Return false. - if (isAB) { - try { - return !!$arrayBufferResizable && $arrayBufferResizable(arrayBuffer); // step 1 - } catch (e) { - return false; // step 2 - } + if (isAB && $arrayBufferResizable) { + return !$arrayBufferResizable(arrayBuffer); // step 1 } - if (isSAB) { - try { - return !!$sharedArrayGrowable && $sharedArrayGrowable(arrayBuffer); // step 1 - } catch (e) { - return false; // step 2 - } + if (isSAB && $sharedArrayGrowable) { + return !$sharedArrayGrowable(arrayBuffer); // step 1 } - return false; // step 2 + return true; // step 2 }; diff --git a/implementation.js b/implementation.js index 63334a9..148ff01 100644 --- a/implementation.js +++ b/implementation.js @@ -5,5 +5,5 @@ var ArrayBufferCopyAndDetach = require('./aos/ArrayBufferCopyAndDetach'); module.exports = function transferToFixedLength() { var newLength = arguments.length > 0 ? arguments[0] : void undefined; var O = this; // step 1 - return ArrayBufferCopyAndDetach(O, newLength, 'fixed-length'); // step 2 + return ArrayBufferCopyAndDetach(O, newLength, 'FIXED-LENGTH'); // step 2 }; diff --git a/test/tests.js b/test/tests.js index 4bb160f..21bcde0 100644 --- a/test/tests.js +++ b/test/tests.js @@ -50,7 +50,7 @@ module.exports = function runTests(transferToFixedLength, t) { st.equal(IsDetachedBuffer(nbLen), false, 'new ArrayBuffer is not detached'); st.equal(byteLength(ab2), 0, 'detached original ArrayBuffer has length 0'); - st.equal(byteLength(nbLen), 4, 'newly transferToFixedLengthred ArrayBuffer has length 4'); + st.equal(byteLength(nbLen), 4, 'newly transferred ArrayBuffer has length 4'); st.test('test262: test/built-ins/ArrayBuffer/prototype/transferToFixedLength/from-fixed-to-larger.js', function (s2t) { var source = new ArrayBuffer(4);