UNPKG

es-arraybuffer-base64

Version:

An ES-spec-compliant shim/polyfill/replacement for ArrayBuffer base64 methods that works as far down as ES3

244 lines (202 loc) 7.12 kB
'use strict'; var callBind = require('call-bind'); var defineProperties = require('define-properties'); var DetachArrayBuffer = require('es-abstract/2024/DetachArrayBuffer'); var forEach = require('es-abstract/helpers/forEach'); var isCore = require('is-core-module'); var test = require('tape'); /* globals postMessage: false */ var canDetach = typeof structuredClone === 'function' || typeof postMessage === 'function' || isCore('worker_threads'); var index = require('../Uint8Array.prototype.setFromHex'); var impl = require('../Uint8Array.prototype.setFromHex/implementation'); var polyfill = require('../Uint8Array.prototype.setFromHex/polyfill')(); var isEnumerable = Object.prototype.propertyIsEnumerable; var shimName = 'Uint8Array.prototype.setFromHex'; module.exports = { tests: function (t, method) { t.test('Uint8Arrays not supported', { skip: typeof Uint8Array === 'function' }, function (st) { st['throws']( function () { return method(''); }, SyntaxError, 'throws SyntaxError when Uint8Arrays are not supported' ); st.end(); }); t.test('Uint8Arrays supported', { skip: typeof Uint8Array !== 'function' }, function (st) { var arr = new Uint8Array(256); arr[0] = 1; st['throws']( function () { return method(arr, 'F'); }, SyntaxError, 'throws on odd-numbered length hex strings' ); st['throws']( function () { return method(arr, 'FG'); }, SyntaxError, 'throws on invalid hex string characters' ); var expectedArr = new Uint8Array(256); expectedArr[0] = 1; st.deepEqual(arr, expectedArr, 'initial `arr`'); st.deepEqual(method(arr, ''), { read: 0, written: 0 }, 'empty string makes no changes'); st.deepEqual(arr, expectedArr, '`arr`, no changes'); var hex = ''; var expected = []; for (var i = 0; i < 256; i++) { hex += ('00' + i.toString(16)).slice(-2); expected.push(i); } st.deepEqual( method(arr, hex), { read: 512, written: 256 }, 'return object is as expected' ); st.deepEqual( arr, new Uint8Array(expected), 'hex (' + hex + ') produces expected bytes (' + expected.join(', ') + ') into `arr`' ); st.test('test262: test/built-ins/Uint8Array/prototype/setFromHex/detached-buffer.js', { skip: !canDetach }, function (s2t) { var target = new Uint8Array([255, 255, 255]); DetachArrayBuffer(target.buffer); s2t['throws']( function () { method(target, 'aa'); }, TypeError ); s2t.end(); }); var illegal = [ 'a.a', 'aa^', 'a a', 'a\ta', 'a\x0Aa', 'a\x0Ca', 'a\x0Da', 'a\u00A0a', // nbsp 'a\u2009a', // thin space 'a\u2028a' // line separator ]; forEach(illegal, function (value) { st['throws']( function () { var target = new Uint8Array([255, 255, 255, 255, 255]); method(target, value); }, SyntaxError ); }); var cases = [ ['', []], ['66', [102]], ['666f', [102, 111]], ['666F', [102, 111]], ['666f6f', [102, 111, 111]], ['666F6f', [102, 111, 111]], ['666f6f62', [102, 111, 111, 98]], ['666f6f6261', [102, 111, 111, 98, 97]], ['666f6f626172', [102, 111, 111, 98, 97, 114]] ]; forEach(cases, function (pair) { var allFF = [255, 255, 255, 255, 255, 255, 255, 255]; var target = new Uint8Array(allFF); var result = method(target, pair[0]); st.deepEqual(result, { read: pair[0].length, written: pair[1].length }); var expectedResult = new Uint8Array(pair[1].concat(allFF.slice(pair[1].length))); st.deepEqual(target, expectedResult, 'decoding ' + pair[0]); }); st.test('test262: test/built-ins/Uint8Array/prototype/setFromHex/string-coercion.js', function (s2t) { var throwyToString = {}; var results = s2t.intercept(throwyToString, 'toString', { value: function () { throw new EvalError('toString called'); } }); s2t['throws']( function () { var target = new Uint8Array(10); method(target, throwyToString); }, TypeError ); s2t.deepEqual(results(), []); s2t.end(); }); st.test('test262: test/built-ins/Uint8Array/prototype/setFromHex/subarray.js', function (s2t) { var base = new Uint8Array([255, 255, 255, 255, 255, 255, 255]); var subarray = base.subarray(2, 5); var result = method(subarray, 'aabbcc'); s2t.deepEqual(result, { read: 6, written: 3 }); s2t.deepEqual(subarray, new Uint8Array([170, 187, 204])); s2t.deepEqual(base, new Uint8Array([255, 255, 170, 187, 204, 255, 255])); s2t.end(); }); st.test('test262: test/built-ins/Uint8Array/prototype/setFromHex/target-size.js', function (s2t) { // buffer too small var target = new Uint8Array([255, 255]); var result = method(target, 'aabbcc'); s2t.deepEqual(result, { read: 4, written: 2 }); s2t.deepEqual(target, new Uint8Array([170, 187])); // buffer exact var target2 = new Uint8Array([255, 255, 255]); var result2 = method(target2, 'aabbcc'); s2t.deepEqual(result2, { read: 6, written: 3 }); s2t.deepEqual(target2, new Uint8Array([170, 187, 204])); // buffer too large var target3 = new Uint8Array([255, 255, 255, 255]); var result3 = method(target3, 'aabbcc'); s2t.deepEqual(result3, { read: 6, written: 3 }); s2t.deepEqual(target3, new Uint8Array([170, 187, 204, 255])); s2t.end(); }); st.test('test262: test/built-ins/Uint8Array/prototype/setFromHex/writes-up-to-error', function (s2t) { ['aaa ', 'aaag'].forEach(function (value) { var target = new Uint8Array([255, 255, 255, 255, 255]); s2t['throws']( function () { method(target, value); }, SyntaxError ); s2t.deepEqual(target, new Uint8Array([170, 255, 255, 255, 255]), 'decoding from ' + value); }); var target = new Uint8Array([255, 255, 255, 255, 255]); s2t['throws']( function () { method(target, 'aaa'); }, SyntaxError ); s2t.deepEqual(target, new Uint8Array([255, 255, 255, 255, 255]), 'when length is odd no data is written'); s2t.end(); }); st.end(); }); }, index: function () { test(shimName + ': index', function (t) { t.notEqual(index, polyfill, 'index !== polyfill'); t.equal(typeof index, 'function', 'index is a function'); t['throws']( function () { return new index(); }, // eslint-disable-line new-cap TypeError, 'index throws when Construct-ed' ); module.exports.tests(t, index); t.end(); }); }, implementation: function () { test(shimName + ': implementation', function (t) { t.equal(impl, polyfill, 'implementation is polyfill itself'); module.exports.tests(t, callBind(impl)); t.end(); }); }, shimmed: function () { test(shimName + ': shimmed', function (t) { t.test('enumerability', { skip: !defineProperties.supportsDescriptors }, function (et) { et.equal(false, isEnumerable.call(Uint8Array.prototype, 'setFromHex'), shimName + ' is not enumerable'); et.end(); }); module.exports.tests(t, callBind(Uint8Array.prototype.setFromHex)); t.end(); }); } };