diff --git a/CHANGELOG.md b/CHANGELOG.md index 66e0169d7a55..3db955c68ff2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ##### Unreleased - Added [`ArrayBuffer.prototype.{ transfer, transferToFixedLength }`](https://github.com/tc39/proposal-arraybuffer-transfer) and support transferring of `ArrayBuffer`s via [`structuredClone`](https://html.spec.whatwg.org/multipage/structured-data.html#dom-structuredclone) to engines with `MessageChannel` - Optimized [`Math.f16round`](https://github.com/tc39/proposal-float16array) polyfill -- Fixed [some conversion cases](https://github.com/petamoriken/float16/issues/1046) of `Math.f16round` +- Fixed [some conversion cases](https://github.com/petamoriken/float16/issues/1046) of [`Math.f16round` and `DataView.prototype.{ getFloat16, setFloat16 }`](https://github.com/tc39/proposal-float16array) - Fully forced polyfilling of [the TC39 `Observable` proposal](https://github.com/tc39/proposal-observable) because of incompatibility with [the new WHATWG `Observable` proposal](https://github.com/WICG/observable) - Added an extra workaround of errors with exotic environment objects in `Symbol` polyfill, [#1289](https://github.com/zloirock/core-js/issues/1289) - Compat data improvements: diff --git a/packages/core-js/internals/array-buffer.js b/packages/core-js/internals/array-buffer.js index 0671919c9acb..366420b21353 100644 --- a/packages/core-js/internals/array-buffer.js +++ b/packages/core-js/internals/array-buffer.js @@ -12,6 +12,7 @@ var anInstance = require('../internals/an-instance'); var toIntegerOrInfinity = require('../internals/to-integer-or-infinity'); var toLength = require('../internals/to-length'); var toIndex = require('../internals/to-index'); +var fround = require('../internals/math-fround'); var IEEE754 = require('../internals/ieee754'); var getPrototypeOf = require('../internals/object-get-prototype-of'); var setPrototypeOf = require('../internals/object-set-prototype-of'); @@ -62,7 +63,7 @@ var unpackInt32 = function (buffer) { }; var packFloat32 = function (number) { - return packIEEE754(number, 23, 4); + return packIEEE754(fround(number), 23, 4); }; var packFloat64 = function (number) { diff --git a/packages/core-js/internals/ieee754.js b/packages/core-js/internals/ieee754.js index 057c4bd91bf9..36775b084f4f 100644 --- a/packages/core-js/internals/ieee754.js +++ b/packages/core-js/internals/ieee754.js @@ -1,8 +1,5 @@ 'use strict'; // IEEE754 conversions based on https://github.com/feross/ieee754 -var sign = require('../internals/math-sign'); -var trunc = require('../internals/math-trunc'); - var $Array = Array; var abs = Math.abs; var pow = Math.pow; @@ -10,21 +7,13 @@ var floor = Math.floor; var log = Math.log; var LN2 = Math.LN2; -var roundToEven = function (number) { - var truncated = trunc(number); - var delta = abs(number - truncated); - if (delta > 0.5 || delta === 0.5 && truncated % 2 !== 0) { - return truncated + sign(number); - } return truncated; -}; - var pack = function (number, mantissaLength, bytes) { var buffer = $Array(bytes); var exponentLength = bytes * 8 - mantissaLength - 1; var eMax = (1 << exponentLength) - 1; var eBias = eMax >> 1; var rt = mantissaLength === 23 ? pow(2, -24) - pow(2, -77) : 0; - var s = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0; + var sign = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0; var index = 0; var exponent, mantissa, c; number = abs(number); @@ -53,10 +42,10 @@ var pack = function (number, mantissaLength, bytes) { mantissa = 0; exponent = eMax; } else if (exponent + eBias >= 1) { - mantissa = roundToEven((number * c - 1) * pow(2, mantissaLength)); + mantissa = (number * c - 1) * pow(2, mantissaLength); exponent += eBias; } else { - mantissa = roundToEven(number * pow(2, eBias - 1) * pow(2, mantissaLength)); + mantissa = number * pow(2, eBias - 1) * pow(2, mantissaLength); exponent = 0; } } @@ -72,7 +61,7 @@ var pack = function (number, mantissaLength, bytes) { exponent /= 256; exponentLength -= 8; } - buffer[--index] |= s * 128; + buffer[--index] |= sign * 128; return buffer; }; @@ -83,10 +72,10 @@ var unpack = function (buffer, mantissaLength) { var eBias = eMax >> 1; var nBits = exponentLength - 7; var index = bytes - 1; - var s = buffer[index--]; - var exponent = s & 127; + var sign = buffer[index--]; + var exponent = sign & 127; var mantissa; - s >>= 7; + sign >>= 7; while (nBits > 0) { exponent = exponent * 256 + buffer[index--]; nBits -= 8; @@ -101,11 +90,11 @@ var unpack = function (buffer, mantissaLength) { if (exponent === 0) { exponent = 1 - eBias; } else if (exponent === eMax) { - return mantissa ? NaN : s ? -Infinity : Infinity; + return mantissa ? NaN : sign ? -Infinity : Infinity; } else { mantissa += pow(2, mantissaLength); exponent -= eBias; - } return (s ? -1 : 1) * mantissa * pow(2, exponent - mantissaLength); + } return (sign ? -1 : 1) * mantissa * pow(2, exponent - mantissaLength); }; module.exports = { diff --git a/packages/core-js/modules/esnext.data-view.set-float16.js b/packages/core-js/modules/esnext.data-view.set-float16.js index 97d71d55ad13..03b82d240ccc 100644 --- a/packages/core-js/modules/esnext.data-view.set-float16.js +++ b/packages/core-js/modules/esnext.data-view.set-float16.js @@ -4,6 +4,7 @@ var uncurryThis = require('../internals/function-uncurry-this'); var classof = require('../internals/classof'); var toIndex = require('../internals/to-index'); var packIEEE754 = require('../internals/ieee754').pack; +var f16round = require('../internals/math-f16round'); var $TypeError = TypeError; // eslint-disable-next-line es/no-typed-arrays -- safe @@ -15,7 +16,7 @@ $({ target: 'DataView', proto: true }, { setFloat16: function setFloat16(byteOffset, value /* , littleEndian */) { if (classof(this) !== 'DataView') throw new $TypeError('Incorrect receiver'); var offset = toIndex(byteOffset); - var bytes = packIEEE754(+value, 10, 2); + var bytes = packIEEE754(f16round(value), 10, 2); return setUint16(this, offset, bytes[1] << 8 | bytes[0], arguments.length > 2 ? arguments[2] : false); } }); diff --git a/tests/unit-global/esnext.data-view.set-float16.js b/tests/unit-global/esnext.data-view.set-float16.js index 8f8506a2c5b0..55d20a124813 100644 --- a/tests/unit-global/esnext.data-view.set-float16.js +++ b/tests/unit-global/esnext.data-view.set-float16.js @@ -41,4 +41,26 @@ QUnit.test('DataView.prototype.{ getFloat16, setFloat16 }', assert => { assert.same(view.getUint16(0, LE), bin, `DataView.prototype.setFloat16 + DataView.prototype.getUint16, LE: ${ LE }, ${ toString(f16) } -> ${ toString(bin) }`); assert.same(view.getFloat16(0, LE), f16, `DataView.prototype.setFloat16 + DataView.prototype.getFloat16, LE: ${ LE }, ${ toString(f16) }`); } + + const MAX_FLOAT16 = 65504; + const MIN_FLOAT16 = 2 ** -24; + + const conversions = [ + [1.337, 1.3369140625], + [0.499994, 0.5], + [7.9999999, 8], + [MAX_FLOAT16, MAX_FLOAT16], + [-MAX_FLOAT16, -MAX_FLOAT16], + [MIN_FLOAT16, MIN_FLOAT16], + [-MIN_FLOAT16, -MIN_FLOAT16], + [MIN_FLOAT16 / 2, 0], + [-MIN_FLOAT16 / 2, -0], + [2.980232238769531911744490042422139897126953655970282852649688720703125e-8, MIN_FLOAT16], + [-2.980232238769531911744490042422139897126953655970282852649688720703125e-8, -MIN_FLOAT16], + ]; + + for (const [from, to] of conversions) for (const LE of [false, true]) { + view.setFloat16(0, from, LE); + assert.same(view.getFloat16(0, LE), to, `DataView.prototype.setFloat16 + DataView.prototype.getFloat16, LE: ${ LE }, ${ toString(from) } -> ${ toString(to) }`); + } }); diff --git a/tests/unit-global/esnext.math.f16round.js b/tests/unit-global/esnext.math.f16round.js index 230e51e085c0..cdd603bb3f15 100644 --- a/tests/unit-global/esnext.math.f16round.js +++ b/tests/unit-global/esnext.math.f16round.js @@ -23,17 +23,17 @@ QUnit.test('Math.f16round', assert => { assert.same(f16round(MAX_VALUE), Infinity); assert.same(f16round(-MAX_VALUE), -Infinity); - const maxFloat16 = 65504; - const minFloat16 = 2 ** -24; + const MAX_FLOAT16 = 65504; + const MIN_FLOAT16 = 2 ** -24; - assert.same(f16round(maxFloat16), maxFloat16); - assert.same(f16round(-maxFloat16), -maxFloat16); - assert.same(f16round(minFloat16), minFloat16); - assert.same(f16round(-minFloat16), -minFloat16); - assert.same(f16round(minFloat16 / 2), 0); - assert.same(f16round(-minFloat16 / 2), -0); - assert.same(f16round(2.980232238769531911744490042422139897126953655970282852649688720703125e-8), minFloat16); - assert.same(f16round(-2.980232238769531911744490042422139897126953655970282852649688720703125e-8), -minFloat16); + assert.same(f16round(MAX_FLOAT16), MAX_FLOAT16); + assert.same(f16round(-MAX_FLOAT16), -MAX_FLOAT16); + assert.same(f16round(MIN_FLOAT16), MIN_FLOAT16); + assert.same(f16round(-MIN_FLOAT16), -MIN_FLOAT16); + assert.same(f16round(MIN_FLOAT16 / 2), 0); + assert.same(f16round(-MIN_FLOAT16 / 2), -0); + assert.same(f16round(2.980232238769531911744490042422139897126953655970282852649688720703125e-8), MIN_FLOAT16); + assert.same(f16round(-2.980232238769531911744490042422139897126953655970282852649688720703125e-8), -MIN_FLOAT16); assert.same(f16round(1.337), 1.3369140625); assert.same(f16round(0.499994), 0.5); diff --git a/tests/unit-pure/esnext.math.f16round.js b/tests/unit-pure/esnext.math.f16round.js index f7ba20f8a73a..8c51a0f1f183 100644 --- a/tests/unit-pure/esnext.math.f16round.js +++ b/tests/unit-pure/esnext.math.f16round.js @@ -22,17 +22,17 @@ QUnit.test('Math.f16round', assert => { assert.same(f16round(MAX_VALUE), Infinity); assert.same(f16round(-MAX_VALUE), -Infinity); - const maxFloat16 = 65504; - const minFloat16 = 2 ** -24; + const MAX_FLOAT16 = 65504; + const MIN_FLOAT16 = 2 ** -24; - assert.same(f16round(maxFloat16), maxFloat16); - assert.same(f16round(-maxFloat16), -maxFloat16); - assert.same(f16round(minFloat16), minFloat16); - assert.same(f16round(-minFloat16), -minFloat16); - assert.same(f16round(minFloat16 / 2), 0); - assert.same(f16round(-minFloat16 / 2), -0); - assert.same(f16round(2.980232238769531911744490042422139897126953655970282852649688720703125e-8), minFloat16); - assert.same(f16round(-2.980232238769531911744490042422139897126953655970282852649688720703125e-8), -minFloat16); + assert.same(f16round(MAX_FLOAT16), MAX_FLOAT16); + assert.same(f16round(-MAX_FLOAT16), -MAX_FLOAT16); + assert.same(f16round(MIN_FLOAT16), MIN_FLOAT16); + assert.same(f16round(-MIN_FLOAT16), -MIN_FLOAT16); + assert.same(f16round(MIN_FLOAT16 / 2), 0); + assert.same(f16round(-MIN_FLOAT16 / 2), -0); + assert.same(f16round(2.980232238769531911744490042422139897126953655970282852649688720703125e-8), MIN_FLOAT16); + assert.same(f16round(-2.980232238769531911744490042422139897126953655970282852649688720703125e-8), -MIN_FLOAT16); assert.same(f16round(1.337), 1.3369140625); assert.same(f16round(0.499994), 0.5);