From 771cd8a589c5309366c4a1f65933b97272101d56 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 24 Nov 2024 13:55:39 -1000 Subject: [PATCH 1/9] [Fix] `ES2015`+: `TestIntegrityLevel`: properly handle envs without property descriptors --- 2015/TestIntegrityLevel.js | 2 +- 2016/TestIntegrityLevel.js | 2 +- 2017/TestIntegrityLevel.js | 2 +- 2018/TestIntegrityLevel.js | 2 +- 2019/TestIntegrityLevel.js | 2 +- 2020/TestIntegrityLevel.js | 2 +- 2021/TestIntegrityLevel.js | 2 +- 2022/TestIntegrityLevel.js | 2 +- 2023/TestIntegrityLevel.js | 2 +- 2024/TestIntegrityLevel.js | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/2015/TestIntegrityLevel.js b/2015/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2015/TestIntegrityLevel.js +++ b/2015/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2016/TestIntegrityLevel.js b/2016/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2016/TestIntegrityLevel.js +++ b/2016/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2017/TestIntegrityLevel.js b/2017/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2017/TestIntegrityLevel.js +++ b/2017/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2018/TestIntegrityLevel.js b/2018/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2018/TestIntegrityLevel.js +++ b/2018/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2019/TestIntegrityLevel.js b/2019/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2019/TestIntegrityLevel.js +++ b/2019/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2020/TestIntegrityLevel.js b/2020/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2020/TestIntegrityLevel.js +++ b/2020/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2021/TestIntegrityLevel.js b/2021/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2021/TestIntegrityLevel.js +++ b/2021/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2022/TestIntegrityLevel.js b/2022/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2022/TestIntegrityLevel.js +++ b/2022/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2023/TestIntegrityLevel.js b/2023/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2023/TestIntegrityLevel.js +++ b/2023/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); diff --git a/2024/TestIntegrityLevel.js b/2024/TestIntegrityLevel.js index 77f8e9a9..6df11a23 100644 --- a/2024/TestIntegrityLevel.js +++ b/2024/TestIntegrityLevel.js @@ -21,7 +21,7 @@ module.exports = function TestIntegrityLevel(O, level) { throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); } var status = IsExtensible(O); - if (status) { + if (status || !$gOPD) { return false; } var theKeys = OwnPropertyKeys(O); From 2550ec336363e5f7ba72b15962237f14f8667a0c Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 24 Nov 2024 22:40:03 -1000 Subject: [PATCH 2/9] [Tests] bigint tests are ES2020+ only --- test/tests.js | 72 ++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/test/tests.js b/test/tests.js index 75697b6e..ff85d88b 100644 --- a/test/tests.js +++ b/test/tests.js @@ -6879,44 +6879,6 @@ var es2018 = function ES2018(ES, ops, expectedMissing, skips) { })); var test = makeTest(ES, skips); - test('Abstract Relational Comparison', function (t) { - forEach(v.bigints, function (bigint) { - t.equal( - ES['Abstract Relational Comparison'](bigint, bigint + BigInt(1), false), - true, - debug(bigint) + ' is less than the same + 1n' - ); - t.equal( - ES['Abstract Relational Comparison'](bigint, bigint - BigInt(1), false), - false, - debug(bigint) + ' is not less than the same - 1n' - ); - - t.equal( - ES['Abstract Relational Comparison'](bigint, -Infinity, false), - false, - debug(bigint) + ' is not less than -∞' - ); - t.equal( - ES['Abstract Relational Comparison'](-Infinity, bigint, false), - true, - '-∞ is less than ' + debug(bigint) - ); - t.equal( - ES['Abstract Relational Comparison'](bigint, Infinity, false), - true, - debug(bigint) + ' is less than ∞' - ); - t.equal( - ES['Abstract Relational Comparison'](Infinity, bigint, false), - false, - '∞ is not less than ' + debug(bigint) - ); - }); - - t.end(); - }); - test('CopyDataProperties', function (t) { t.test('first argument: target', function (st) { forEach(v.primitives, function (primitive) { @@ -8087,6 +8049,40 @@ var es2020 = function ES2020(ES, ops, expectedMissing, skips) { }); test('Abstract Relational Comparison', { skip: !hasBigInts }, function (t) { + forEach(v.bigints, function (bigint) { + t.equal( + ES['Abstract Relational Comparison'](bigint, bigint + BigInt(1), false), + true, + debug(bigint) + ' is less than the same + 1n' + ); + t.equal( + ES['Abstract Relational Comparison'](bigint, bigint - BigInt(1), false), + false, + debug(bigint) + ' is not less than the same - 1n' + ); + + t.equal( + ES['Abstract Relational Comparison'](bigint, -Infinity, false), + false, + debug(bigint) + ' is not less than -∞' + ); + t.equal( + ES['Abstract Relational Comparison'](-Infinity, bigint, false), + true, + '-∞ is less than ' + debug(bigint) + ); + t.equal( + ES['Abstract Relational Comparison'](bigint, Infinity, false), + true, + debug(bigint) + ' is less than ∞' + ); + t.equal( + ES['Abstract Relational Comparison'](Infinity, bigint, false), + false, + '∞ is not less than ' + debug(bigint) + ); + }); + t.equal(ES['Abstract Relational Comparison']($BigInt(0), '1', true), true, 'LeftFirst: 0n is less than "1"'); t.equal(ES['Abstract Relational Comparison']('1', $BigInt(0), true), false, 'LeftFirst: "1" is not less than 0n'); t.equal(ES['Abstract Relational Comparison']($BigInt(0), '1', false), true, '!LeftFirst: 0n is less than "1"'); From 423b48b8e2954494617bc9087347af124dbe260c Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 24 Nov 2024 14:13:42 -1000 Subject: [PATCH 3/9] [Refactor] use `+` over `Number()` It is equally clear, more concise, and robust --- .eslintrc | 5 +++++ 2015/TimeClip.js | 3 +-- 2015/ToNumber.js | 2 +- 2016/TimeClip.js | 3 +-- 2016/ToNumber.js | 2 +- 2017/TimeClip.js | 3 +-- 2017/ToNumber.js | 2 +- 2018/TimeClip.js | 3 +-- 2018/ToNumber.js | 2 +- 2019/TimeClip.js | 3 +-- 2019/ToNumber.js | 2 +- 2020/TimeClip.js | 3 +-- 2020/ToNumber.js | 2 +- 2021/TimeClip.js | 3 +-- 2021/ToNumber.js | 2 +- 2022/StringToNumber.js | 7 +++---- 2022/TimeClip.js | 3 +-- 2022/ToNumber.js | 2 +- 2023/ParseHexOctet.js | 5 +---- 2023/StringToNumber.js | 7 +++---- 2023/TimeClip.js | 3 +-- 2023/ToNumber.js | 2 +- 2024/ParseHexOctet.js | 5 +---- 2024/StringToNumber.js | 7 +++---- 2024/TimeClip.js | 3 +-- 2024/ToNumber.js | 2 +- 5/TimeClip.js | 3 +-- 5/ToNumber.js | 8 +++++--- 28 files changed, 42 insertions(+), 55 deletions(-) diff --git a/.eslintrc b/.eslintrc index 0393412f..33a70dbe 100644 --- a/.eslintrc +++ b/.eslintrc @@ -18,6 +18,11 @@ "max-statements": 1, "max-statements-per-line": [2, { "max": 2 }], "multiline-comment-style": 0, + "no-implicit-coercion": [2, { + "boolean": false, + "number": false, + "string": true, + }], "no-magic-numbers": 0, "new-cap": 0, "no-extra-parens": 1, diff --git a/2015/TimeClip.js b/2015/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2015/TimeClip.js +++ b/2015/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2015/ToNumber.js b/2015/ToNumber.js index 4cb56a61..9cd51b36 100644 --- a/2015/ToNumber.js +++ b/2015/ToNumber.js @@ -44,5 +44,5 @@ module.exports = function ToNumber(argument) { } } - return $Number(value); + return +value; }; diff --git a/2016/TimeClip.js b/2016/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2016/TimeClip.js +++ b/2016/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2016/ToNumber.js b/2016/ToNumber.js index 4cb56a61..9cd51b36 100644 --- a/2016/ToNumber.js +++ b/2016/ToNumber.js @@ -44,5 +44,5 @@ module.exports = function ToNumber(argument) { } } - return $Number(value); + return +value; }; diff --git a/2017/TimeClip.js b/2017/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2017/TimeClip.js +++ b/2017/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2017/ToNumber.js b/2017/ToNumber.js index 4cb56a61..9cd51b36 100644 --- a/2017/ToNumber.js +++ b/2017/ToNumber.js @@ -44,5 +44,5 @@ module.exports = function ToNumber(argument) { } } - return $Number(value); + return +value; }; diff --git a/2018/TimeClip.js b/2018/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2018/TimeClip.js +++ b/2018/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2018/ToNumber.js b/2018/ToNumber.js index 4cb56a61..9cd51b36 100644 --- a/2018/ToNumber.js +++ b/2018/ToNumber.js @@ -44,5 +44,5 @@ module.exports = function ToNumber(argument) { } } - return $Number(value); + return +value; }; diff --git a/2019/TimeClip.js b/2019/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2019/TimeClip.js +++ b/2019/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2019/ToNumber.js b/2019/ToNumber.js index 4cb56a61..9cd51b36 100644 --- a/2019/ToNumber.js +++ b/2019/ToNumber.js @@ -44,5 +44,5 @@ module.exports = function ToNumber(argument) { } } - return $Number(value); + return +value; }; diff --git a/2020/TimeClip.js b/2020/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2020/TimeClip.js +++ b/2020/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2020/ToNumber.js b/2020/ToNumber.js index e8beb5df..8c11ace7 100644 --- a/2020/ToNumber.js +++ b/2020/ToNumber.js @@ -47,5 +47,5 @@ module.exports = function ToNumber(argument) { } } - return $Number(value); + return +value; }; diff --git a/2021/TimeClip.js b/2021/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2021/TimeClip.js +++ b/2021/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2021/ToNumber.js b/2021/ToNumber.js index e8beb5df..8c11ace7 100644 --- a/2021/ToNumber.js +++ b/2021/ToNumber.js @@ -47,5 +47,5 @@ module.exports = function ToNumber(argument) { } } - return $Number(value); + return +value; }; diff --git a/2022/StringToNumber.js b/2022/StringToNumber.js index c542a035..d1e3a268 100644 --- a/2022/StringToNumber.js +++ b/2022/StringToNumber.js @@ -2,7 +2,6 @@ var GetIntrinsic = require('get-intrinsic'); -var $Number = GetIntrinsic('%Number%'); var $RegExp = GetIntrinsic('%RegExp%'); var $TypeError = require('es-errors/type'); var $parseInteger = GetIntrinsic('%parseInt%'); @@ -27,10 +26,10 @@ module.exports = function StringToNumber(argument) { throw new $TypeError('Assertion failed: `argument` is not a String'); } if (isBinary(argument)) { - return $Number($parseInteger($strSlice(argument, 2), 2)); + return +$parseInteger($strSlice(argument, 2), 2); } if (isOctal(argument)) { - return $Number($parseInteger($strSlice(argument, 2), 8)); + return +$parseInteger($strSlice(argument, 2), 8); } if (hasNonWS(argument) || isInvalidHexLiteral(argument)) { return NaN; @@ -39,5 +38,5 @@ module.exports = function StringToNumber(argument) { if (trimmed !== argument) { return StringToNumber(trimmed); } - return $Number(argument); + return +argument; }; diff --git a/2022/TimeClip.js b/2022/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2022/TimeClip.js +++ b/2022/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2022/ToNumber.js b/2022/ToNumber.js index 4f678666..2e7dc516 100644 --- a/2022/ToNumber.js +++ b/2022/ToNumber.js @@ -22,5 +22,5 @@ module.exports = function ToNumber(argument) { if (typeof value === 'string') { return StringToNumber(value); } - return $Number(value); + return +value; }; diff --git a/2023/ParseHexOctet.js b/2023/ParseHexOctet.js index f92e7a53..d1710648 100644 --- a/2023/ParseHexOctet.js +++ b/2023/ParseHexOctet.js @@ -1,8 +1,5 @@ 'use strict'; -var GetIntrinsic = require('get-intrinsic'); - -var $Number = GetIntrinsic('%Number%'); var $SyntaxError = require('es-errors/syntax'); var $TypeError = require('es-errors/type'); @@ -28,7 +25,7 @@ module.exports = function ParseHexOctet(string, position) { } var hexDigits = substring(string, position, position + 2); // step 3 - var n = $Number('0x' + hexDigits); + var n = +('0x' + hexDigits); if (isNaN(n)) { return [new $SyntaxError('Invalid hexadecimal characters')]; } diff --git a/2023/StringToNumber.js b/2023/StringToNumber.js index c542a035..d1e3a268 100644 --- a/2023/StringToNumber.js +++ b/2023/StringToNumber.js @@ -2,7 +2,6 @@ var GetIntrinsic = require('get-intrinsic'); -var $Number = GetIntrinsic('%Number%'); var $RegExp = GetIntrinsic('%RegExp%'); var $TypeError = require('es-errors/type'); var $parseInteger = GetIntrinsic('%parseInt%'); @@ -27,10 +26,10 @@ module.exports = function StringToNumber(argument) { throw new $TypeError('Assertion failed: `argument` is not a String'); } if (isBinary(argument)) { - return $Number($parseInteger($strSlice(argument, 2), 2)); + return +$parseInteger($strSlice(argument, 2), 2); } if (isOctal(argument)) { - return $Number($parseInteger($strSlice(argument, 2), 8)); + return +$parseInteger($strSlice(argument, 2), 8); } if (hasNonWS(argument) || isInvalidHexLiteral(argument)) { return NaN; @@ -39,5 +38,5 @@ module.exports = function StringToNumber(argument) { if (trimmed !== argument) { return StringToNumber(trimmed); } - return $Number(argument); + return +argument; }; diff --git a/2023/TimeClip.js b/2023/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2023/TimeClip.js +++ b/2023/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2023/ToNumber.js b/2023/ToNumber.js index 4f678666..2e7dc516 100644 --- a/2023/ToNumber.js +++ b/2023/ToNumber.js @@ -22,5 +22,5 @@ module.exports = function ToNumber(argument) { if (typeof value === 'string') { return StringToNumber(value); } - return $Number(value); + return +value; }; diff --git a/2024/ParseHexOctet.js b/2024/ParseHexOctet.js index f92e7a53..d1710648 100644 --- a/2024/ParseHexOctet.js +++ b/2024/ParseHexOctet.js @@ -1,8 +1,5 @@ 'use strict'; -var GetIntrinsic = require('get-intrinsic'); - -var $Number = GetIntrinsic('%Number%'); var $SyntaxError = require('es-errors/syntax'); var $TypeError = require('es-errors/type'); @@ -28,7 +25,7 @@ module.exports = function ParseHexOctet(string, position) { } var hexDigits = substring(string, position, position + 2); // step 3 - var n = $Number('0x' + hexDigits); + var n = +('0x' + hexDigits); if (isNaN(n)) { return [new $SyntaxError('Invalid hexadecimal characters')]; } diff --git a/2024/StringToNumber.js b/2024/StringToNumber.js index c542a035..d1e3a268 100644 --- a/2024/StringToNumber.js +++ b/2024/StringToNumber.js @@ -2,7 +2,6 @@ var GetIntrinsic = require('get-intrinsic'); -var $Number = GetIntrinsic('%Number%'); var $RegExp = GetIntrinsic('%RegExp%'); var $TypeError = require('es-errors/type'); var $parseInteger = GetIntrinsic('%parseInt%'); @@ -27,10 +26,10 @@ module.exports = function StringToNumber(argument) { throw new $TypeError('Assertion failed: `argument` is not a String'); } if (isBinary(argument)) { - return $Number($parseInteger($strSlice(argument, 2), 2)); + return +$parseInteger($strSlice(argument, 2), 2); } if (isOctal(argument)) { - return $Number($parseInteger($strSlice(argument, 2), 8)); + return +$parseInteger($strSlice(argument, 2), 8); } if (hasNonWS(argument) || isInvalidHexLiteral(argument)) { return NaN; @@ -39,5 +38,5 @@ module.exports = function StringToNumber(argument) { if (trimmed !== argument) { return StringToNumber(trimmed); } - return $Number(argument); + return +argument; }; diff --git a/2024/TimeClip.js b/2024/TimeClip.js index e416cab4..f2ce6252 100644 --- a/2024/TimeClip.js +++ b/2024/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/2024/ToNumber.js b/2024/ToNumber.js index 4f678666..2e7dc516 100644 --- a/2024/ToNumber.js +++ b/2024/ToNumber.js @@ -22,5 +22,5 @@ module.exports = function ToNumber(argument) { if (typeof value === 'string') { return StringToNumber(value); } - return $Number(value); + return +value; }; diff --git a/5/TimeClip.js b/5/TimeClip.js index e416cab4..f2ce6252 100644 --- a/5/TimeClip.js +++ b/5/TimeClip.js @@ -3,7 +3,6 @@ var GetIntrinsic = require('get-intrinsic'); var $Date = GetIntrinsic('%Date%'); -var $Number = GetIntrinsic('%Number%'); var $isFinite = require('../helpers/isFinite'); @@ -16,6 +15,6 @@ module.exports = function TimeClip(time) { if (!$isFinite(time) || abs(time) > 8.64e15) { return NaN; } - return $Number(new $Date(ToNumber(time))); + return +new $Date(ToNumber(time)); }; diff --git a/5/ToNumber.js b/5/ToNumber.js index 1e7507ad..b501972a 100644 --- a/5/ToNumber.js +++ b/5/ToNumber.js @@ -10,12 +10,14 @@ var safeRegexTester = require('safe-regex-test'); var isNonDecimal = safeRegexTester(/^0[ob]|^[+-]0x/); +var $Number = Number; + // http://262.ecma-international.org/5.1/#sec-9.3 module.exports = function ToNumber(value) { - var prim = ToPrimitive(value, Number); + var prim = ToPrimitive(value, $Number); if (typeof prim !== 'string') { - return +prim; // eslint-disable-line no-implicit-coercion + return $Number(prim); } var trimmed = $replace( @@ -28,5 +30,5 @@ module.exports = function ToNumber(value) { return NaN; } - return +trimmed; // eslint-disable-line no-implicit-coercion + return +trimmed; }; From a32602ce1a13a1d00e5ae81306c9cf5ac467fe60 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 25 Nov 2024 08:16:30 -1000 Subject: [PATCH 4/9] [Fix] `ES2015`+: `QuoteJSONString`: properly handle surrogates --- 2015/QuoteJSONString.js | 2 +- 2016/QuoteJSONString.js | 2 +- 2017/QuoteJSONString.js | 2 +- 2018/QuoteJSONString.js | 2 +- 2019/QuoteJSONString.js | 4 ++-- 2020/QuoteJSONString.js | 5 +++-- 2021/QuoteJSONString.js | 5 +++-- 2022/QuoteJSONString.js | 5 +++-- 2023/QuoteJSONString.js | 5 +++-- 2024/QuoteJSONString.js | 5 +++-- test/tests.js | 33 +++++++++++++++++++++++++++++++++ 11 files changed, 54 insertions(+), 16 deletions(-) diff --git a/2015/QuoteJSONString.js b/2015/QuoteJSONString.js index f837dafd..dfd9f403 100644 --- a/2015/QuoteJSONString.js +++ b/2015/QuoteJSONString.js @@ -27,7 +27,7 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach($strSplit(value), function (C) { + forEach($strSplit(value, ''), function (C) { if (C === '"' || C === '\\') { product += '\u005C' + C; } else if (C === '\u0008' || C === '\u000C' || C === '\u000A' || C === '\u000D' || C === '\u0009') { diff --git a/2016/QuoteJSONString.js b/2016/QuoteJSONString.js index f837dafd..dfd9f403 100644 --- a/2016/QuoteJSONString.js +++ b/2016/QuoteJSONString.js @@ -27,7 +27,7 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach($strSplit(value), function (C) { + forEach($strSplit(value, ''), function (C) { if (C === '"' || C === '\\') { product += '\u005C' + C; } else if (C === '\u0008' || C === '\u000C' || C === '\u000A' || C === '\u000D' || C === '\u0009') { diff --git a/2017/QuoteJSONString.js b/2017/QuoteJSONString.js index f837dafd..dfd9f403 100644 --- a/2017/QuoteJSONString.js +++ b/2017/QuoteJSONString.js @@ -27,7 +27,7 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach($strSplit(value), function (C) { + forEach($strSplit(value, ''), function (C) { if (C === '"' || C === '\\') { product += '\u005C' + C; } else if (C === '\u0008' || C === '\u000C' || C === '\u000A' || C === '\u000D' || C === '\u0009') { diff --git a/2018/QuoteJSONString.js b/2018/QuoteJSONString.js index 52d3fda1..52cb5b15 100644 --- a/2018/QuoteJSONString.js +++ b/2018/QuoteJSONString.js @@ -30,7 +30,7 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach($strSplit(value), function (C) { + forEach($strSplit(value, ''), function (C) { if (hasOwn(escapes, C)) { product += escapes[C]; } else if ($charCodeAt(C, 0) < 0x20) { diff --git a/2019/QuoteJSONString.js b/2019/QuoteJSONString.js index 5f2de0b4..44a509ea 100644 --- a/2019/QuoteJSONString.js +++ b/2019/QuoteJSONString.js @@ -33,12 +33,12 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach($strSplit(value), function (C) { + forEach($strSplit(value, ''), function (C) { if (hasOwn(escapes, C)) { product += escapes[C]; } else { var cCharCode = $charCodeAt(C, 0); - if (cCharCode < 0x20 || isLeadingSurrogate(C) || isTrailingSurrogate(C)) { + if (cCharCode < 0x20 || isLeadingSurrogate(cCharCode) || isTrailingSurrogate(cCharCode)) { product += UnicodeEscape(C); } else { product += UTF16Encoding(cCharCode); diff --git a/2020/QuoteJSONString.js b/2020/QuoteJSONString.js index 07b32acd..1025707e 100644 --- a/2020/QuoteJSONString.js +++ b/2020/QuoteJSONString.js @@ -8,6 +8,7 @@ var isLeadingSurrogate = require('../helpers/isLeadingSurrogate'); var isTrailingSurrogate = require('../helpers/isTrailingSurrogate'); var $charCodeAt = callBound('String.prototype.charCodeAt'); +var $strSplit = callBound('String.prototype.split'); var UnicodeEscape = require('./UnicodeEscape'); var UTF16DecodeString = require('./UTF16DecodeString'); @@ -33,12 +34,12 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach(UTF16DecodeString(value), function (C) { + forEach($strSplit(UTF16DecodeString(value), ''), function (C) { if (hasOwn(escapes, C)) { product += escapes[C]; } else { var cCharCode = $charCodeAt(C, 0); - if (cCharCode < 0x20 || isLeadingSurrogate(C) || isTrailingSurrogate(C)) { + if (cCharCode < 0x20 || isLeadingSurrogate(cCharCode) || isTrailingSurrogate(cCharCode)) { product += UnicodeEscape(C); } else { product += UTF16Encoding(cCharCode); diff --git a/2021/QuoteJSONString.js b/2021/QuoteJSONString.js index 4e4f4a20..ca8996b1 100644 --- a/2021/QuoteJSONString.js +++ b/2021/QuoteJSONString.js @@ -8,6 +8,7 @@ var isLeadingSurrogate = require('../helpers/isLeadingSurrogate'); var isTrailingSurrogate = require('../helpers/isTrailingSurrogate'); var $charCodeAt = callBound('String.prototype.charCodeAt'); +var $strSplit = callBound('String.prototype.split'); var StringToCodePoints = require('./StringToCodePoints'); var UnicodeEscape = require('./UnicodeEscape'); @@ -33,12 +34,12 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach(StringToCodePoints(value), function (C) { + forEach($strSplit(StringToCodePoints(value), ''), function (C) { if (hasOwn(escapes, C)) { product += escapes[C]; } else { var cCharCode = $charCodeAt(C, 0); - if (cCharCode < 0x20 || isLeadingSurrogate(C) || isTrailingSurrogate(C)) { + if (cCharCode < 0x20 || isLeadingSurrogate(cCharCode) || isTrailingSurrogate(cCharCode)) { product += UnicodeEscape(C); } else { product += UTF16EncodeCodePoint(cCharCode); diff --git a/2022/QuoteJSONString.js b/2022/QuoteJSONString.js index 4e4f4a20..ca8996b1 100644 --- a/2022/QuoteJSONString.js +++ b/2022/QuoteJSONString.js @@ -8,6 +8,7 @@ var isLeadingSurrogate = require('../helpers/isLeadingSurrogate'); var isTrailingSurrogate = require('../helpers/isTrailingSurrogate'); var $charCodeAt = callBound('String.prototype.charCodeAt'); +var $strSplit = callBound('String.prototype.split'); var StringToCodePoints = require('./StringToCodePoints'); var UnicodeEscape = require('./UnicodeEscape'); @@ -33,12 +34,12 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach(StringToCodePoints(value), function (C) { + forEach($strSplit(StringToCodePoints(value), ''), function (C) { if (hasOwn(escapes, C)) { product += escapes[C]; } else { var cCharCode = $charCodeAt(C, 0); - if (cCharCode < 0x20 || isLeadingSurrogate(C) || isTrailingSurrogate(C)) { + if (cCharCode < 0x20 || isLeadingSurrogate(cCharCode) || isTrailingSurrogate(cCharCode)) { product += UnicodeEscape(C); } else { product += UTF16EncodeCodePoint(cCharCode); diff --git a/2023/QuoteJSONString.js b/2023/QuoteJSONString.js index 4e4f4a20..ca8996b1 100644 --- a/2023/QuoteJSONString.js +++ b/2023/QuoteJSONString.js @@ -8,6 +8,7 @@ var isLeadingSurrogate = require('../helpers/isLeadingSurrogate'); var isTrailingSurrogate = require('../helpers/isTrailingSurrogate'); var $charCodeAt = callBound('String.prototype.charCodeAt'); +var $strSplit = callBound('String.prototype.split'); var StringToCodePoints = require('./StringToCodePoints'); var UnicodeEscape = require('./UnicodeEscape'); @@ -33,12 +34,12 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach(StringToCodePoints(value), function (C) { + forEach($strSplit(StringToCodePoints(value), ''), function (C) { if (hasOwn(escapes, C)) { product += escapes[C]; } else { var cCharCode = $charCodeAt(C, 0); - if (cCharCode < 0x20 || isLeadingSurrogate(C) || isTrailingSurrogate(C)) { + if (cCharCode < 0x20 || isLeadingSurrogate(cCharCode) || isTrailingSurrogate(cCharCode)) { product += UnicodeEscape(C); } else { product += UTF16EncodeCodePoint(cCharCode); diff --git a/2024/QuoteJSONString.js b/2024/QuoteJSONString.js index 4e4f4a20..ca8996b1 100644 --- a/2024/QuoteJSONString.js +++ b/2024/QuoteJSONString.js @@ -8,6 +8,7 @@ var isLeadingSurrogate = require('../helpers/isLeadingSurrogate'); var isTrailingSurrogate = require('../helpers/isTrailingSurrogate'); var $charCodeAt = callBound('String.prototype.charCodeAt'); +var $strSplit = callBound('String.prototype.split'); var StringToCodePoints = require('./StringToCodePoints'); var UnicodeEscape = require('./UnicodeEscape'); @@ -33,12 +34,12 @@ module.exports = function QuoteJSONString(value) { } var product = '"'; if (value) { - forEach(StringToCodePoints(value), function (C) { + forEach($strSplit(StringToCodePoints(value), ''), function (C) { if (hasOwn(escapes, C)) { product += escapes[C]; } else { var cCharCode = $charCodeAt(C, 0); - if (cCharCode < 0x20 || isLeadingSurrogate(C) || isTrailingSurrogate(C)) { + if (cCharCode < 0x20 || isLeadingSurrogate(cCharCode) || isTrailingSurrogate(cCharCode)) { product += UnicodeEscape(C); } else { product += UTF16EncodeCodePoint(cCharCode); diff --git a/test/tests.js b/test/tests.js index ff85d88b..04ef80b0 100644 --- a/test/tests.js +++ b/test/tests.js @@ -4251,7 +4251,11 @@ var es2015 = function ES2015(ES, ops, expectedMissing, skips) { t.equal(ES.QuoteJSONString('\r'), '"\\r"', '"\\r" gets properly JSON-quoted'); t.equal(ES.QuoteJSONString('\\'), '"\\\\"', '"\\\\" gets properly JSON-quoted'); t.equal(ES.QuoteJSONString('\\'), '"\\\\"', '"\\\\" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\u000B'), '"\\u000b"', '"\\u000B" gets properly JSON-quoted'); t.equal(ES.QuoteJSONString('\u0019'), '"\\u0019"', '"\\u0019" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString(leadingPoo), '"\ud83d"', 'leading poo gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString(trailingPoo), '"\udca9"', 'trailing poo gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString(wholePoo), '"\ud83d\udca9"', 'whole poo gets properly JSON-quoted'); t.end(); }); @@ -7760,6 +7764,7 @@ var es2018 = function ES2018(ES, ops, expectedMissing, skips) { var es2019 = function ES2019(ES, ops, expectedMissing, skips) { es2018(ES, ops, expectedMissing, assign({}, skips, { + QuoteJSONString: true })); var test = makeTest(ES, skips); @@ -7922,6 +7927,34 @@ var es2019 = function ES2019(ES, ops, expectedMissing, skips) { t.end(); }); + test('QuoteJSONString', function (t) { + forEach(v.nonStrings, function (nonString) { + t['throws']( + function () { ES.QuoteJSONString(nonString); }, + TypeError, + debug(nonString) + ' is not a String' + ); + }); + + t.equal(ES.QuoteJSONString(''), '""', '"" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('a'), '"a"', '"a" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('"'), '"\\""', '"\\"" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\b'), '"\\b"', '"\\b" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\t'), '"\\t"', '"\\t" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\n'), '"\\n"', '"\\n" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\f'), '"\\f"', '"\\f" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\r'), '"\\r"', '"\\r" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\\'), '"\\\\"', '"\\\\" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\\'), '"\\\\"', '"\\\\" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\u000B'), '"\\u000b"', '"\\u000B" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString('\u0019'), '"\\u0019"', '"\\u0019" gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString(leadingPoo), '"\\ud83d"', 'leading poo gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString(trailingPoo), '"\\udca9"', 'trailing poo gets properly JSON-quoted'); + t.equal(ES.QuoteJSONString(wholePoo), '"\\ud83d\\udca9"', 'whole poo gets properly JSON-quoted'); + + t.end(); + }); + test('TrimString', function (t) { t.test('non-object string', function (st) { forEach(v.nullPrimitives, function (nullish) { From 2b14b6778b195f9f85e2e15724fac0ed256fda43 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 24 Nov 2024 22:44:12 -1000 Subject: [PATCH 5/9] [Refactor] `ES5`+: `MonthFromTime`: throw a `RangeError` for an out of range timestamp --- 2015/MonthFromTime.js | 4 ++++ 2016/MonthFromTime.js | 4 ++++ 2017/MonthFromTime.js | 4 ++++ 2018/MonthFromTime.js | 4 ++++ 2019/MonthFromTime.js | 4 ++++ 2020/MonthFromTime.js | 4 ++++ 2021/MonthFromTime.js | 4 ++++ 2022/MonthFromTime.js | 4 ++++ 2023/MonthFromTime.js | 4 ++++ 2024/MonthFromTime.js | 4 ++++ 5/MonthFromTime.js | 4 ++++ 11 files changed, 44 insertions(+) diff --git a/2015/MonthFromTime.js b/2015/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2015/MonthFromTime.js +++ b/2015/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2016/MonthFromTime.js b/2016/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2016/MonthFromTime.js +++ b/2016/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2017/MonthFromTime.js b/2017/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2017/MonthFromTime.js +++ b/2017/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2018/MonthFromTime.js b/2018/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2018/MonthFromTime.js +++ b/2018/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2019/MonthFromTime.js b/2019/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2019/MonthFromTime.js +++ b/2019/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2020/MonthFromTime.js b/2020/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2020/MonthFromTime.js +++ b/2020/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2021/MonthFromTime.js b/2021/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2021/MonthFromTime.js +++ b/2021/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2022/MonthFromTime.js b/2022/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2022/MonthFromTime.js +++ b/2022/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2023/MonthFromTime.js b/2023/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2023/MonthFromTime.js +++ b/2023/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/2024/MonthFromTime.js b/2024/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/2024/MonthFromTime.js +++ b/2024/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; diff --git a/5/MonthFromTime.js b/5/MonthFromTime.js index a482a7df..e551ee2b 100644 --- a/5/MonthFromTime.js +++ b/5/MonthFromTime.js @@ -1,5 +1,7 @@ 'use strict'; +var $RangeError = require('es-errors/range'); + var DayWithinYear = require('./DayWithinYear'); var InLeapYear = require('./InLeapYear'); @@ -44,4 +46,6 @@ module.exports = function MonthFromTime(t) { if ((334 + leap) <= day && day < (365 + leap)) { return 11; } + + throw new $RangeError('Assertion failed: `day` is out of range'); }; From 65cf24d12fe2dfa2071160aea4c9c5ae09c1e9f5 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 25 Nov 2024 10:24:22 -1000 Subject: [PATCH 6/9] [Fix] `ES2017` - `ES2019`: `SetValueInBuffer`: handle proper number of arguments --- .gitattributes | 1 - 2017/SetValueInBuffer.js | 90 +++++------ 2017/tables/typed-array-objects.js | 2 +- 2018/SetValueInBuffer.js | 90 +++++------ 2018/tables/typed-array-objects.js | 2 +- 2019/SetValueInBuffer.js | 90 +++++------ 2020/SetValueInBuffer.js | 4 +- test/tests.js | 236 ++++++++++++++++++++++------- 8 files changed, 293 insertions(+), 222 deletions(-) diff --git a/.gitattributes b/.gitattributes index 34620f09..8fe72a22 100644 --- a/.gitattributes +++ b/.gitattributes @@ -262,7 +262,6 @@ /2017/Set.js spackled linguist-generated=true /2017/SetFunctionName.js spackled linguist-generated=true /2017/SetIntegrityLevel.js spackled linguist-generated=true -/2017/SetValueInBuffer.js spackled linguist-generated=true /2017/SpeciesConstructor.js spackled linguist-generated=true /2017/SplitMatch.js spackled linguist-generated=true /2017/StrictEqualityComparison.js spackled linguist-generated=true diff --git a/2017/SetValueInBuffer.js b/2017/SetValueInBuffer.js index c6ce306a..0a1424d7 100644 --- a/2017/SetValueInBuffer.js +++ b/2017/SetValueInBuffer.js @@ -2,47 +2,32 @@ var GetIntrinsic = require('get-intrinsic'); +var $SyntaxError = require('es-errors/syntax'); var $TypeError = require('es-errors/type'); var $Uint8Array = GetIntrinsic('%Uint8Array%', true); var isInteger = require('../helpers/isInteger'); var IsDetachedBuffer = require('./IsDetachedBuffer'); -var ToInt16 = require('./ToInt16'); -var ToInt32 = require('./ToInt32'); -var ToInt8 = require('./ToInt8'); -var ToUint16 = require('./ToUint16'); -var ToUint32 = require('./ToUint32'); -var ToUint8 = require('./ToUint8'); -var ToUint8Clamp = require('./ToUint8Clamp'); +var NumberToRawBytes = require('./NumberToRawBytes'); var isArrayBuffer = require('is-array-buffer'); +var isSharedArrayBuffer = require('is-shared-array-buffer'); var hasOwn = require('hasown'); var tableTAO = require('./tables/typed-array-objects'); -var TypeToAO = { - __proto__: null, - Int8: ToInt8, - Uint8: ToUint8, - Uint8C: ToUint8Clamp, - Int16: ToInt16, - Uint16: ToUint16, - Int32: ToInt32, - Uint32: ToUint32 -}; - var defaultEndianness = require('../helpers/defaultEndianness'); var forEach = require('../helpers/forEach'); -var integerToNBytes = require('../helpers/integerToNBytes'); -var valueToFloat32Bytes = require('../helpers/valueToFloat32Bytes'); -var valueToFloat64Bytes = require('../helpers/valueToFloat64Bytes'); -// https://262.ecma-international.org/6.0/#sec-setvalueinbuffer +// https://262.ecma-international.org/8.0/#sec-setvalueinbuffer + +/* eslint max-params: 0 */ -module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) { - if (!isArrayBuffer(arrayBuffer)) { - throw new $TypeError('Assertion failed: `arrayBuffer` must be an ArrayBuffer'); +module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value, isTypedArray, order) { + var isSAB = isSharedArrayBuffer(arrayBuffer); + if (!isArrayBuffer(arrayBuffer) && !isSAB) { + throw new $TypeError('Assertion failed: `arrayBuffer` must be an ArrayBuffer or a SharedArrayBuffer'); } if (!isInteger(byteIndex)) { @@ -57,7 +42,14 @@ module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) throw new $TypeError('Assertion failed: `value` must be a number'); } - if (arguments.length > 4 && typeof arguments[4] !== 'boolean') { + if (typeof isTypedArray !== 'boolean') { + throw new $TypeError('Assertion failed: `isTypedArray` must be a boolean'); + } + if (order !== 'SeqCst' && order !== 'Unordered' && order !== 'Init') { + throw new $TypeError('Assertion failed: `order` must be `"SeqCst"`, `"Unordered"`, or `"Init"`'); + } + + if (arguments.length > 6 && typeof arguments[6] !== 'boolean') { throw new $TypeError('Assertion failed: `isLittleEndian` must be a boolean, if present'); } @@ -73,38 +65,30 @@ module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) // 4. Assert: Type(value) is Number. - // 5. Let block be arrayBuffer’s [[ArrayBufferData]] internal slot. + // 5. Let block be arrayBuffer.[[ArrayBufferData]]. - // 6. Assert: block is not undefined. + var elementSize = tableTAO.size['$' + type]; // step 6 - var elementSize = tableTAO.size['$' + type]; // step 7 - if (!elementSize) { - throw new $TypeError('Assertion failed: `type` must be one of "Int8", "Uint8", "Uint8C", "Int16", "Uint16", "Int32", "Uint32", "Float32", or "Float64"'); - } + // 7. If isLittleEndian is not present, set isLittleEndian to to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. + var isLittleEndian = arguments.length > 6 ? arguments[6] : defaultEndianness === 'little'; // step 8 - // 8. If isLittleEndian is not present, set isLittleEndian to either true or false. The choice is implementation dependent and should be the alternative that is most efficient for the implementation. An implementation must use the same value each time this step is executed and the same value must be used for the corresponding step in the GetValueFromBuffer abstract operation. - var isLittleEndian = arguments.length > 4 ? arguments[4] : defaultEndianness === 'little'; // step 8 + var rawBytes = NumberToRawBytes(type, value, isLittleEndian); // step 8 - var rawBytes; - if (type === 'Float32') { // step 1 - rawBytes = valueToFloat32Bytes(value, isLittleEndian); - } else if (type === 'Float64') { // step 2 - rawBytes = valueToFloat64Bytes(value, isLittleEndian); + if (isSAB) { // step 9 + /* + Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record. + Let eventList be the [[EventList]] field of the element in execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier(). + If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false. + Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventList. + */ + throw new $SyntaxError('SharedArrayBuffer is not supported by this implementation'); } else { - var n = elementSize; // step 3.a - - var convOp = TypeToAO[type]; // step 3.b - - var intValue = convOp(value); // step 3.c - - rawBytes = integerToNBytes(intValue, n, isLittleEndian); // step 3.d, 3.e, 4 + // 10. Store the individual bytes of rawBytes into block, in order, starting at block[byteIndex]. + var arr = new $Uint8Array(arrayBuffer, byteIndex, elementSize); + forEach(rawBytes, function (rawByte, i) { + arr[i] = rawByte; + }); } - // 12. Store the individual bytes of rawBytes into block, in order, starting at block[byteIndex]. - var arr = new $Uint8Array(arrayBuffer, byteIndex, elementSize); - forEach(rawBytes, function (rawByte, i) { - arr[i] = rawByte; - }); - - // 13. Return NormalCompletion(undefined). + // 11. Return NormalCompletion(undefined). }; diff --git a/2017/tables/typed-array-objects.js b/2017/tables/typed-array-objects.js index dc8692a6..307a2d23 100644 --- a/2017/tables/typed-array-objects.js +++ b/2017/tables/typed-array-objects.js @@ -1,6 +1,6 @@ 'use strict'; -// https://262.ecma-international.org/8.0/#table-59 +// https://262.ecma-international.org/8.0/#table-49 module.exports = { __proto__: null, diff --git a/2018/SetValueInBuffer.js b/2018/SetValueInBuffer.js index c6ce306a..0a1424d7 100644 --- a/2018/SetValueInBuffer.js +++ b/2018/SetValueInBuffer.js @@ -2,47 +2,32 @@ var GetIntrinsic = require('get-intrinsic'); +var $SyntaxError = require('es-errors/syntax'); var $TypeError = require('es-errors/type'); var $Uint8Array = GetIntrinsic('%Uint8Array%', true); var isInteger = require('../helpers/isInteger'); var IsDetachedBuffer = require('./IsDetachedBuffer'); -var ToInt16 = require('./ToInt16'); -var ToInt32 = require('./ToInt32'); -var ToInt8 = require('./ToInt8'); -var ToUint16 = require('./ToUint16'); -var ToUint32 = require('./ToUint32'); -var ToUint8 = require('./ToUint8'); -var ToUint8Clamp = require('./ToUint8Clamp'); +var NumberToRawBytes = require('./NumberToRawBytes'); var isArrayBuffer = require('is-array-buffer'); +var isSharedArrayBuffer = require('is-shared-array-buffer'); var hasOwn = require('hasown'); var tableTAO = require('./tables/typed-array-objects'); -var TypeToAO = { - __proto__: null, - Int8: ToInt8, - Uint8: ToUint8, - Uint8C: ToUint8Clamp, - Int16: ToInt16, - Uint16: ToUint16, - Int32: ToInt32, - Uint32: ToUint32 -}; - var defaultEndianness = require('../helpers/defaultEndianness'); var forEach = require('../helpers/forEach'); -var integerToNBytes = require('../helpers/integerToNBytes'); -var valueToFloat32Bytes = require('../helpers/valueToFloat32Bytes'); -var valueToFloat64Bytes = require('../helpers/valueToFloat64Bytes'); -// https://262.ecma-international.org/6.0/#sec-setvalueinbuffer +// https://262.ecma-international.org/8.0/#sec-setvalueinbuffer + +/* eslint max-params: 0 */ -module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) { - if (!isArrayBuffer(arrayBuffer)) { - throw new $TypeError('Assertion failed: `arrayBuffer` must be an ArrayBuffer'); +module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value, isTypedArray, order) { + var isSAB = isSharedArrayBuffer(arrayBuffer); + if (!isArrayBuffer(arrayBuffer) && !isSAB) { + throw new $TypeError('Assertion failed: `arrayBuffer` must be an ArrayBuffer or a SharedArrayBuffer'); } if (!isInteger(byteIndex)) { @@ -57,7 +42,14 @@ module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) throw new $TypeError('Assertion failed: `value` must be a number'); } - if (arguments.length > 4 && typeof arguments[4] !== 'boolean') { + if (typeof isTypedArray !== 'boolean') { + throw new $TypeError('Assertion failed: `isTypedArray` must be a boolean'); + } + if (order !== 'SeqCst' && order !== 'Unordered' && order !== 'Init') { + throw new $TypeError('Assertion failed: `order` must be `"SeqCst"`, `"Unordered"`, or `"Init"`'); + } + + if (arguments.length > 6 && typeof arguments[6] !== 'boolean') { throw new $TypeError('Assertion failed: `isLittleEndian` must be a boolean, if present'); } @@ -73,38 +65,30 @@ module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) // 4. Assert: Type(value) is Number. - // 5. Let block be arrayBuffer’s [[ArrayBufferData]] internal slot. + // 5. Let block be arrayBuffer.[[ArrayBufferData]]. - // 6. Assert: block is not undefined. + var elementSize = tableTAO.size['$' + type]; // step 6 - var elementSize = tableTAO.size['$' + type]; // step 7 - if (!elementSize) { - throw new $TypeError('Assertion failed: `type` must be one of "Int8", "Uint8", "Uint8C", "Int16", "Uint16", "Int32", "Uint32", "Float32", or "Float64"'); - } + // 7. If isLittleEndian is not present, set isLittleEndian to to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. + var isLittleEndian = arguments.length > 6 ? arguments[6] : defaultEndianness === 'little'; // step 8 - // 8. If isLittleEndian is not present, set isLittleEndian to either true or false. The choice is implementation dependent and should be the alternative that is most efficient for the implementation. An implementation must use the same value each time this step is executed and the same value must be used for the corresponding step in the GetValueFromBuffer abstract operation. - var isLittleEndian = arguments.length > 4 ? arguments[4] : defaultEndianness === 'little'; // step 8 + var rawBytes = NumberToRawBytes(type, value, isLittleEndian); // step 8 - var rawBytes; - if (type === 'Float32') { // step 1 - rawBytes = valueToFloat32Bytes(value, isLittleEndian); - } else if (type === 'Float64') { // step 2 - rawBytes = valueToFloat64Bytes(value, isLittleEndian); + if (isSAB) { // step 9 + /* + Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record. + Let eventList be the [[EventList]] field of the element in execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier(). + If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false. + Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventList. + */ + throw new $SyntaxError('SharedArrayBuffer is not supported by this implementation'); } else { - var n = elementSize; // step 3.a - - var convOp = TypeToAO[type]; // step 3.b - - var intValue = convOp(value); // step 3.c - - rawBytes = integerToNBytes(intValue, n, isLittleEndian); // step 3.d, 3.e, 4 + // 10. Store the individual bytes of rawBytes into block, in order, starting at block[byteIndex]. + var arr = new $Uint8Array(arrayBuffer, byteIndex, elementSize); + forEach(rawBytes, function (rawByte, i) { + arr[i] = rawByte; + }); } - // 12. Store the individual bytes of rawBytes into block, in order, starting at block[byteIndex]. - var arr = new $Uint8Array(arrayBuffer, byteIndex, elementSize); - forEach(rawBytes, function (rawByte, i) { - arr[i] = rawByte; - }); - - // 13. Return NormalCompletion(undefined). + // 11. Return NormalCompletion(undefined). }; diff --git a/2018/tables/typed-array-objects.js b/2018/tables/typed-array-objects.js index dc8692a6..307a2d23 100644 --- a/2018/tables/typed-array-objects.js +++ b/2018/tables/typed-array-objects.js @@ -1,6 +1,6 @@ 'use strict'; -// https://262.ecma-international.org/8.0/#table-59 +// https://262.ecma-international.org/8.0/#table-49 module.exports = { __proto__: null, diff --git a/2019/SetValueInBuffer.js b/2019/SetValueInBuffer.js index c6ce306a..0a1424d7 100644 --- a/2019/SetValueInBuffer.js +++ b/2019/SetValueInBuffer.js @@ -2,47 +2,32 @@ var GetIntrinsic = require('get-intrinsic'); +var $SyntaxError = require('es-errors/syntax'); var $TypeError = require('es-errors/type'); var $Uint8Array = GetIntrinsic('%Uint8Array%', true); var isInteger = require('../helpers/isInteger'); var IsDetachedBuffer = require('./IsDetachedBuffer'); -var ToInt16 = require('./ToInt16'); -var ToInt32 = require('./ToInt32'); -var ToInt8 = require('./ToInt8'); -var ToUint16 = require('./ToUint16'); -var ToUint32 = require('./ToUint32'); -var ToUint8 = require('./ToUint8'); -var ToUint8Clamp = require('./ToUint8Clamp'); +var NumberToRawBytes = require('./NumberToRawBytes'); var isArrayBuffer = require('is-array-buffer'); +var isSharedArrayBuffer = require('is-shared-array-buffer'); var hasOwn = require('hasown'); var tableTAO = require('./tables/typed-array-objects'); -var TypeToAO = { - __proto__: null, - Int8: ToInt8, - Uint8: ToUint8, - Uint8C: ToUint8Clamp, - Int16: ToInt16, - Uint16: ToUint16, - Int32: ToInt32, - Uint32: ToUint32 -}; - var defaultEndianness = require('../helpers/defaultEndianness'); var forEach = require('../helpers/forEach'); -var integerToNBytes = require('../helpers/integerToNBytes'); -var valueToFloat32Bytes = require('../helpers/valueToFloat32Bytes'); -var valueToFloat64Bytes = require('../helpers/valueToFloat64Bytes'); -// https://262.ecma-international.org/6.0/#sec-setvalueinbuffer +// https://262.ecma-international.org/8.0/#sec-setvalueinbuffer + +/* eslint max-params: 0 */ -module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) { - if (!isArrayBuffer(arrayBuffer)) { - throw new $TypeError('Assertion failed: `arrayBuffer` must be an ArrayBuffer'); +module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value, isTypedArray, order) { + var isSAB = isSharedArrayBuffer(arrayBuffer); + if (!isArrayBuffer(arrayBuffer) && !isSAB) { + throw new $TypeError('Assertion failed: `arrayBuffer` must be an ArrayBuffer or a SharedArrayBuffer'); } if (!isInteger(byteIndex)) { @@ -57,7 +42,14 @@ module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) throw new $TypeError('Assertion failed: `value` must be a number'); } - if (arguments.length > 4 && typeof arguments[4] !== 'boolean') { + if (typeof isTypedArray !== 'boolean') { + throw new $TypeError('Assertion failed: `isTypedArray` must be a boolean'); + } + if (order !== 'SeqCst' && order !== 'Unordered' && order !== 'Init') { + throw new $TypeError('Assertion failed: `order` must be `"SeqCst"`, `"Unordered"`, or `"Init"`'); + } + + if (arguments.length > 6 && typeof arguments[6] !== 'boolean') { throw new $TypeError('Assertion failed: `isLittleEndian` must be a boolean, if present'); } @@ -73,38 +65,30 @@ module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value) // 4. Assert: Type(value) is Number. - // 5. Let block be arrayBuffer’s [[ArrayBufferData]] internal slot. + // 5. Let block be arrayBuffer.[[ArrayBufferData]]. - // 6. Assert: block is not undefined. + var elementSize = tableTAO.size['$' + type]; // step 6 - var elementSize = tableTAO.size['$' + type]; // step 7 - if (!elementSize) { - throw new $TypeError('Assertion failed: `type` must be one of "Int8", "Uint8", "Uint8C", "Int16", "Uint16", "Int32", "Uint32", "Float32", or "Float64"'); - } + // 7. If isLittleEndian is not present, set isLittleEndian to to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. + var isLittleEndian = arguments.length > 6 ? arguments[6] : defaultEndianness === 'little'; // step 8 - // 8. If isLittleEndian is not present, set isLittleEndian to either true or false. The choice is implementation dependent and should be the alternative that is most efficient for the implementation. An implementation must use the same value each time this step is executed and the same value must be used for the corresponding step in the GetValueFromBuffer abstract operation. - var isLittleEndian = arguments.length > 4 ? arguments[4] : defaultEndianness === 'little'; // step 8 + var rawBytes = NumberToRawBytes(type, value, isLittleEndian); // step 8 - var rawBytes; - if (type === 'Float32') { // step 1 - rawBytes = valueToFloat32Bytes(value, isLittleEndian); - } else if (type === 'Float64') { // step 2 - rawBytes = valueToFloat64Bytes(value, isLittleEndian); + if (isSAB) { // step 9 + /* + Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record. + Let eventList be the [[EventList]] field of the element in execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier(). + If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false. + Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventList. + */ + throw new $SyntaxError('SharedArrayBuffer is not supported by this implementation'); } else { - var n = elementSize; // step 3.a - - var convOp = TypeToAO[type]; // step 3.b - - var intValue = convOp(value); // step 3.c - - rawBytes = integerToNBytes(intValue, n, isLittleEndian); // step 3.d, 3.e, 4 + // 10. Store the individual bytes of rawBytes into block, in order, starting at block[byteIndex]. + var arr = new $Uint8Array(arrayBuffer, byteIndex, elementSize); + forEach(rawBytes, function (rawByte, i) { + arr[i] = rawByte; + }); } - // 12. Store the individual bytes of rawBytes into block, in order, starting at block[byteIndex]. - var arr = new $Uint8Array(arrayBuffer, byteIndex, elementSize); - forEach(rawBytes, function (rawByte, i) { - arr[i] = rawByte; - }); - - // 13. Return NormalCompletion(undefined). + // 11. Return NormalCompletion(undefined). }; diff --git a/2020/SetValueInBuffer.js b/2020/SetValueInBuffer.js index 8a919eb1..563e3b31 100644 --- a/2020/SetValueInBuffer.js +++ b/2020/SetValueInBuffer.js @@ -68,11 +68,11 @@ module.exports = function SetValueInBuffer(arrayBuffer, byteIndex, type, value, throw new $TypeError('Assertion failed: `value` must be a BigInt if type is BigInt64 or BigUint64, otherwise a Number'); } - // 5. Let block be arrayBuffer’s [[ArrayBufferData]] internal slot. + // 5. Let block be arrayBuffer.[[ArrayBufferData]]. var elementSize = tableTAO.size['$' + type]; // step 6 - // 8. If isLittleEndian is not present, set isLittleEndian to either true or false. The choice is implementation dependent and should be the alternative that is most efficient for the implementation. An implementation must use the same value each time this step is executed and the same value must be used for the corresponding step in the GetValueFromBuffer abstract operation. + // 7. If isLittleEndian is not present, set isLittleEndian to to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. var isLittleEndian = arguments.length > 6 ? arguments[6] : defaultEndianness === 'little'; // step 8 var rawBytes = NumericToRawBytes(type, value, isLittleEndian); // step 8 diff --git a/test/tests.js b/test/tests.js index 04ef80b0..c2b22e56 100644 --- a/test/tests.js +++ b/test/tests.js @@ -116,6 +116,66 @@ var noThrowOnStrictViolation = (function () { return false; }()); +var clearBuffer = function clearBuffer(buffer) { + new DataView(buffer).setFloat64(0, 0, true); // clear the buffer +}; + +var testSetValueInBuffer = function (ES, st, testCase, isTypedArray, order) { + return function (type) { + var isBigInt = type === 'BigInt64' || type === 'BigUint64'; + var Z = isBigInt ? safeBigInt : Number; + var elementSize = elementSizes['$' + (type === 'Uint8C' ? 'Uint8Clamped' : type) + 'Array']; + var hasBigEndian = type !== 'Int8' && type !== 'Uint8' && type !== 'Uint8C'; // the 8-bit types are special, they don't have big-endian + var result = testCase[type === 'Uint8C' ? 'Uint8Clamped' : type]; + var value = unserialize(testCase.value); + + if (isBigInt && (!isFinite(value) || Math.floor(value) !== value)) { + return; + } + + var valToSet = type === 'Uint8Clamped' && value > 255 ? 255 : Z(value); + + /* + st.equal( + ES.SetValueInBuffer(testCase.buffer, 0, type, true, order), + defaultEndianness === testCase.endian ? testCase[type].little.value] : testCase[type].big.value, + 'buffer holding ' + debug(testCase.value) + ' (' + testCase.endian + ' endian) with type ' + type + ', default endian, yields expected value' + ); + */ + + var buffer = new ArrayBuffer(elementSizes.$Float64Array); + var copyBytes = new Uint8Array(buffer); + + clearBuffer(buffer); + + st.equal( + ES.SetValueInBuffer(buffer, 0, type, valToSet, isTypedArray, order, true), + void undefined, + 'returns undefined' + ); + st.deepEqual( + Array.prototype.slice.call(copyBytes, 0, elementSize), + Array.prototype.slice.call(new Uint8Array(result[type === 'Float64' ? 'setAsLittle' : 'setAsTruncatedLittle'].bytes), 0, elementSize), + 'buffer holding ' + debug(value) + ' with type ' + type + ', little endian, yields expected value' + ); + + if (hasBigEndian) { + clearBuffer(buffer); + + st.equal( + ES.SetValueInBuffer(buffer, 0, type, valToSet, isTypedArray, order, false), + void undefined, + 'returns undefined' + ); + st.deepEqual( + Array.prototype.slice.call(copyBytes, 0, elementSize), + Array.prototype.slice.call(new Uint8Array(result[type === 'Float64' ? 'setAsBig' : 'setAsTruncatedBig'].bytes), 0, elementSizes[type + 'Array']), + 'buffer holding ' + debug(value) + ' with type ' + type + ', big endian, yields expected value' + ); + } + }; +}; + // var defaultEndianness = require('../helpers/defaultEndianness'); var nameExceptions = { @@ -249,10 +309,6 @@ var kludgeMatch = function kludgeMatch(R, matchObject) { return matchObject; }; -var clearBuffer = function clearBuffer(buffer) { - new DataView(buffer).setFloat64(0, 0, true); // clear the buffer -}; - var testEnumerableOwnNames = function (t, enumerableOwnNames) { forEach(v.primitives, function (nonObject) { t['throws']( @@ -6002,7 +6058,8 @@ var es2017 = function ES2017(ES, ops, expectedMissing, skips) { GetValueFromBuffer: true, EnumerableOwnNames: true, IsWordChar: true, - IterableToArrayLike: true + IterableToArrayLike: true, + SetValueInBuffer: true })); var test = makeTest(ES, skips); @@ -6693,6 +6750,121 @@ var es2017 = function ES2017(ES, ops, expectedMissing, skips) { t.end(); }); + test('SetValueInBuffer', function (t) { + var order = 'Unordered'; + + forEach(v.primitives.concat(v.objects), function (nonAB) { + t['throws']( + function () { ES.SetValueInBuffer(nonAB, 0, 'Int8', 0, false, order); }, + TypeError, + debug(nonAB) + ' is not an ArrayBuffer' + ); + }); + + t.test('ArrayBuffers supported', { skip: typeof ArrayBuffer !== 'function' }, function (st) { + var isTypedArray = false; // only matters for SAB + + forEach(v.notNonNegativeIntegers, function (nonNonNegativeInteger) { + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), nonNonNegativeInteger, 'Int8', 0, isTypedArray, order); }, + TypeError, + debug(nonNonNegativeInteger) + ' is not a valid byte index' + ); + }); + + forEach(v.nonStrings.concat('not a valid type'), function (nonString) { + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), 0, nonString, 0, isTypedArray, order); }, + TypeError, + 'type: ' + debug(nonString) + ' is not a valid String (or type) value' + ); + }); + + forEach(v.nonBooleans, function (nonBoolean) { + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), 0, 'Int8', 0, nonBoolean, order); }, + TypeError, + 'isTypedArray: ' + debug(nonBoolean) + ' is not a valid Boolean value' + ); + + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), 0, 'Int8', 0, isTypedArray, order, nonBoolean); }, + TypeError, + 'isLittleEndian: ' + debug(nonBoolean) + ' is not a valid Boolean value' + ); + }); + + forEach(v.nonNumbers, function (nonNumber) { + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), 0, 'Int8', nonNumber, isTypedArray, order); }, + TypeError, + debug(nonNumber) + ' is not a valid Number or BigInt value' + ); + }); + + if (hasBigInts) { + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), 0, 'Int8', $BigInt(0), isTypedArray, order); }, + TypeError, + debug($BigInt(0)) + ' is not a number, but the given type requires one' + ); + + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), 0, 'BigUint64', 0, isTypedArray, order); }, + TypeError, + debug(0) + ' is not a bigint, but the given type requires one' + ); + } + + st['throws']( + function () { ES.SetValueInBuffer(new ArrayBuffer(8), 0, 'Int8', 0, isTypedArray, 'invalid order'); }, + TypeError, + 'invalid order' + ); + + st.test('can detach', { skip: !canDetach }, function (s2t) { + var buffer = new ArrayBuffer(8); + s2t.equal(ES.DetachArrayBuffer(buffer), null, 'detaching returns null'); + + s2t['throws']( + function () { ES.SetValueInBuffer(buffer, 0, 'Int8', 0, isTypedArray, order); }, + TypeError, + 'detached buffers throw' + ); + + s2t.end(); + }); + + st.test('SharedArrayBuffers supported', { skip: typeof SharedArrayBuffer !== 'function' }, function (s2t) { + s2t['throws']( + function () { ES.SetValueInBuffer(new SharedArrayBuffer(0), 0, 'Int8', 0, true, order); }, + SyntaxError, + 'SAB not yet supported' + ); + + s2t.end(); + }); + + forEach(bufferTestCases, function (testCase, name) { + forEach([].concat( + 'Int8', + 'Uint8', + 'Uint8C', + 'Int16', + 'Uint16', + 'Int32', + 'Uint32', + 'Float32', + 'Float64' + ), testSetValueInBuffer(ES, st, testCase, isTypedArray, order)); + }); + + st.end(); + }); + + t.end(); + }); + test('StringGetOwnProperty', function (t) { forEach(v.nonStrings.concat(v.strings), function (nonBoxedString) { t['throws']( @@ -10701,59 +10873,7 @@ var es2020 = function ES2020(ES, ops, expectedMissing, skips) { hasBigInts ? bigIntTypes : [], 'Float32', 'Float64' - ), function (type) { - var isBigInt = type === 'BigInt64' || type === 'BigUint64'; - var Z = isBigInt ? safeBigInt : Number; - var elementSize = elementSizes['$' + (type === 'Uint8C' ? 'Uint8Clamped' : type) + 'Array']; - var hasBigEndian = type !== 'Int8' && type !== 'Uint8' && type !== 'Uint8C'; // the 8-bit types are special, they don't have big-endian - var result = testCase[type === 'Uint8C' ? 'Uint8Clamped' : type]; - var value = unserialize(testCase.value); - - if (isBigInt && (!isFinite(value) || Math.floor(value) !== value)) { - return; - } - - var valToSet = type === 'Uint8Clamped' && value > 255 ? 255 : Z(value); - - /* - st.equal( - ES.SetValueInBuffer(testCase.buffer, 0, type, true, order), - defaultEndianness === testCase.endian ? testCase[type].little.value] : testCase[type].big.value, - 'buffer holding ' + debug(testCase.value) + ' (' + testCase.endian + ' endian) with type ' + type + ', default endian, yields expected value' - ); - */ - - var buffer = new ArrayBuffer(elementSizes.$Float64Array); - var copyBytes = new Uint8Array(buffer); - - clearBuffer(buffer); - - st.equal( - ES.SetValueInBuffer(buffer, 0, type, valToSet, isTypedArray, order, true), - void undefined, - 'returns undefined' - ); - st.deepEqual( - Array.prototype.slice.call(copyBytes, 0, elementSize), - Array.prototype.slice.call(new Uint8Array(result[type === 'Float64' ? 'setAsLittle' : 'setAsTruncatedLittle'].bytes), 0, elementSize), - 'buffer holding ' + debug(value) + ' with type ' + type + ', little endian, yields expected value' - ); - - if (hasBigEndian) { - clearBuffer(buffer); - - st.equal( - ES.SetValueInBuffer(buffer, 0, type, valToSet, isTypedArray, order, false), - void undefined, - 'returns undefined' - ); - st.deepEqual( - Array.prototype.slice.call(copyBytes, 0, elementSize), - Array.prototype.slice.call(new Uint8Array(result[type === 'Float64' ? 'setAsBig' : 'setAsTruncatedBig'].bytes), 0, elementSizes[type + 'Array']), - 'buffer holding ' + debug(value) + ' with type ' + type + ', big endian, yields expected value' - ); - } - }); + ), testSetValueInBuffer(ES, st, testCase, isTypedArray, order)); }); st.end(); From 8f742b632bc2ac2f397683b939b9d7f588474c26 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Mon, 25 Nov 2024 17:47:53 -1000 Subject: [PATCH 7/9] [Tests] `isStringOrUndefined`: increase coverage --- test/helpers/isStringOrUndefined.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/helpers/isStringOrUndefined.js b/test/helpers/isStringOrUndefined.js index 06a654d9..7b2eee9b 100644 --- a/test/helpers/isStringOrUndefined.js +++ b/test/helpers/isStringOrUndefined.js @@ -1,13 +1,23 @@ 'use strict'; var test = require('tape'); +var v = require('es-value-fixtures'); +var inspect = require('object-inspect'); + +var forEach = require('../../helpers/forEach'); var isStringOrUndefined = require('../../helpers/isStringOrUndefined'); test('isStringOrUndefined', function (t) { - t.ok(isStringOrUndefined('foo', 0, ['foo', 'bar', 'baz']), 'string item is a string or undefined'); + t.ok(isStringOrUndefined('foo'), 'string is a string or undefined'); + + t.ok(isStringOrUndefined(undefined), 'undefined is a string or undefined'); - t.ok(isStringOrUndefined(undefined, 0, [undefined, 'bar', 'baz']), 'present undefined item is a string or undefined'); + forEach(v.primitives, function (primitive) { + if (typeof primitive !== 'undefined' && typeof primitive !== 'string') { + t.notOk(isStringOrUndefined(primitive), inspect(primitive) + ' is not a string or undefined'); + } + }); t.end(); }); From b5544b3cd0aca2a83c0528785651ca59747afbe7 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 26 Nov 2024 10:37:28 -0800 Subject: [PATCH 8/9] [Deps] update `es-to-primitive` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ee1dbffe..fb4b9128 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", + "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", "get-symbol-description": "^1.0.2", From ea2268bc2b6157885361fee3d664185dfe6e0521 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 26 Nov 2024 11:22:28 -0800 Subject: [PATCH 9/9] [Dev Deps] update `is-registered-symbol` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fb4b9128..fcb48294 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "has-strict-mode": "^1.0.1", "in-publish": "^2.0.1", "is-core-module": "^2.15.1", - "is-registered-symbol": "^1.0.1", + "is-registered-symbol": "^1.1.0", "jackspeak": "=2.1.1", "make-arrow-function": "^1.2.0", "make-async-function": "^1.0.0",