diff options
author | 2023-01-28 04:03:45 -0800 | |
---|---|---|
committer | 2023-01-28 04:03:45 -0800 | |
commit | 7db4b90837b3515134b79733bb8fdd541a1b836b (patch) | |
tree | 373801b480ebe30b148b2954bf91935a95724cf1 | |
parent | cd48346ca87c5e350e6e748eed927753f87546fe (diff) | |
download | bun-7db4b90837b3515134b79733bb8fdd541a1b836b.tar.gz bun-7db4b90837b3515134b79733bb8fdd541a1b836b.tar.zst bun-7db4b90837b3515134b79733bb8fdd541a1b836b.zip |
commit failing tests
-rw-r--r-- | test/bun.js/buffer.test.js | 1682 |
1 files changed, 1682 insertions, 0 deletions
diff --git a/test/bun.js/buffer.test.js b/test/bun.js/buffer.test.js index 9869f732e..c732b58e3 100644 --- a/test/bun.js/buffer.test.js +++ b/test/bun.js/buffer.test.js @@ -6,6 +6,1296 @@ const BufferModule = await import("buffer"); beforeEach(() => gc()); afterEach(() => gc()); +const assert = { + deepStrictEqual(a, b) { + expect(b).toStrictEqual(a); + }, + strictEqual(a, b) { + expect(a).toBe(b); + }, + throws(a, b) { + expect(a).toThrow(); + }, +}; + +it("Buffer.alloc", () => { + // Verify the maximum Uint8Array size. There is no concrete limit by spec. The + // internal limits should be updated if this fails. + assert.throws(() => new Uint8Array(2 ** 32 + 1), { + message: "Invalid typed array length: 4294967297", + }); + + const b = Buffer.allocUnsafe(1024); + assert.strictEqual(b.length, 1024); + + b[0] = -1; + assert.strictEqual(b[0], 255); + + for (let i = 0; i < 1024; i++) { + b[i] = i % 256; + } + + for (let i = 0; i < 1024; i++) { + assert.strictEqual(i % 256, b[i]); + } + + const c = Buffer.allocUnsafe(512); + assert.strictEqual(c.length, 512); + + const d = Buffer.from([]); + assert.strictEqual(d.length, 0); + + // Test offset properties + { + const b = Buffer.alloc(128); + assert.strictEqual(b.length, 128); + assert.strictEqual(b.byteOffset, 0); + assert.strictEqual(b.offset, 0); + } + + // Test creating a Buffer from a Uint32Array + { + const ui32 = new Uint32Array(4).fill(42); + const e = Buffer.from(ui32); + for (const [index, value] of e.entries()) { + assert.strictEqual(value, ui32[index]); + } + } + // Test creating a Buffer from a Uint32Array (old constructor) + { + const ui32 = new Uint32Array(4).fill(42); + const e = Buffer(ui32); + for (const [key, value] of e.entries()) { + assert.deepStrictEqual(value, ui32[key]); + } + } + + // Test invalid encoding for Buffer.toString + assert.throws(() => b.toString("invalid"), /Unknown encoding: invalid/); + // Invalid encoding for Buffer.write + assert.throws( + () => b.write("test string", 0, 5, "invalid"), + /Unknown encoding: invalid/, + ); + // Unsupported arguments for Buffer.write + // assert.throws(() => b.write("test", "utf8", 0), { + // code: "ERR_INVALID_ARG_TYPE", + // }); + + // Try to create 0-length buffers. Should not throw. + Buffer.from(""); + Buffer.from("", "ascii"); + Buffer.from("", "latin1"); + Buffer.alloc(0); + Buffer.allocUnsafe(0); + new Buffer(""); + new Buffer("", "ascii"); + new Buffer("", "latin1"); + new Buffer("", "binary"); + Buffer(0); + + const outOfRangeError = { + code: "ERR_OUT_OF_RANGE", + name: "RangeError", + }; + + // Try to write a 0-length string beyond the end of b + // assert.throws(() => b.write("", 2048), outOfRangeError); + + // // Throw when writing to negative offset + // assert.throws(() => b.write("a", -1), outOfRangeError); + + // // Throw when writing past bounds from the pool + // assert.throws(() => b.write("a", 2048), outOfRangeError); + + // // Throw when writing to negative offset + // assert.throws(() => b.write("a", -1), outOfRangeError); + + // Try to copy 0 bytes worth of data into an empty buffer + b.copy(Buffer.alloc(0), 0, 0, 0); + + // Try to copy 0 bytes past the end of the target buffer + b.copy(Buffer.alloc(0), 1, 1, 1); + b.copy(Buffer.alloc(1), 1, 1, 1); + + // Try to copy 0 bytes from past the end of the source buffer + b.copy(Buffer.alloc(1), 0, 2048, 2048); + + // Testing for smart defaults and ability to pass string values as offset + { + const writeTest = Buffer.from("abcdes"); + writeTest.write("n", "ascii"); + assert.throws(() => writeTest.write("o", "1", "ascii"), { + code: "ERR_INVALID_ARG_TYPE", + }); + writeTest.write("o", 1, "ascii"); + writeTest.write("d", 2, "ascii"); + writeTest.write("e", 3, "ascii"); + writeTest.write("j", 4, "ascii"); + assert.strictEqual(writeTest.toString(), "nodejs"); + } + + // Offset points to the end of the buffer and does not throw. + // (see https://github.com/nodejs/node/issues/8127). + Buffer.alloc(1).write("", 1, 0); + + // ASCII slice test + { + const asciiString = "hello world"; + + for (let i = 0; i < asciiString.length; i++) { + b[i] = asciiString.charCodeAt(i); + } + const asciiSlice = b.toString("ascii", 0, asciiString.length); + assert.strictEqual(asciiString, asciiSlice); + } + + { + const asciiString = "hello world"; + const offset = 100; + + assert.strictEqual( + asciiString.length, + b.write(asciiString, offset, "ascii"), + ); + const asciiSlice = b.toString("ascii", offset, offset + asciiString.length); + assert.strictEqual(asciiString, asciiSlice); + } + + { + const asciiString = "hello world"; + const offset = 100; + + const sliceA = b.slice(offset, offset + asciiString.length); + const sliceB = b.slice(offset, offset + asciiString.length); + for (let i = 0; i < asciiString.length; i++) { + assert.strictEqual(sliceA[i], sliceB[i]); + } + } + + // UTF-8 slice test + { + const utf8String = "¡hέlló wôrld!"; + const offset = 100; + + b.write(utf8String, 0, Buffer.byteLength(utf8String), "utf8"); + let utf8Slice = b.toString("utf8", 0, Buffer.byteLength(utf8String)); + assert.strictEqual(utf8String, utf8Slice); + + assert.strictEqual( + Buffer.byteLength(utf8String), + b.write(utf8String, offset, "utf8"), + ); + utf8Slice = b.toString( + "utf8", + offset, + offset + Buffer.byteLength(utf8String), + ); + assert.strictEqual(utf8String, utf8Slice); + + const sliceA = b.slice(offset, offset + Buffer.byteLength(utf8String)); + const sliceB = b.slice(offset, offset + Buffer.byteLength(utf8String)); + for (let i = 0; i < Buffer.byteLength(utf8String); i++) { + assert.strictEqual(sliceA[i], sliceB[i]); + } + } + + { + const slice = b.slice(100, 150); + assert.strictEqual(slice.length, 50); + for (let i = 0; i < 50; i++) { + assert.strictEqual(b[100 + i], slice[i]); + } + } + + { + // Make sure only top level parent propagates from allocPool + const b = Buffer.allocUnsafe(5); + const c = b.slice(0, 4); + const d = c.slice(0, 2); + assert.strictEqual(b.parent, c.parent); + assert.strictEqual(b.parent, d.parent); + } + + { + // Also from a non-pooled instance + const b = Buffer.allocUnsafeSlow(5); + const c = b.slice(0, 4); + const d = c.slice(0, 2); + assert.strictEqual(c.parent, d.parent); + } + + { + // Bug regression test + const testValue = "\u00F6\u65E5\u672C\u8A9E"; // ö日本語 + const buffer = Buffer.allocUnsafe(32); + const size = buffer.write(testValue, 0, "utf8"); + const slice = buffer.toString("utf8", 0, size); + assert.strictEqual(slice, testValue); + } + + { + // Test triple slice + const a = Buffer.allocUnsafe(8); + for (let i = 0; i < 8; i++) a[i] = i; + const b = a.slice(4, 8); + assert.strictEqual(b[0], 4); + assert.strictEqual(b[1], 5); + assert.strictEqual(b[2], 6); + assert.strictEqual(b[3], 7); + const c = b.slice(2, 4); + assert.strictEqual(c[0], 6); + assert.strictEqual(c[1], 7); + } + + { + const d = Buffer.from([23, 42, 255]); + assert.strictEqual(d.length, 3); + assert.strictEqual(d[0], 23); + assert.strictEqual(d[1], 42); + assert.strictEqual(d[2], 255); + assert.deepStrictEqual(d, Buffer.from(d)); + } + + { + // Test for proper UTF-8 Encoding + const e = Buffer.from("über"); + assert.deepStrictEqual(e, Buffer.from([195, 188, 98, 101, 114])); + } + + { + // Test for proper ascii Encoding, length should be 4 + const f = Buffer.from("über", "ascii"); + assert.deepStrictEqual(f, Buffer.from([252, 98, 101, 114])); + } + + ["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach((encoding) => { + { + // Test for proper UTF16LE encoding, length should be 8 + const f = Buffer.from("über", encoding); + assert.deepStrictEqual(f, Buffer.from([252, 0, 98, 0, 101, 0, 114, 0])); + } + + { + // Length should be 12 + const f = Buffer.from("привет", encoding); + assert.deepStrictEqual( + f, + Buffer.from([63, 4, 64, 4, 56, 4, 50, 4, 53, 4, 66, 4]), + ); + assert.strictEqual(f.toString(encoding), "привет"); + } + + { + const f = Buffer.from([0, 0, 0, 0, 0]); + assert.strictEqual(f.length, 5); + const size = f.write("あいうえお", encoding); + assert.strictEqual(size, 4); + assert.deepStrictEqual(f, Buffer.from([0x42, 0x30, 0x44, 0x30, 0x00])); + } + }); + + { + const f = Buffer.from("\uD83D\uDC4D", "utf-16le"); // THUMBS UP SIGN (U+1F44D) + assert.strictEqual(f.length, 4); + assert.deepStrictEqual(f, Buffer.from("3DD84DDC", "hex")); + } + + // Test construction from arrayish object + { + const arrayIsh = { 0: 0, 1: 1, 2: 2, 3: 3, length: 4 }; + let g = Buffer.from(arrayIsh); + assert.deepStrictEqual(g, Buffer.from([0, 1, 2, 3])); + const strArrayIsh = { 0: "0", 1: "1", 2: "2", 3: "3", length: 4 }; + g = Buffer.from(strArrayIsh); + assert.deepStrictEqual(g, Buffer.from([0, 1, 2, 3])); + } + + // + // Test toString('base64') + // + assert.strictEqual(Buffer.from("Man").toString("base64"), "TWFu"); + assert.strictEqual(Buffer.from("Woman").toString("base64"), "V29tYW4="); + + // + // Test toString('base64url') + // + assert.strictEqual(Buffer.from("Man").toString("base64url"), "TWFu"); + assert.strictEqual(Buffer.from("Woman").toString("base64url"), "V29tYW4"); + + { + // Test that regular and URL-safe base64 both work both ways + const expected = [0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff]; + assert.deepStrictEqual( + Buffer.from("//++/++/++//", "base64"), + Buffer.from(expected), + ); + assert.deepStrictEqual( + Buffer.from("__--_--_--__", "base64"), + Buffer.from(expected), + ); + assert.deepStrictEqual( + Buffer.from("//++/++/++//", "base64url"), + Buffer.from(expected), + ); + assert.deepStrictEqual( + Buffer.from("__--_--_--__", "base64url"), + Buffer.from(expected), + ); + } + + const base64flavors = ["base64", "base64url"]; + + { + // Test that regular and URL-safe base64 both work both ways with padding + const expected = [ + 0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff, 0xfb, + ]; + assert.deepStrictEqual( + Buffer.from("//++/++/++//+w==", "base64"), + Buffer.from(expected), + ); + assert.deepStrictEqual( + Buffer.from("//++/++/++//+w==", "base64"), + Buffer.from(expected), + ); + assert.deepStrictEqual( + Buffer.from("//++/++/++//+w==", "base64url"), + Buffer.from(expected), + ); + assert.deepStrictEqual( + Buffer.from("//++/++/++//+w==", "base64url"), + Buffer.from(expected), + ); + } + + { + // big example + const quote = + "Man is distinguished, not only by his reason, but by this " + + "singular passion from other animals, which is a lust " + + "of the mind, that by a perseverance of delight in the " + + "continued and indefatigable generation of knowledge, " + + "exceeds the short vehemence of any carnal pleasure."; + const expected = + "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb" + + "24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci" + + "BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQ" + + "gYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" + + "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ" + + "GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm" + + "5hbCBwbGVhc3VyZS4="; + assert.strictEqual(Buffer.from(quote).toString("base64"), expected); + assert.strictEqual( + Buffer.from(quote).toString("base64url"), + expected.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", ""), + ); + + base64flavors.forEach((encoding) => { + let b = Buffer.allocUnsafe(1024); + let bytesWritten = b.write(expected, 0, encoding); + assert.strictEqual(quote.length, bytesWritten); + assert.strictEqual(quote, b.toString("ascii", 0, quote.length)); + + // Check that the base64 decoder ignores whitespace + const expectedWhite = + `${expected.slice(0, 60)} \n` + + `${expected.slice(60, 120)} \n` + + `${expected.slice(120, 180)} \n` + + `${expected.slice(180, 240)} \n` + + `${expected.slice(240, 300)}\n` + + `${expected.slice(300, 360)}\n`; + b = Buffer.allocUnsafe(1024); + bytesWritten = b.write(expectedWhite, 0, encoding); + assert.strictEqual(quote.length, bytesWritten); + assert.strictEqual(quote, b.toString("ascii", 0, quote.length)); + + // Check that the base64 decoder on the constructor works + // even in the presence of whitespace. + b = Buffer.from(expectedWhite, encoding); + assert.strictEqual(quote.length, b.length); + assert.strictEqual(quote, b.toString("ascii", 0, quote.length)); + + // Check that the base64 decoder ignores illegal chars + const expectedIllegal = + expected.slice(0, 60) + + " \x80" + + expected.slice(60, 120) + + " \xff" + + expected.slice(120, 180) + + " \x00" + + expected.slice(180, 240) + + " \x98" + + expected.slice(240, 300) + + "\x03" + + expected.slice(300, 360); + b = Buffer.from(expectedIllegal, encoding); + assert.strictEqual(quote.length, b.length); + assert.strictEqual(quote, b.toString("ascii", 0, quote.length)); + }); + } + + base64flavors.forEach((encoding) => { + assert.strictEqual(Buffer.from("", encoding).toString(), ""); + assert.strictEqual(Buffer.from("K", encoding).toString(), ""); + + // multiple-of-4 with padding + assert.strictEqual(Buffer.from("Kg==", encoding).toString(), "*"); + assert.strictEqual(Buffer.from("Kio=", encoding).toString(), "*".repeat(2)); + assert.strictEqual(Buffer.from("Kioq", encoding).toString(), "*".repeat(3)); + assert.strictEqual( + Buffer.from("KioqKg==", encoding).toString(), + "*".repeat(4), + ); + assert.strictEqual( + Buffer.from("KioqKio=", encoding).toString(), + "*".repeat(5), + ); + assert.strictEqual( + Buffer.from("KioqKioq", encoding).toString(), + "*".repeat(6), + ); + assert.strictEqual( + Buffer.from("KioqKioqKg==", encoding).toString(), + "*".repeat(7), + ); + assert.strictEqual( + Buffer.from("KioqKioqKio=", encoding).toString(), + "*".repeat(8), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioq", encoding).toString(), + "*".repeat(9), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKg==", encoding).toString(), + "*".repeat(10), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKio=", encoding).toString(), + "*".repeat(11), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioq", encoding).toString(), + "*".repeat(12), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKg==", encoding).toString(), + "*".repeat(13), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKio=", encoding).toString(), + "*".repeat(14), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioq", encoding).toString(), + "*".repeat(15), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKg==", encoding).toString(), + "*".repeat(16), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKio=", encoding).toString(), + "*".repeat(17), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKioq", encoding).toString(), + "*".repeat(18), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKioqKg==", encoding).toString(), + "*".repeat(19), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKioqKio=", encoding).toString(), + "*".repeat(20), + ); + + // No padding, not a multiple of 4 + assert.strictEqual(Buffer.from("Kg", encoding).toString(), "*"); + assert.strictEqual(Buffer.from("Kio", encoding).toString(), "*".repeat(2)); + assert.strictEqual( + Buffer.from("KioqKg", encoding).toString(), + "*".repeat(4), + ); + assert.strictEqual( + Buffer.from("KioqKio", encoding).toString(), + "*".repeat(5), + ); + assert.strictEqual( + Buffer.from("KioqKioqKg", encoding).toString(), + "*".repeat(7), + ); + assert.strictEqual( + Buffer.from("KioqKioqKio", encoding).toString(), + "*".repeat(8), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKg", encoding).toString(), + "*".repeat(10), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKio", encoding).toString(), + "*".repeat(11), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKg", encoding).toString(), + "*".repeat(13), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKio", encoding).toString(), + "*".repeat(14), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKg", encoding).toString(), + "*".repeat(16), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKio", encoding).toString(), + "*".repeat(17), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKioqKg", encoding).toString(), + "*".repeat(19), + ); + assert.strictEqual( + Buffer.from("KioqKioqKioqKioqKioqKioqKio", encoding).toString(), + "*".repeat(20), + ); + }); + + // Handle padding graciously, multiple-of-4 or not + assert.strictEqual( + Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==", "base64") + .length, + 32, + ); + assert.strictEqual( + Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw==", "base64url") + .length, + 32, + ); + assert.strictEqual( + Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=", "base64") + .length, + 32, + ); + assert.strictEqual( + Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw=", "base64url") + .length, + 32, + ); + assert.strictEqual( + Buffer.from("72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw", "base64").length, + 32, + ); + assert.strictEqual( + Buffer.from("72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw", "base64url") + .length, + 32, + ); + assert.strictEqual( + Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==", "base64") + .length, + 31, + ); + assert.strictEqual( + Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==", "base64url") + .length, + 31, + ); + assert.strictEqual( + Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=", "base64").length, + 31, + ); + assert.strictEqual( + Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=", "base64url") + .length, + 31, + ); + assert.strictEqual( + Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg", "base64").length, + 31, + ); + assert.strictEqual( + Buffer.from("w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg", "base64url") + .length, + 31, + ); + + { + // This string encodes single '.' character in UTF-16 + const dot = Buffer.from("//4uAA==", "base64"); + assert.strictEqual(dot[0], 0xff); + assert.strictEqual(dot[1], 0xfe); + assert.strictEqual(dot[2], 0x2e); + assert.strictEqual(dot[3], 0x00); + assert.strictEqual(dot.toString("base64"), "//4uAA=="); + } + + { + // This string encodes single '.' character in UTF-16 + const dot = Buffer.from("//4uAA", "base64url"); + assert.strictEqual(dot[0], 0xff); + assert.strictEqual(dot[1], 0xfe); + assert.strictEqual(dot[2], 0x2e); + assert.strictEqual(dot[3], 0x00); + assert.strictEqual(dot.toString("base64url"), "__4uAA"); + } + + { + // Writing base64 at a position > 0 should not mangle the result. + // + // https://github.com/joyent/node/issues/402 + const segments = ["TWFkbmVzcz8h", "IFRoaXM=", "IGlz", "IG5vZGUuanMh"]; + const b = Buffer.allocUnsafe(64); + let pos = 0; + + for (let i = 0; i < segments.length; ++i) { + pos += b.write(segments[i], pos, "base64"); + } + assert.strictEqual( + b.toString("latin1", 0, pos), + "Madness?! This is node.js!", + ); + } + + { + // Writing base64url at a position > 0 should not mangle the result. + // + // https://github.com/joyent/node/issues/402 + const segments = ["TWFkbmVzcz8h", "IFRoaXM", "IGlz", "IG5vZGUuanMh"]; + const b = Buffer.allocUnsafe(64); + let pos = 0; + + for (let i = 0; i < segments.length; ++i) { + pos += b.write(segments[i], pos, "base64url"); + } + assert.strictEqual( + b.toString("latin1", 0, pos), + "Madness?! This is node.js!", + ); + } + + // Regression test for https://github.com/nodejs/node/issues/3496. + assert.strictEqual(Buffer.from("=bad".repeat(1e4), "base64").length, 0); + + // Regression test for https://github.com/nodejs/node/issues/11987. + assert.deepStrictEqual( + Buffer.from("w0 ", "base64"), + Buffer.from("w0", "base64"), + ); + + // Regression test for https://github.com/nodejs/node/issues/13657. + assert.deepStrictEqual( + Buffer.from(" YWJvcnVtLg", "base64"), + Buffer.from("YWJvcnVtLg", "base64"), + ); + + { + // Creating buffers larger than pool size. + const l = Buffer.poolSize + 5; + const s = "h".repeat(l); + const b = Buffer.from(s); + + for (let i = 0; i < l; i++) { + assert.strictEqual(b[i], "h".charCodeAt(0)); + } + + const sb = b.toString(); + assert.strictEqual(sb.length, s.length); + assert.strictEqual(sb, s); + } + + { + // test hex toString + const hexb = Buffer.allocUnsafe(256); + for (let i = 0; i < 256; i++) { + hexb[i] = i; + } + const hexStr = hexb.toString("hex"); + assert.strictEqual( + hexStr, + "000102030405060708090a0b0c0d0e0f" + + "101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f" + + "303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f" + + "505152535455565758595a5b5c5d5e5f" + + "606162636465666768696a6b6c6d6e6f" + + "707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f" + + "909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + ); + + const hexb2 = Buffer.from(hexStr, "hex"); + for (let i = 0; i < 256; i++) { + assert.strictEqual(hexb2[i], hexb[i]); + } + } + + // Test single hex character is discarded. + assert.strictEqual(Buffer.from("A", "hex").length, 0); + + // Test that if a trailing character is discarded, rest of string is processed. + assert.deepStrictEqual(Buffer.from("Abx", "hex"), Buffer.from("Ab", "hex")); + + // Test single base64 char encodes as 0. + assert.strictEqual(Buffer.from("A", "base64").length, 0); + + { + // Test an invalid slice end. + const b = Buffer.from([1, 2, 3, 4, 5]); + const b2 = b.toString("hex", 1, 10000); + const b3 = b.toString("hex", 1, 5); + const b4 = b.toString("hex", 1); + assert.strictEqual(b2, b3); + assert.strictEqual(b2, b4); + } + + function buildBuffer(data) { + if (Array.isArray(data)) { + const buffer = Buffer.allocUnsafe(data.length); + data.forEach((v, k) => (buffer[k] = v)); + return buffer; + } + return null; + } + + const x = buildBuffer([0x81, 0xa3, 0x66, 0x6f, 0x6f, 0xa3, 0x62, 0x61, 0x72]); + + // assert.strictEqual(x.inspect(), "<Buffer 81 a3 66 6f 6f a3 62 61 72>"); + + { + const z = x.slice(4); + assert.strictEqual(z.length, 5); + assert.strictEqual(z[0], 0x6f); + assert.strictEqual(z[1], 0xa3); + assert.strictEqual(z[2], 0x62); + assert.strictEqual(z[3], 0x61); + assert.strictEqual(z[4], 0x72); + } + + { + const z = x.slice(0); + assert.strictEqual(z.length, x.length); + } + + { + const z = x.slice(0, 4); + assert.strictEqual(z.length, 4); + assert.strictEqual(z[0], 0x81); + assert.strictEqual(z[1], 0xa3); + } + + { + const z = x.slice(0, 9); + assert.strictEqual(z.length, 9); + } + + { + const z = x.slice(1, 4); + assert.strictEqual(z.length, 3); + assert.strictEqual(z[0], 0xa3); + } + + { + const z = x.slice(2, 4); + assert.strictEqual(z.length, 2); + assert.strictEqual(z[0], 0x66); + assert.strictEqual(z[1], 0x6f); + } + + ["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach((encoding) => { + const b = Buffer.allocUnsafe(10); + b.write("あいうえお", encoding); + assert.strictEqual(b.toString(encoding), "あいうえお"); + }); + + ["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach((encoding) => { + const b = Buffer.allocUnsafe(11); + b.write("あいうえお", 1, encoding); + assert.strictEqual(b.toString(encoding, 1), "あいうえお"); + }); + + { + // latin1 encoding should write only one byte per character. + const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]); + let s = String.fromCharCode(0xffff); + b.write(s, 0, "latin1"); + assert.strictEqual(b[0], 0xff); + assert.strictEqual(b[1], 0xad); + assert.strictEqual(b[2], 0xbe); + assert.strictEqual(b[3], 0xef); + s = String.fromCharCode(0xaaee); + b.write(s, 0, "latin1"); + assert.strictEqual(b[0], 0xee); + assert.strictEqual(b[1], 0xad); + assert.strictEqual(b[2], 0xbe); + assert.strictEqual(b[3], 0xef); + } + + { + // Binary encoding should write only one byte per character. + const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]); + let s = String.fromCharCode(0xffff); + b.write(s, 0, "latin1"); + assert.strictEqual(b[0], 0xff); + assert.strictEqual(b[1], 0xad); + assert.strictEqual(b[2], 0xbe); + assert.strictEqual(b[3], 0xef); + s = String.fromCharCode(0xaaee); + b.write(s, 0, "latin1"); + assert.strictEqual(b[0], 0xee); + assert.strictEqual(b[1], 0xad); + assert.strictEqual(b[2], 0xbe); + assert.strictEqual(b[3], 0xef); + } + + { + // https://github.com/nodejs/node-v0.x-archive/pull/1210 + // Test UTF-8 string includes null character + let buf = Buffer.from("\0"); + assert.strictEqual(buf.length, 1); + buf = Buffer.from("\0\0"); + assert.strictEqual(buf.length, 2); + } + + { + const buf = Buffer.allocUnsafe(2); + assert.strictEqual(buf.write(""), 0); // 0bytes + assert.strictEqual(buf.write("\0"), 1); // 1byte (v8 adds null terminator) + assert.strictEqual(buf.write("a\0"), 2); // 1byte * 2 + assert.strictEqual(buf.write("あ"), 0); // 3bytes + assert.strictEqual(buf.write("\0あ"), 1); // 1byte + 3bytes + assert.strictEqual(buf.write("\0\0あ"), 2); // 1byte * 2 + 3bytes + } + + { + const buf = Buffer.allocUnsafe(10); + assert.strictEqual(buf.write("あいう"), 9); // 3bytes * 3 (v8 adds null term.) + assert.strictEqual(buf.write("あいう\0"), 10); // 3bytes * 3 + 1byte + } + + { + // https://github.com/nodejs/node-v0.x-archive/issues/243 + // Test write() with maxLength + const buf = Buffer.allocUnsafe(4); + buf.fill(0xff); + assert.strictEqual(buf.write("abcd", 1, 2, "utf8"), 2); + assert.strictEqual(buf[0], 0xff); + assert.strictEqual(buf[1], 0x61); + assert.strictEqual(buf[2], 0x62); + assert.strictEqual(buf[3], 0xff); + + buf.fill(0xff); + assert.strictEqual(buf.write("abcd", 1, 4), 3); + assert.strictEqual(buf[0], 0xff); + assert.strictEqual(buf[1], 0x61); + assert.strictEqual(buf[2], 0x62); + assert.strictEqual(buf[3], 0x63); + + buf.fill(0xff); + assert.strictEqual(buf.write("abcd", 1, 2, "utf8"), 2); + assert.strictEqual(buf[0], 0xff); + assert.strictEqual(buf[1], 0x61); + assert.strictEqual(buf[2], 0x62); + assert.strictEqual(buf[3], 0xff); + + buf.fill(0xff); + assert.strictEqual(buf.write("abcdef", 1, 2, "hex"), 2); + assert.strictEqual(buf[0], 0xff); + assert.strictEqual(buf[1], 0xab); + assert.strictEqual(buf[2], 0xcd); + assert.strictEqual(buf[3], 0xff); + + ["ucs2", "ucs-2", "utf16le", "utf-16le"].forEach((encoding) => { + buf.fill(0xff); + assert.strictEqual(buf.write("abcd", 0, 2, encoding), 2); + assert.strictEqual(buf[0], 0x61); + assert.strictEqual(buf[1], 0x00); + assert.strictEqual(buf[2], 0xff); + assert.strictEqual(buf[3], 0xff); + }); + } + + { + // Test offset returns are correct + const b = Buffer.allocUnsafe(16); + assert.strictEqual(b.writeUInt32LE(0, 0), 4); + assert.strictEqual(b.writeUInt16LE(0, 4), 6); + assert.strictEqual(b.writeUInt8(0, 6), 7); + assert.strictEqual(b.writeInt8(0, 7), 8); + assert.strictEqual(b.writeDoubleLE(0, 8), 16); + } + + { + // Test unmatched surrogates not producing invalid utf8 output + // ef bf bd = utf-8 representation of unicode replacement character + // see https://codereview.chromium.org/121173009/ + const buf = Buffer.from("ab\ud800cd", "utf8"); + assert.strictEqual(buf[0], 0x61); + assert.strictEqual(buf[1], 0x62); + assert.strictEqual(buf[2], 0xef); + assert.strictEqual(buf[3], 0xbf); + assert.strictEqual(buf[4], 0xbd); + assert.strictEqual(buf[5], 0x63); + assert.strictEqual(buf[6], 0x64); + } + + { + // Test for buffer overrun + const buf = Buffer.from([0, 0, 0, 0, 0]); // length: 5 + const sub = buf.slice(0, 4); // length: 4 + assert.strictEqual(sub.write("12345", "latin1"), 4); + assert.strictEqual(buf[4], 0); + assert.strictEqual(sub.write("12345", "binary"), 4); + assert.strictEqual(buf[4], 0); + } + + { + // Test alloc with fill option + const buf = Buffer.alloc(5, "800A", "hex"); + assert.strictEqual(buf[0], 128); + assert.strictEqual(buf[1], 10); + assert.strictEqual(buf[2], 128); + assert.strictEqual(buf[3], 10); + assert.strictEqual(buf[4], 128); + } + + // Check for fractional length args, junk length args, etc. + // https://github.com/joyent/node/issues/1758 + + // Call .fill() first, stops valgrind warning about uninitialized memory reads. + Buffer.allocUnsafe(3.3).fill().toString(); + // Throws bad argument error in commit 43cb4ec + Buffer.alloc(3.3).fill().toString(); + assert.strictEqual(Buffer.allocUnsafe(3.3).length, 3); + assert.strictEqual(Buffer.from({ length: 3.3 }).length, 3); + assert.strictEqual(Buffer.from({ length: "BAM" }).length, 0); + + // Make sure that strings are not coerced to numbers. + assert.strictEqual(Buffer.from("99").length, 2); + assert.strictEqual(Buffer.from("13.37").length, 5); + + // Ensure that the length argument is respected. + ["ascii", "utf8", "hex", "base64", "latin1", "binary"].forEach((enc) => { + assert.strictEqual(Buffer.allocUnsafe(1).write("aaaaaa", 0, 1, enc), 1); + }); + + { + // Regression test, guard against buffer overrun in the base64 decoder. + const a = Buffer.allocUnsafe(3); + const b = Buffer.from("xxx"); + a.write("aaaaaaaa", "base64"); + assert.strictEqual(b.toString(), "xxx"); + } + + // issue GH-3416 + Buffer.from(Buffer.allocUnsafe(0), 0, 0); + + // issue GH-5587 + assert.throws(() => Buffer.alloc(8).writeFloatLE(0, 5), outOfRangeError); + assert.throws(() => Buffer.alloc(16).writeDoubleLE(0, 9), outOfRangeError); + + // Attempt to overflow buffers, similar to previous bug in array buffers + assert.throws( + () => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), + outOfRangeError, + ); + assert.throws( + () => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), + outOfRangeError, + ); + + // Ensure negative values can't get past offset + assert.throws( + () => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), + outOfRangeError, + ); + assert.throws( + () => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), + outOfRangeError, + ); + + // Test for common write(U)IntLE/BE + { + let buf = Buffer.allocUnsafe(3); + buf.writeUIntLE(0x123456, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0x56, 0x34, 0x12]); + assert.strictEqual(buf.readUIntLE(0, 3), 0x123456); + + buf.fill(0xff); + buf.writeUIntBE(0x123456, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56]); + assert.strictEqual(buf.readUIntBE(0, 3), 0x123456); + + buf.fill(0xff); + buf.writeIntLE(0x123456, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0x56, 0x34, 0x12]); + assert.strictEqual(buf.readIntLE(0, 3), 0x123456); + + buf.fill(0xff); + buf.writeIntBE(0x123456, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56]); + assert.strictEqual(buf.readIntBE(0, 3), 0x123456); + + buf.fill(0xff); + buf.writeIntLE(-0x123456, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0xaa, 0xcb, 0xed]); + assert.strictEqual(buf.readIntLE(0, 3), -0x123456); + + buf.fill(0xff); + buf.writeIntBE(-0x123456, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0xed, 0xcb, 0xaa]); + assert.strictEqual(buf.readIntBE(0, 3), -0x123456); + + buf.fill(0xff); + buf.writeIntLE(-0x123400, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0x00, 0xcc, 0xed]); + assert.strictEqual(buf.readIntLE(0, 3), -0x123400); + + buf.fill(0xff); + buf.writeIntBE(-0x123400, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0xed, 0xcc, 0x00]); + assert.strictEqual(buf.readIntBE(0, 3), -0x123400); + + buf.fill(0xff); + buf.writeIntLE(-0x120000, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0x00, 0x00, 0xee]); + assert.strictEqual(buf.readIntLE(0, 3), -0x120000); + + buf.fill(0xff); + buf.writeIntBE(-0x120000, 0, 3); + assert.deepStrictEqual(buf.toJSON().data, [0xee, 0x00, 0x00]); + assert.strictEqual(buf.readIntBE(0, 3), -0x120000); + + buf = Buffer.allocUnsafe(5); + buf.writeUIntLE(0x1234567890, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0x90, 0x78, 0x56, 0x34, 0x12]); + assert.strictEqual(buf.readUIntLE(0, 5), 0x1234567890); + + buf.fill(0xff); + buf.writeUIntBE(0x1234567890, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56, 0x78, 0x90]); + assert.strictEqual(buf.readUIntBE(0, 5), 0x1234567890); + + buf.fill(0xff); + buf.writeIntLE(0x1234567890, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0x90, 0x78, 0x56, 0x34, 0x12]); + assert.strictEqual(buf.readIntLE(0, 5), 0x1234567890); + + buf.fill(0xff); + buf.writeIntBE(0x1234567890, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56, 0x78, 0x90]); + assert.strictEqual(buf.readIntBE(0, 5), 0x1234567890); + + buf.fill(0xff); + buf.writeIntLE(-0x1234567890, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0x70, 0x87, 0xa9, 0xcb, 0xed]); + assert.strictEqual(buf.readIntLE(0, 5), -0x1234567890); + + buf.fill(0xff); + buf.writeIntBE(-0x1234567890, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0xed, 0xcb, 0xa9, 0x87, 0x70]); + assert.strictEqual(buf.readIntBE(0, 5), -0x1234567890); + + buf.fill(0xff); + buf.writeIntLE(-0x0012000000, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0x00, 0x00, 0x00, 0xee, 0xff]); + assert.strictEqual(buf.readIntLE(0, 5), -0x0012000000); + + buf.fill(0xff); + buf.writeIntBE(-0x0012000000, 0, 5); + assert.deepStrictEqual(buf.toJSON().data, [0xff, 0xee, 0x00, 0x00, 0x00]); + assert.strictEqual(buf.readIntBE(0, 5), -0x0012000000); + } + + // Regression test for https://github.com/nodejs/node-v0.x-archive/issues/5482: + // should throw but not assert in C++ land. + assert.throws(() => Buffer.from("", "buffer"), { + code: "ERR_UNKNOWN_ENCODING", + name: "TypeError", + message: "Unknown encoding: buffer", + }); + + // Regression test for https://github.com/nodejs/node-v0.x-archive/issues/6111. + // Constructing a buffer from another buffer should a) work, and b) not corrupt + // the source buffer. + { + const a = [...Array(128).keys()]; // [0, 1, 2, 3, ... 126, 127] + const b = Buffer.from(a); + const c = Buffer.from(b); + assert.strictEqual(b.length, a.length); + assert.strictEqual(c.length, a.length); + for (let i = 0, k = a.length; i < k; ++i) { + assert.strictEqual(a[i], i); + assert.strictEqual(b[i], i); + assert.strictEqual(c[i], i); + } + } + + // if (common.hasCrypto) { + // eslint-disable-line node-core/crypto-check + // Test truncation after decode + const crypto = require("crypto"); + + const b1 = Buffer.from("YW55=======", "base64"); + const b2 = Buffer.from("YW55", "base64"); + + assert.strictEqual( + crypto.createHash("sha1").update(b1).digest("hex"), + crypto.createHash("sha1").update(b2).digest("hex"), + ); + // } else { + // common.printSkipMessage("missing crypto"); + // } + + const ps = Buffer.poolSize; + Buffer.poolSize = 0; + assert(Buffer.allocUnsafe(1).parent instanceof ArrayBuffer); + Buffer.poolSize = ps; + + assert.throws(() => Buffer.allocUnsafe(10).copy(), { + code: "ERR_INVALID_ARG_TYPE", + name: "TypeError", + message: + 'The "target" argument must be an instance of Buffer or ' + + "Uint8Array. Received undefined", + }); + + assert.throws(() => Buffer.from(), { + name: "TypeError", + message: + "The first argument must be of type string or an instance of " + + "Buffer, ArrayBuffer, or Array or an Array-like Object. Received undefined", + }); + assert.throws(() => Buffer.from(null), { + name: "TypeError", + message: + "The first argument must be of type string or an instance of " + + "Buffer, ArrayBuffer, or Array or an Array-like Object. Received null", + }); + + // Test prototype getters don't throw + assert.strictEqual(Buffer.prototype.parent, undefined); + assert.strictEqual(Buffer.prototype.offset, undefined); + assert.strictEqual(SlowBuffer.prototype.parent, undefined); + assert.strictEqual(SlowBuffer.prototype.offset, undefined); + + { + // Test that large negative Buffer length inputs don't affect the pool offset. + // Use the fromArrayLike() variant here because it's more lenient + // about its input and passes the length directly to allocate(). + assert.deepStrictEqual( + Buffer.from({ length: -Buffer.poolSize }), + Buffer.from(""), + ); + assert.deepStrictEqual(Buffer.from({ length: -100 }), Buffer.from("")); + + // Check pool offset after that by trying to write string into the pool. + Buffer.from("abc"); + } + + // Test that ParseArrayIndex handles full uint32 + { + const errMsg = common.expectsError({ + code: "ERR_BUFFER_OUT_OF_BOUNDS", + name: "RangeError", + message: '"offset" is outside of buffer bounds', + }); + assert.throws(() => Buffer.from(new ArrayBuffer(0), -1 >>> 0), errMsg); + } + + // ParseArrayIndex() should reject values that don't fit in a 32 bits size_t. + assert.throws(() => { + const a = Buffer.alloc(1); + const b = Buffer.alloc(1); + a.copy(b, 0, 0x100000000, 0x100000001); + }, outOfRangeError); + + // Unpooled buffer (replaces SlowBuffer) + { + const ubuf = Buffer.allocUnsafeSlow(10); + assert(ubuf); + assert(ubuf.buffer); + assert.strictEqual(ubuf.buffer.byteLength, 10); + } + + // Regression test to verify that an empty ArrayBuffer does not throw. + Buffer.from(new ArrayBuffer()); + + // Test that ArrayBuffer from a different context is detected correctly. + const arrayBuf = vm.runInNewContext("new ArrayBuffer()"); + Buffer.from(arrayBuf); + Buffer.from({ buffer: arrayBuf }); + + assert.throws( + () => Buffer.alloc({ valueOf: () => 1 }), + /"size" argument must be of type number/, + ); + assert.throws( + () => Buffer.alloc({ valueOf: () => -1 }), + /"size" argument must be of type number/, + ); + + assert.strictEqual( + Buffer.prototype.toLocaleString, + Buffer.prototype.toString, + ); + { + const buf = Buffer.from("test"); + assert.strictEqual(buf.toLocaleString(), buf.toString()); + } + + assert.throws( + () => { + Buffer.alloc(0x1000, "This is not correctly encoded", "hex"); + }, + { + code: "ERR_INVALID_ARG_VALUE", + name: "TypeError", + }, + ); + + assert.throws( + () => { + Buffer.alloc(0x1000, "c", "hex"); + }, + { + code: "ERR_INVALID_ARG_VALUE", + name: "TypeError", + }, + ); + + assert.throws( + () => { + Buffer.alloc(1, Buffer.alloc(0)); + }, + { + code: "ERR_INVALID_ARG_VALUE", + name: "TypeError", + }, + ); + + assert.throws( + () => { + Buffer.alloc(40, "x", 20); + }, + { + code: "ERR_INVALID_ARG_TYPE", + name: "TypeError", + }, + ); +}); + it("Buffer.toJSON()", () => { expect(JSON.stringify(Buffer.from("hello"))).toBe( JSON.stringify({ @@ -1003,3 +2293,395 @@ it("new Buffer() (Node.js test/test-buffer-new.js)", () => { // Test an array like entry with the length set to NaN. expect(Buffer.from({ length: NaN })).toStrictEqual(Buffer.alloc(0)); }); + +it("Buffer.fill (Node.js tests)", () => { + "use strict"; + const SIZE = 28; + + const buf1 = Buffer.allocUnsafe(SIZE); + const buf2 = Buffer.allocUnsafe(SIZE); + + function assertEqual(a, b) { + expect(a).toEqual(b); + } + + // Default encoding + testBufs("abc"); + testBufs("\u0222aa"); + testBufs("a\u0234b\u0235c\u0236"); + testBufs("abc", 4); + testBufs("abc", 5); + testBufs("abc", SIZE); + testBufs("\u0222aa", 2); + testBufs("\u0222aa", 8); + testBufs("a\u0234b\u0235c\u0236", 4); + testBufs("a\u0234b\u0235c\u0236", 12); + testBufs("abc", 4, 1); + testBufs("abc", 5, 1); + testBufs("\u0222aa", 8, 1); + testBufs("a\u0234b\u0235c\u0236", 4, 1); + testBufs("a\u0234b\u0235c\u0236", 12, 1); + + // UTF8 + testBufs("abc", "utf8"); + testBufs("\u0222aa", "utf8"); + testBufs("a\u0234b\u0235c\u0236", "utf8"); + testBufs("abc", 4, "utf8"); + testBufs("abc", 5, "utf8"); + testBufs("abc", SIZE, "utf8"); + testBufs("\u0222aa", 2, "utf8"); + testBufs("\u0222aa", 8, "utf8"); + testBufs("a\u0234b\u0235c\u0236", 4, "utf8"); + testBufs("a\u0234b\u0235c\u0236", 12, "utf8"); + testBufs("abc", 4, 1, "utf8"); + testBufs("abc", 5, 1, "utf8"); + testBufs("\u0222aa", 8, 1, "utf8"); + testBufs("a\u0234b\u0235c\u0236", 4, 1, "utf8"); + testBufs("a\u0234b\u0235c\u0236", 12, 1, "utf8"); + assertEqual(Buffer.allocUnsafe(1).fill(0).fill("\u0222")[0], 0xc8); + + // BINARY + testBufs("abc", "binary"); + testBufs("\u0222aa", "binary"); + testBufs("a\u0234b\u0235c\u0236", "binary"); + testBufs("abc", 4, "binary"); + testBufs("abc", 5, "binary"); + testBufs("abc", SIZE, "binary"); + testBufs("\u0222aa", 2, "binary"); + testBufs("\u0222aa", 8, "binary"); + testBufs("a\u0234b\u0235c\u0236", 4, "binary"); + testBufs("a\u0234b\u0235c\u0236", 12, "binary"); + testBufs("abc", 4, 1, "binary"); + testBufs("abc", 5, 1, "binary"); + testBufs("\u0222aa", 8, 1, "binary"); + testBufs("a\u0234b\u0235c\u0236", 4, 1, "binary"); + testBufs("a\u0234b\u0235c\u0236", 12, 1, "binary"); + + // LATIN1 + testBufs("abc", "latin1"); + testBufs("\u0222aa", "latin1"); + testBufs("a\u0234b\u0235c\u0236", "latin1"); + testBufs("abc", 4, "latin1"); + testBufs("abc", 5, "latin1"); + testBufs("abc", SIZE, "latin1"); + testBufs("\u0222aa", 2, "latin1"); + testBufs("\u0222aa", 8, "latin1"); + testBufs("a\u0234b\u0235c\u0236", 4, "latin1"); + testBufs("a\u0234b\u0235c\u0236", 12, "latin1"); + testBufs("abc", 4, 1, "latin1"); + testBufs("abc", 5, 1, "latin1"); + testBufs("\u0222aa", 8, 1, "latin1"); + testBufs("a\u0234b\u0235c\u0236", 4, 1, "latin1"); + testBufs("a\u0234b\u0235c\u0236", 12, 1, "latin1"); + + // UCS2 + testBufs("abc", "ucs2"); + testBufs("\u0222aa", "ucs2"); + testBufs("a\u0234b\u0235c\u0236", "ucs2"); + testBufs("abc", 4, "ucs2"); + testBufs("abc", SIZE, "ucs2"); + testBufs("\u0222aa", 2, "ucs2"); + testBufs("\u0222aa", 8, "ucs2"); + testBufs("a\u0234b\u0235c\u0236", 4, "ucs2"); + testBufs("a\u0234b\u0235c\u0236", 12, "ucs2"); + testBufs("abc", 4, 1, "ucs2"); + testBufs("abc", 5, 1, "ucs2"); + testBufs("\u0222aa", 8, 1, "ucs2"); + testBufs("a\u0234b\u0235c\u0236", 4, 1, "ucs2"); + testBufs("a\u0234b\u0235c\u0236", 12, 1, "ucs2"); + assertEqual(Buffer.allocUnsafe(1).fill("\u0222", "ucs2")[0], 0x22); + + // HEX + testBufs("616263", "hex"); + testBufs("c8a26161", "hex"); + testBufs("61c8b462c8b563c8b6", "hex"); + testBufs("616263", 4, "hex"); + testBufs("616263", 5, "hex"); + testBufs("616263", SIZE, "hex"); + testBufs("c8a26161", 2, "hex"); + testBufs("c8a26161", 8, "hex"); + testBufs("61c8b462c8b563c8b6", 4, "hex"); + testBufs("61c8b462c8b563c8b6", 12, "hex"); + testBufs("616263", 4, 1, "hex"); + testBufs("616263", 5, 1, "hex"); + testBufs("c8a26161", 8, 1, "hex"); + testBufs("61c8b462c8b563c8b6", 4, 1, "hex"); + testBufs("61c8b462c8b563c8b6", 12, 1, "hex"); + + expect(() => { + const buf = Buffer.allocUnsafe(SIZE); + + buf.fill("yKJh", "hex"); + }).toThrow(); + + expect(() => { + const buf = Buffer.allocUnsafe(SIZE); + + buf.fill("\u0222", "hex"); + }).toThrow(); + + // BASE64 + testBufs("YWJj", "base64"); + testBufs("yKJhYQ==", "base64"); + testBufs("Yci0Ysi1Y8i2", "base64"); + testBufs("YWJj", 4, "base64"); + testBufs("YWJj", SIZE, "base64"); + testBufs("yKJhYQ==", 2, "base64"); + testBufs("yKJhYQ==", 8, "base64"); + testBufs("Yci0Ysi1Y8i2", 4, "base64"); + testBufs("Yci0Ysi1Y8i2", 12, "base64"); + testBufs("YWJj", 4, 1, "base64"); + testBufs("YWJj", 5, 1, "base64"); + testBufs("yKJhYQ==", 8, 1, "base64"); + testBufs("Yci0Ysi1Y8i2", 4, 1, "base64"); + testBufs("Yci0Ysi1Y8i2", 12, 1, "base64"); + + // BASE64URL + testBufs("YWJj", "base64url"); + testBufs("yKJhYQ", "base64url"); + testBufs("Yci0Ysi1Y8i2", "base64url"); + testBufs("YWJj", 4, "base64url"); + testBufs("YWJj", SIZE, "base64url"); + testBufs("yKJhYQ", 2, "base64url"); + testBufs("yKJhYQ", 8, "base64url"); + testBufs("Yci0Ysi1Y8i2", 4, "base64url"); + testBufs("Yci0Ysi1Y8i2", 12, "base64url"); + testBufs("YWJj", 4, 1, "base64url"); + testBufs("YWJj", 5, 1, "base64url"); + testBufs("yKJhYQ", 8, 1, "base64url"); + testBufs("Yci0Ysi1Y8i2", 4, 1, "base64url"); + testBufs("Yci0Ysi1Y8i2", 12, 1, "base64url"); + + // Buffer + function deepStrictEqualValues(buf, arr) { + for (const [index, value] of buf.entries()) { + expect(value).toStrictEqual(arr[index]); + } + } + + const buf2Fill = Buffer.allocUnsafe(1).fill(2); + deepStrictEqualValues(genBuffer(4, [buf2Fill]), [2, 2, 2, 2]); + deepStrictEqualValues(genBuffer(4, [buf2Fill, 1]), [0, 2, 2, 2]); + deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 3]), [0, 2, 2, 0]); + deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 1]), [0, 0, 0, 0]); + const hexBufFill = Buffer.allocUnsafe(2).fill(0).fill("0102", "hex"); + deepStrictEqualValues(genBuffer(4, [hexBufFill]), [1, 2, 1, 2]); + deepStrictEqualValues(genBuffer(4, [hexBufFill, 1]), [0, 1, 2, 1]); + deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 3]), [0, 1, 2, 0]); + deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 1]), [0, 0, 0, 0]); + + // Check exceptions + [ + [0, -1], + [0, 0, buf1.length + 1], + ["", -1], + ["", 0, buf1.length + 1], + ["", 1, -1], + ].forEach((args) => { + expect(() => buf1.fill(...args)).toThrow(); + }); + + expect(() => buf1.fill("a", 0, buf1.length, "node rocks!")).toThrow(); + + [ + ["a", 0, 0, NaN], + ["a", 0, 0, false], + ].forEach((args) => { + expect(() => buf1.fill(...args)).toThrow(); + }); + + expect(() => buf1.fill("a", 0, 0, "foo")).toThrow(); + + function genBuffer(size, args) { + const b = Buffer.allocUnsafe(size); + return b.fill(0).fill.apply(b, args); + } + + function bufReset() { + buf1.fill(0); + buf2.fill(0); + } + + // This is mostly accurate. Except write() won't write partial bytes to the + // string while fill() blindly copies bytes into memory. To account for that an + // error will be thrown if not all the data can be written, and the SIZE has + // been massaged to work with the input characters. + function writeToFill(string, offset, end, encoding) { + if (typeof offset === "string") { + encoding = offset; + offset = 0; + end = buf2.length; + } else if (typeof end === "string") { + encoding = end; + end = buf2.length; + } else if (end === undefined) { + end = buf2.length; + } + + // Should never be reached. + if (offset < 0 || end > buf2.length) throw new ERR_OUT_OF_RANGE(); + + if (end <= offset) return buf2; + + offset >>>= 0; + end >>>= 0; + expect(offset <= buf2.length).toBe(true); + + // Convert "end" to "length" (which write understands). + const length = end - offset < 0 ? 0 : end - offset; + + let wasZero = false; + do { + const written = buf2.write(string, offset, length, encoding); + offset += written; + // Safety check in case write falls into infinite loop. + if (written === 0) { + if (wasZero) + throw new Error("Could not write all data to Buffer at " + offset); + else wasZero = true; + } + } while (offset < buf2.length); + + return buf2; + } + + function testBufs(string, offset, length, encoding) { + bufReset(); + buf1.fill.apply(buf1, arguments); + // Swap bytes on BE archs for ucs2 encoding. + expect(buf1.fill.apply(buf1, arguments)).toStrictEqual( + writeToFill.apply(null, arguments), + ); + } + + // Make sure these throw. + expect(() => Buffer.allocUnsafe(8).fill("a", -1)).toThrow(); + expect(() => Buffer.allocUnsafe(8).fill("a", 0, 9)).toThrow(); + + // Make sure this doesn't hang indefinitely. + Buffer.allocUnsafe(8).fill(""); + Buffer.alloc(8, ""); + + { + const buf = Buffer.alloc(64, 10); + for (let i = 0; i < buf.length; i++) assertEqual(buf[i], 10); + + buf.fill(11, 0, buf.length >> 1); + for (let i = 0; i < buf.length >> 1; i++) assertEqual(buf[i], 11); + for (let i = (buf.length >> 1) + 1; i < buf.length; i++) + assertEqual(buf[i], 10); + + buf.fill("h"); + for (let i = 0; i < buf.length; i++) assertEqual(buf[i], "h".charCodeAt(0)); + + buf.fill(0); + for (let i = 0; i < buf.length; i++) assertEqual(buf[i], 0); + + buf.fill(null); + for (let i = 0; i < buf.length; i++) assertEqual(buf[i], 0); + + buf.fill(1, 16, 32); + for (let i = 0; i < 16; i++) assertEqual(buf[i], 0); + for (let i = 16; i < 32; i++) assertEqual(buf[i], 1); + for (let i = 32; i < buf.length; i++) assertEqual(buf[i], 0); + } + + { + const buf = Buffer.alloc(10, "abc"); + assertEqual(buf.toString(), "abcabcabca"); + buf.fill("է"); + assertEqual(buf.toString(), "էէէէէ"); + } + + // // Testing process.binding. Make sure "start" is properly checked for range + // // errors. + // assert.throws( + // () => { + // internalBinding("buffer").fill(Buffer.alloc(1), 1, -1, 0, 1); + // }, + // { code: "ERR_OUT_OF_RANGE" }, + // ); + + // Make sure "end" is properly checked, even if it's magically mangled using + // Symbol.toPrimitive. + { + expect(() => { + const end = { + [Symbol.toPrimitive]() { + return 1; + }, + }; + Buffer.alloc(1).fill(Buffer.alloc(1), 0, end); + }).toThrow(); + } + + // Testing process.binding. Make sure "end" is properly checked for range + // errors. + // assert.throws( + // () => { + // internalBinding("buffer").fill(Buffer.alloc(1), 1, 1, -2, 1); + // }, + // { code: "ERR_OUT_OF_RANGE" }, + // ); + + // Test that bypassing 'length' won't cause an abort. + expect(() => { + const buf = Buffer.from("w00t"); + Object.defineProperty(buf, "length", { + value: 1337, + enumerable: true, + }); + buf.fill(""); + }).toThrow(); + + assertEqual( + Buffer.allocUnsafeSlow(16).fill("ab", "utf16le"), + Buffer.from("61006200610062006100620061006200", "hex"), + ); + + assertEqual( + Buffer.allocUnsafeSlow(15).fill("ab", "utf16le"), + Buffer.from("610062006100620061006200610062", "hex"), + ); + + assertEqual( + Buffer.allocUnsafeSlow(16).fill("ab", "utf16le"), + Buffer.from("61006200610062006100620061006200", "hex"), + ); + assertEqual( + Buffer.allocUnsafeSlow(16).fill("a", "utf16le"), + Buffer.from("61006100610061006100610061006100", "hex"), + ); + + assertEqual( + Buffer.allocUnsafeSlow(16).fill("a", "utf16le").toString("utf16le"), + "a".repeat(8), + ); + assertEqual( + Buffer.allocUnsafeSlow(16).fill("a", "latin1").toString("latin1"), + "a".repeat(16), + ); + assertEqual( + Buffer.allocUnsafeSlow(16).fill("a", "utf8").toString("utf8"), + "a".repeat(16), + ); + + assertEqual( + Buffer.allocUnsafeSlow(16).fill("Љ", "utf16le").toString("utf16le"), + "Љ".repeat(8), + ); + assertEqual( + Buffer.allocUnsafeSlow(16).fill("Љ", "latin1").toString("latin1"), + "\t".repeat(16), + ); + assertEqual( + Buffer.allocUnsafeSlow(16).fill("Љ", "utf8").toString("utf8"), + "Љ".repeat(8), + ); + + expect(() => { + const buf = Buffer.from("a".repeat(1000)); + + buf.fill("This is not correctly encoded", "hex"); + }).toThrow(); +}); |