Skip to content

Commit

Permalink
Merge pull request #1264 from zloirock/float16
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Jul 22, 2023
2 parents 5fae871 + 310a81f commit 01f2059
Show file tree
Hide file tree
Showing 25 changed files with 282 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -25,6 +25,12 @@
- Moved back into [the initial proposal](https://github.com/tc39/proposal-explicit-resource-management) -> moved to stage 3, [proposal-explicit-resource-management/154](https://github.com/tc39/proposal-explicit-resource-management/pull/154)
- Added `/actual/` namespace entries, disabled forced replacement
- Ignore return value of `[@@dispose]()` method when hint is `async-dispose`, [proposal-explicit-resource-management/180](https://github.com/tc39/proposal-explicit-resource-management/pull/180)
- Added some methods from [`Float16Array` stage 3 proposal](https://github.com/tc39/proposal-float16array):
- There are some reason why I don't want to add `Float16Array` right now, however, make sense to add some methods from this proposal.
- Methods:
- `Math.f16round`
- `DataView.prototype.getFloat16`
- `DataView.prototype.setFloat16`
- Added [`DataView` get / set `Uint8Clamped` methods stage 1 proposal](https://github.com/tc39/proposal-dataview-get-set-uint8clamped):
- Methods:
- `DataView.prototype.getUint8Clamped`
Expand Down
36 changes: 36 additions & 0 deletions README.md
Expand Up @@ -158,6 +158,7 @@ structuredClone(new Set([1, 2, 3])); // => new Set([1, 2, 3])
- [New `Set` methods](#new-set-methods)
- [`Promise.withResolvers`](#promisewithresolvers)
- [`JSON.parse` source text access](#jsonparse-source-text-access)
- [`Float16` methods](#float16-methods)
- [`ArrayBuffer.prototype.transfer` and friends](#arraybufferprototypetransfer-and-friends)
- [Explicit resource management](#explicit-resource-management)
- [`Symbol.metadata` for decorators metadata proposal](#symbolmetadata-for-decorators-metadata-proposal)
Expand Down Expand Up @@ -2359,6 +2360,35 @@ JSON.parse(String(wayTooBig), digitsToBigInt) === wayTooBig; // true
const embedded = JSON.stringify({ tooBigForNumber }, bigIntToRawJSON);
embedded === '{"tooBigForNumber":9007199254740993}'; // true
```
##### [`Float16` methods](https://github.com/tc39/proposal-float16array)[⬆](#index)
Modules [`esnext.data-view.get-uint8-clamped`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.data-view.get-uint8-clamped.js), [`esnext.data-view.set-uint8-clamped`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.data-view.set-uint8-clamped.js) and [`esnext.math.f16round`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.math.f16round.js)
```js
class DataView {
getFloat16(offset: any): number
setFloat16(offset: any, value: any): void;
}

namespace Math {
fround(number: any): number;
}
```
[*CommonJS entry points:*](#commonjs-api)
```js
core-js/proposals/float16
core-js/actual|full/dataview/get-float16
core-js/actual|full/dataview/set-float16
core-js/actual|full/math/f16round
```
[Examples](https://tinyurl.com/2zxkrwub):
```js
console.log(Math.f16round(1.337)); // => 1.3369140625

const view = new DataView(new ArrayBuffer(2));
view.setFloat16(0, 1.337);
console.log(view.getFloat16(0)); // => 1.3369140625
```
##### [`ArrayBuffer.prototype.transfer` and friends](#https://github.com/tc39/proposal-arraybuffer-transfer)[⬆](#index)
Note: **`ArrayBuffer.prototype.{ transfer, transferToFixedLength }` polyfilled only in runtime with native `structuredClone` with `ArrayBuffer` transfer support.**
Modules [`esnext.array-buffer.detached`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array-buffer.detached.js), [`esnext.array-buffer.transfer`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array-buffer.transfer.js), [`esnext.array-buffer.transfer-to-fixed-length`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array-buffer.transfer-to-fixed-length.js).
Expand Down Expand Up @@ -2920,6 +2950,12 @@ core-js/proposals/data-view-get-set-uint8-clamped
core-js/full/dataview/get-uint8-clamped
core-js/full/dataview/set-uint8-clamped
```
[Examples](https://tinyurl.com/2h4zv8sw):
```js
const view = new DataView(new ArrayBuffer(1));
view.setUint8Clamped(0, 100500);
console.log(view.getUint8Clamped(0)); // => 255
```
##### [`Number.fromString`](https://github.com/tc39/proposal-number-fromstring)[⬆](#index)
Module [`esnext.number.from-string`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.number.from-string.js)
Expand Down
6 changes: 6 additions & 0 deletions packages/core-js-compat/src/data.mjs
Expand Up @@ -1973,8 +1973,12 @@ export const data = {
},
'esnext.composite-symbol': {
},
'esnext.data-view.get-float16': {
},
'esnext.data-view.get-uint8-clamped': {
},
'esnext.data-view.set-float16': {
},
'esnext.data-view.set-uint8-clamped': {
},
'esnext.disposable-stack.constructor': {
Expand Down Expand Up @@ -2088,6 +2092,8 @@ export const data = {
},
'esnext.math.fscale': {
},
'esnext.math.f16round': {
},
// TODO: Remove from `core-js@4`
'esnext.math.iaddh': {
},
Expand Down
3 changes: 3 additions & 0 deletions packages/core-js-compat/src/modules-by-versions.mjs
Expand Up @@ -214,7 +214,10 @@ export default {
'web.url-search-params.has',
],
3.32: [
'esnext.data-view.get-float16',
'esnext.data-view.get-uint8-clamped',
'esnext.data-view.set-float16',
'esnext.data-view.set-uint8-clamped',
'esnext.math.f16round',
],
};
@@ -0,0 +1 @@
// empty
@@ -0,0 +1 @@
// empty
2 changes: 2 additions & 0 deletions packages/core-js/actual/data-view/get-float16.js
@@ -0,0 +1,2 @@
'use strict';
require('../../modules/esnext.data-view.get-float16');
2 changes: 2 additions & 0 deletions packages/core-js/actual/data-view/index.js
@@ -1,4 +1,6 @@
'use strict';
var parent = require('../../stable/data-view');
require('../../modules/esnext.data-view.get-float16');
require('../../modules/esnext.data-view.set-float16');

module.exports = parent;
2 changes: 2 additions & 0 deletions packages/core-js/actual/data-view/set-float16.js
@@ -0,0 +1,2 @@
'use strict';
require('../../modules/esnext.data-view.set-float16');
5 changes: 5 additions & 0 deletions packages/core-js/actual/math/f16round.js
@@ -0,0 +1,5 @@
'use strict';
require('../../modules/esnext.math.f16round');
var path = require('../../internals/path');

module.exports = path.Math.f16round;
1 change: 1 addition & 0 deletions packages/core-js/actual/math/index.js
@@ -1,4 +1,5 @@
'use strict';
var parent = require('../../stable/math');
require('../../modules/esnext.math.f16round');

module.exports = parent;
4 changes: 4 additions & 0 deletions packages/core-js/full/data-view/get-float16.js
@@ -0,0 +1,4 @@
'use strict';
var parent = require('../../actual/data-view/get-float16');

module.exports = parent;
4 changes: 4 additions & 0 deletions packages/core-js/full/data-view/set-float16.js
@@ -0,0 +1,4 @@
'use strict';
var parent = require('../../actual/data-view/set-float16');

module.exports = parent;
4 changes: 4 additions & 0 deletions packages/core-js/full/math/f16round.js
@@ -0,0 +1,4 @@
'use strict';
var parent = require('../../actual/math/f16round');

module.exports = parent;
16 changes: 16 additions & 0 deletions packages/core-js/modules/esnext.data-view.get-float16.js
@@ -0,0 +1,16 @@
'use strict';
var $ = require('../internals/export');
var uncurryThis = require('../internals/function-uncurry-this');
var unpackIEEE754 = require('../internals/ieee754').unpack;

// eslint-disable-next-line es/no-typed-arrays -- safe
var getUint16 = uncurryThis(DataView.prototype.getUint16);

// `DataView.prototype.getFloat16` method
// https://github.com/tc39/proposal-float16array
$({ target: 'DataView', proto: true, forced: true }, {
getFloat16: function getFloat16(byteOffset /* , littleEndian */) {
var uint16 = getUint16(this, byteOffset, arguments.length > 1 ? arguments[1] : false);
return unpackIEEE754([uint16 & 0xFF, uint16 >> 8 & 0xFF], 10);
}
});
21 changes: 21 additions & 0 deletions packages/core-js/modules/esnext.data-view.set-float16.js
@@ -0,0 +1,21 @@
'use strict';
var $ = require('../internals/export');
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 $TypeError = TypeError;
// eslint-disable-next-line es/no-typed-arrays -- safe
var setUint16 = uncurryThis(DataView.prototype.setUint16);

// `DataView.prototype.setFloat16` method
// https://github.com/tc39/proposal-float16array
$({ target: 'DataView', proto: true, forced: true }, {
setFloat16: function setFloat16(byteOffset, value /* , littleEndian */) {
if (classof(this) !== 'DataView') throw $TypeError('Incorrect receiver');
var offset = toIndex(byteOffset);
var bytes = packIEEE754(+value, 10, 2);
return setUint16(this, offset, bytes[1] << 8 | bytes[0], arguments.length > 2 ? arguments[2] : false);
}
});
16 changes: 16 additions & 0 deletions packages/core-js/modules/esnext.math.f16round.js
@@ -0,0 +1,16 @@
'use strict';
var $ = require('../internals/export');
var IEEE754 = require('../internals/ieee754');

var packIEEE754 = IEEE754.pack;
var unpackIEEE754 = IEEE754.unpack;
var $isFinite = isFinite;

// `Math.f16round` method
// https://github.com/tc39/proposal-float16array
$({ target: 'Math', stat: true }, {
f16round: function f16round(x) {
var n = +x;
return $isFinite(n) && n !== 0 ? unpackIEEE754(packIEEE754(n, 10, 2), 10) : n;
}
});
5 changes: 5 additions & 0 deletions packages/core-js/proposals/float16.js
@@ -0,0 +1,5 @@
'use strict';
// https://github.com/tc39/proposal-float16array
require('../modules/esnext.data-view.get-float16');
require('../modules/esnext.data-view.set-float16');
require('../modules/esnext.math.f16round');
1 change: 1 addition & 0 deletions packages/core-js/stage/3.js
Expand Up @@ -6,6 +6,7 @@ require('../proposals/array-from-async-stage-2');
require('../proposals/array-grouping-v2');
require('../proposals/decorator-metadata-v2');
require('../proposals/explicit-resource-management');
require('../proposals/float16');
require('../proposals/iterator-helpers-stage-3-2');
require('../proposals/json-parse-with-source');
require('../proposals/promise-with-resolvers');
Expand Down
9 changes: 9 additions & 0 deletions tests/compat/tests.js
Expand Up @@ -1532,9 +1532,15 @@ GLOBAL.tests = {
'esnext.composite-symbol': function () {
return compositeSymbol;
},
'esnext.data-view.get-float16': [ARRAY_BUFFER_SUPPORT, function () {
return DataView.prototype.getFloat16;
}],
'esnext.data-view.get-uint8-clamped': [ARRAY_BUFFER_SUPPORT, function () {
return DataView.prototype.getUint8Clamped;
}],
'esnext.data-view.set-float16': [ARRAY_BUFFER_SUPPORT, function () {
return DataView.prototype.setFloat16;
}],
'esnext.data-view.set-uint8-clamped': [ARRAY_BUFFER_SUPPORT, function () {
return DataView.prototype.setUint8Clamped;
}],
Expand Down Expand Up @@ -1682,6 +1688,9 @@ GLOBAL.tests = {
'esnext.math.fscale': function () {
return Math.fscale;
},
'esnext.math.f16round': function () {
return Math.f16round;
},
'esnext.math.rad-per-deg': function () {
return Math.RAD_PER_DEG;
},
Expand Down
4 changes: 4 additions & 0 deletions tests/entries/unit.mjs
Expand Up @@ -673,6 +673,8 @@ for (PATH of ['core-js-pure', 'core-js']) {
ok(typeof load(NS, 'async-iterator/some') == 'function');
ok(typeof load(NS, 'async-iterator/take') == 'function');
ok(typeof load(NS, 'async-iterator/to-array') == 'function');
load(NS, 'data-view/get-float16');
load(NS, 'data-view/set-float16');
ok(load(NS, 'function/metadata') === null);
ok(typeof load(NS, 'iterator') == 'function');
ok(typeof load(NS, 'iterator/drop') == 'function');
Expand All @@ -692,6 +694,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
ok(load(NS, 'json/parse')('[42]', (key, value, { source }) => typeof value == 'number' ? source + source : value)[0] === '4242');
ok(typeof load(NS, 'json/raw-json')(42) == 'object');
ok(load(NS, 'map/group-by')([], it => it) instanceof load(NS, 'map'));
ok(load(NS, 'math/f16round')(1.337) === 1.3369140625);
ok(load(NS, 'promise/with-resolvers')().promise instanceof load(NS, 'promise'));
ok(load(NS, 'object/group-by')([1, 2, 3, 4, 5], it => it % 2 === 0 ? 'even' : 'odd').odd.length === 3);
ok(load(NS, 'set/difference')(new Set([1, 2, 3]), new Set([3, 4, 5])).size === 2);
Expand Down Expand Up @@ -919,6 +922,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
load('proposals/efficient-64-bit-arithmetic');
load('proposals/error-cause');
load('proposals/explicit-resource-management');
load('proposals/float16');
load('proposals/function-demethodize');
load('proposals/function-is-callable-is-constructor');
load('proposals/function-un-this');
Expand Down
44 changes: 44 additions & 0 deletions tests/unit-global/esnext.data-view.set-float16.js
@@ -0,0 +1,44 @@
QUnit.test('DataView.prototype.{ getFloat16, setFloat16 }', assert => {
const { getFloat16, setFloat16 } = DataView.prototype;

assert.isFunction(getFloat16);
assert.arity(getFloat16, 1);
assert.name(getFloat16, 'getFloat16');

assert.isFunction(setFloat16);
assert.arity(setFloat16, 2);
assert.name(setFloat16, 'setFloat16');

assert.same(new DataView(new ArrayBuffer(8)).setFloat16(0, 0), undefined, 'void');

function toString(it) {
return it === 0 && 1 / it === -Infinity ? '-0' : it;
}

const data = [
[0b0000000000000000, 0],
[0b1000000000000000, -0],
[0b0011110000000000, 1],
[0b1011110000000000, -1],
[0b0100001001001000, 3.140625],
[0b0000001000000000, 0.000030517578125],
[0b0111101111111111, 65504],
[0b1111101111111111, -65504],
[0b0000000000000001, 2 ** -24],
[0b1000000000000001, -(2 ** -24)],
// [0b0111110000000001, NaN], <- what NaN representation should be used?
[0b0111110000000000, Infinity],
[0b1111110000000000, -Infinity],
];

const buffer = new ArrayBuffer(2);
const view = new DataView(buffer);

for (const [bin, f16] of data) for (const LE of [false, true]) {
view.setUint16(0, bin, LE);
assert.same(view.getFloat16(0, LE), f16, `DataView.prototype.setUint16 + DataView.prototype.getFloat16, LE: ${ LE }, ${ toString(bin) } -> ${ toString(f16) }`);
view.setFloat16(0, f16, LE);
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) }`);
}
});
4 changes: 2 additions & 2 deletions tests/unit-global/esnext.data-view.set-uint8-clamped.js
Expand Up @@ -74,8 +74,8 @@ QUnit.test('DataView.prototype.{ getUint8Clamped, setUint8Clamped }', assert =>

for (const [value, conversion, little] of data) {
view.setUint8Clamped(0, value);
assert.same(view.getUint8Clamped(0, value), conversion, `DataView.prototype.setUint8Clamped + DataView.prototype.getUint8Clamped, ${ toString(value) } -> ${ toString(conversion) }`);
assert.same(view.getUint8(0, value), conversion, `DataView.prototype.setUint8Clamped + DataView.prototype.getUint8, ${ toString(value) } -> ${ toString(conversion) }`);
assert.same(view.getUint8Clamped(0), conversion, `DataView.prototype.setUint8Clamped + DataView.prototype.getUint8Clamped, ${ toString(value) } -> ${ toString(conversion) }`);
assert.same(view.getUint8(0), conversion, `DataView.prototype.setUint8Clamped + DataView.prototype.getUint8, ${ toString(value) } -> ${ toString(conversion) }`);
if (DESCRIPTORS) assert.arrayEqual(array, little, `DataView.prototype.setUint8Clamped + Uint8Array ${ toString(value) } -> [${ little }]`);
}
});
44 changes: 44 additions & 0 deletions tests/unit-global/esnext.math.f16round.js
@@ -0,0 +1,44 @@
// some asserts based on https://github.com/petamoriken/float16/blob/master/test/f16round.js
import { createConversionChecker } from '../helpers/helpers';

const { MAX_VALUE, MIN_VALUE } = Number;

QUnit.test('Math.f16round', assert => {
const { f16round } = Math;
assert.isFunction(f16round);
assert.name(f16round, 'f16round');
assert.arity(f16round, 1);
assert.looksNative(f16round);
assert.nonEnumerable(Math, 'f16round');
assert.same(f16round(), NaN);
assert.same(f16round(undefined), NaN);
assert.same(f16round(NaN), NaN);
assert.same(f16round(null), 0);
assert.same(f16round(0), 0);
assert.same(f16round(-0), -0);
assert.same(f16round(MIN_VALUE), 0);
assert.same(f16round(-MIN_VALUE), -0);
assert.same(f16round(Infinity), Infinity);
assert.same(f16round(-Infinity), -Infinity);
assert.same(f16round(MAX_VALUE), Infinity);
assert.same(f16round(-MAX_VALUE), -Infinity);

const maxFloat16 = 65504;
const minFloat16 = 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(minFloat16 / 2 + 2 ** -25), minFloat16);
assert.same(f16round(-minFloat16 / 2 - 2 ** -25), -minFloat16);

assert.same(f16round(1.337), 1.3369140625);

const checker = createConversionChecker(1.1);
assert.same(f16round(checker), 1.099609375, 'object wrapper');
assert.same(checker.$valueOf, 1, 'valueOf calls');
assert.same(checker.$toString, 0, 'toString calls');
});

0 comments on commit 01f2059

Please sign in to comment.