File
Blob: src/workerd/api/node/tests/buffer-nodejs-test.js
| 1 | // Copyright (c) 2017-2022 Cloudflare, Inc. |
| 2 | // Licensed under the Apache 2.0 license found in the LICENSE file or at: |
| 3 | // https://opensource.org/licenses/Apache-2.0 |
| 4 | // |
| 5 | // Adapted from Node.js. Copyright Joyent, Inc. and other Node contributors. |
| 6 | // |
| 7 | // Permission is hereby granted, free of charge, to any person obtaining a |
| 8 | // copy of this software and associated documentation files (the |
| 9 | // "Software"), to deal in the Software without restriction, including |
| 10 | // without limitation the rights to use, copy, modify, merge, publish, |
| 11 | // distribute, sublicense, and/or sell copies of the Software, and to permit |
| 12 | // persons to whom the Software is furnished to do so, subject to the |
| 13 | // following conditions: |
| 14 | // |
| 15 | // The above copyright notice and this permission notice shall be included |
| 16 | // in all copies or substantial portions of the Software. |
| 17 | // |
| 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| 21 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| 22 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| 23 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| 24 | // USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | |
| 26 | import { |
| 27 | deepStrictEqual, |
| 28 | notDeepStrictEqual, |
| 29 | notStrictEqual, |
| 30 | ok, |
| 31 | strictEqual, |
| 32 | throws, |
| 33 | } from 'node:assert'; |
| 34 | import util from 'node:util'; |
| 35 | |
| 36 | import { |
| 37 | Buffer, |
| 38 | File, |
| 39 | SlowBuffer, |
| 40 | constants, |
| 41 | isAscii, |
| 42 | isUtf8, |
| 43 | kMaxLength, |
| 44 | kStringMaxLength, |
| 45 | transcode, |
| 46 | } from 'node:buffer'; |
| 47 | |
| 48 | import * as buffer from 'node:buffer'; |
| 49 | if ( |
| 50 | buffer.Buffer !== Buffer || |
| 51 | buffer.SlowBuffer !== SlowBuffer || |
| 52 | buffer.kMaxLength !== kMaxLength || |
| 53 | buffer.kStringMaxLength !== kStringMaxLength || |
| 54 | buffer.constants !== constants |
| 55 | ) { |
| 56 | throw new Error('Incorrect default exports'); |
| 57 | } |
| 58 | |
| 59 | const { MAX_LENGTH, MAX_STRING_LENGTH } = constants; |
| 60 | |
| 61 | export const simpleAlloc = { |
| 62 | // test-buffer-alloc.js |
| 63 | test(ctrl, env, ctx) { |
| 64 | const b = Buffer.allocUnsafe(1024); |
| 65 | strictEqual(b.length, 1024); |
| 66 | |
| 67 | b[0] = -1; |
| 68 | strictEqual(b[0], 255); |
| 69 | |
| 70 | for (let i = 0; i < 1024; i++) { |
| 71 | b[i] = i % 256; |
| 72 | } |
| 73 | |
| 74 | for (let i = 0; i < 1024; i++) { |
| 75 | strictEqual(i % 256, b[i]); |
| 76 | } |
| 77 | |
| 78 | const c = Buffer.allocUnsafe(512); |
| 79 | strictEqual(c.length, 512); |
| 80 | |
| 81 | const d = Buffer.from([]); |
| 82 | strictEqual(d.length, 0); |
| 83 | }, |
| 84 | }; |
| 85 | |
| 86 | export const offsetProperties = { |
| 87 | test(ctrl, env, ctx) { |
| 88 | const b = Buffer.alloc(128); |
| 89 | strictEqual(b.length, 128); |
| 90 | strictEqual(b.byteOffset, 0); |
| 91 | strictEqual(b.offset, 0); |
| 92 | }, |
| 93 | }; |
| 94 | |
| 95 | export const bufferFromUint8Array = { |
| 96 | test(ctrl, env, ctx) { |
| 97 | { |
| 98 | const ui8 = new Uint8Array(4).fill(42); |
| 99 | const e = Buffer.from(ui8); |
| 100 | for (const [index, value] of e.entries()) { |
| 101 | strictEqual(value, ui8[index]); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | { |
| 106 | const ui8 = new Uint8Array(4).fill(42); |
| 107 | const e = Buffer(ui8); |
| 108 | for (const [key, value] of e.entries()) { |
| 109 | strictEqual(value, ui8[key]); |
| 110 | } |
| 111 | } |
| 112 | }, |
| 113 | }; |
| 114 | |
| 115 | export const bufferFromUint32Array = { |
| 116 | test(ctrl, env, ctx) { |
| 117 | { |
| 118 | const ui32 = new Uint32Array(4).fill(42); |
| 119 | const e = Buffer.from(ui32); |
| 120 | for (const [index, value] of e.entries()) { |
| 121 | strictEqual(value, ui32[index]); |
| 122 | } |
| 123 | } |
| 124 | { |
| 125 | const ui32 = new Uint32Array(4).fill(42); |
| 126 | const e = Buffer(ui32); |
| 127 | for (const [key, value] of e.entries()) { |
| 128 | strictEqual(value, ui32[key]); |
| 129 | } |
| 130 | } |
| 131 | }, |
| 132 | }; |
| 133 | |
| 134 | export const invalidEncodingForToString = { |
| 135 | test(ctrl, env, ctx) { |
| 136 | const b = Buffer.allocUnsafe(10); |
| 137 | // Test invalid encoding for Buffer.toString |
| 138 | throws(() => b.toString('invalid'), /Unknown encoding: invalid/); |
| 139 | // // Invalid encoding for Buffer.write |
| 140 | throws( |
| 141 | () => b.write('test string', 0, 5, 'invalid'), |
| 142 | /Unknown encoding: invalid/ |
| 143 | ); |
| 144 | // Unsupported arguments for Buffer.write |
| 145 | |
| 146 | throws(() => b.write('test', 'utf8', 0), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 147 | }, |
| 148 | }; |
| 149 | |
| 150 | export const toStringWithUndefinedEncoding = { |
| 151 | test(ctrl, env, ctx) { |
| 152 | // Test that Buffer.toString with undefined encoding defaults to utf8 |
| 153 | const buf = Buffer.from('hello world'); |
| 154 | strictEqual(buf.toString(undefined), 'hello world'); |
| 155 | strictEqual(buf.toString(undefined), buf.toString('utf8')); |
| 156 | |
| 157 | // Test with UTF-8 characters |
| 158 | const utf8Buf = Buffer.from('¡hέlló wôrld!'); |
| 159 | strictEqual(utf8Buf.toString(undefined), '¡hέlló wôrld!'); |
| 160 | strictEqual(utf8Buf.toString(undefined), utf8Buf.toString('utf8')); |
| 161 | |
| 162 | // Test with start and end parameters |
| 163 | const sliceBuf = Buffer.from('hello world'); |
| 164 | strictEqual(sliceBuf.toString(undefined, 0, 5), 'hello'); |
| 165 | strictEqual(sliceBuf.toString(undefined, 6), 'world'); |
| 166 | strictEqual( |
| 167 | sliceBuf.toString(undefined, 0, 5), |
| 168 | sliceBuf.toString('utf8', 0, 5) |
| 169 | ); |
| 170 | }, |
| 171 | }; |
| 172 | |
| 173 | export const zeroLengthBuffers = { |
| 174 | test(ctrl, env, ctx) { |
| 175 | Buffer.from(''); |
| 176 | Buffer.from('', 'ascii'); |
| 177 | Buffer.from('', 'latin1'); |
| 178 | Buffer.alloc(0); |
| 179 | Buffer.allocUnsafe(0); |
| 180 | new Buffer(''); |
| 181 | new Buffer('', 'ascii'); |
| 182 | new Buffer('', 'latin1'); |
| 183 | new Buffer('', 'binary'); |
| 184 | Buffer(0); |
| 185 | }, |
| 186 | }; |
| 187 | |
| 188 | export const outOfBoundsWrites = { |
| 189 | test(ctrl, env, ctx) { |
| 190 | const outOfRangeError = { |
| 191 | code: 'ERR_OUT_OF_RANGE', |
| 192 | name: 'RangeError', |
| 193 | }; |
| 194 | |
| 195 | const b = Buffer.alloc(1024); |
| 196 | |
| 197 | // Try to write a 0-length string beyond the end of b |
| 198 | throws(() => b.write('', 2048), outOfRangeError); |
| 199 | |
| 200 | // Throw when writing to negative offset |
| 201 | throws(() => b.write('a', -1), outOfRangeError); |
| 202 | |
| 203 | // Throw when writing past bounds from the pool |
| 204 | throws(() => b.write('a', 2048), outOfRangeError); |
| 205 | |
| 206 | // Throw when writing to negative offset |
| 207 | throws(() => b.write('a', -1), outOfRangeError); |
| 208 | |
| 209 | // Try to copy 0 bytes worth of data into an empty buffer |
| 210 | b.copy(Buffer.alloc(0), 0, 0, 0); |
| 211 | |
| 212 | // Try to copy 0 bytes past the end of the target buffer |
| 213 | b.copy(Buffer.alloc(0), 1, 1, 1); |
| 214 | b.copy(Buffer.alloc(1), 1, 1, 1); |
| 215 | |
| 216 | // Try to copy 0 bytes from past the end of the source buffer |
| 217 | b.copy(Buffer.alloc(1), 0, 2048, 2048); |
| 218 | |
| 219 | Buffer.alloc(1).write('', 1, 0); |
| 220 | }, |
| 221 | }; |
| 222 | |
| 223 | export const smartDefaults = { |
| 224 | test(ctrl, env, ctx) { |
| 225 | const writeTest = Buffer.from('abcdes'); |
| 226 | writeTest.write('n', 'ascii'); |
| 227 | throws(() => writeTest.write('o', '1', 'ascii'), { |
| 228 | code: 'ERR_INVALID_ARG_TYPE', |
| 229 | }); |
| 230 | writeTest.write('o', 1, 'ascii'); |
| 231 | writeTest.write('d', 2, 'ascii'); |
| 232 | writeTest.write('e', 3, 'ascii'); |
| 233 | writeTest.write('j', 4, 'ascii'); |
| 234 | strictEqual(writeTest.toString(), 'nodejs'); |
| 235 | }, |
| 236 | }; |
| 237 | |
| 238 | export const asciiSlice = { |
| 239 | test(ctrl, env, ctx) { |
| 240 | const b = Buffer.alloc(1024); |
| 241 | |
| 242 | { |
| 243 | const asciiString = 'hello world'; |
| 244 | |
| 245 | for (let i = 0; i < asciiString.length; i++) { |
| 246 | b[i] = asciiString.charCodeAt(i); |
| 247 | } |
| 248 | const asciiSlice = b.toString('ascii', 0, asciiString.length); |
| 249 | strictEqual(asciiString, asciiSlice); |
| 250 | } |
| 251 | |
| 252 | { |
| 253 | const asciiString = 'hello world'; |
| 254 | const offset = 100; |
| 255 | |
| 256 | strictEqual(asciiString.length, b.write(asciiString, offset, 'ascii')); |
| 257 | const asciiSlice = b.toString( |
| 258 | 'ascii', |
| 259 | offset, |
| 260 | offset + asciiString.length |
| 261 | ); |
| 262 | strictEqual(asciiString, asciiSlice); |
| 263 | } |
| 264 | |
| 265 | { |
| 266 | const asciiString = 'hello world'; |
| 267 | const offset = 100; |
| 268 | |
| 269 | const sliceA = b.slice(offset, offset + asciiString.length); |
| 270 | const sliceB = b.slice(offset, offset + asciiString.length); |
| 271 | for (let i = 0; i < asciiString.length; i++) { |
| 272 | strictEqual(sliceA[i], sliceB[i]); |
| 273 | } |
| 274 | } |
| 275 | }, |
| 276 | }; |
| 277 | |
| 278 | export const utf8Slice = { |
| 279 | test(ctrl, env, ctx) { |
| 280 | const b = Buffer.alloc(1024); |
| 281 | { |
| 282 | const utf8String = '¡hέlló wôrld!'; |
| 283 | const offset = 100; |
| 284 | |
| 285 | b.write(utf8String, 0, Buffer.byteLength(utf8String), 'utf8'); |
| 286 | let utf8Slice = b.toString('utf8', 0, Buffer.byteLength(utf8String)); |
| 287 | strictEqual(utf8String, utf8Slice); |
| 288 | |
| 289 | strictEqual( |
| 290 | Buffer.byteLength(utf8String), |
| 291 | b.write(utf8String, offset, 'utf8') |
| 292 | ); |
| 293 | utf8Slice = b.toString( |
| 294 | 'utf8', |
| 295 | offset, |
| 296 | offset + Buffer.byteLength(utf8String) |
| 297 | ); |
| 298 | strictEqual(utf8String, utf8Slice); |
| 299 | |
| 300 | const sliceA = b.slice(offset, offset + Buffer.byteLength(utf8String)); |
| 301 | const sliceB = b.slice(offset, offset + Buffer.byteLength(utf8String)); |
| 302 | for (let i = 0; i < Buffer.byteLength(utf8String); i++) { |
| 303 | strictEqual(sliceA[i], sliceB[i]); |
| 304 | } |
| 305 | } |
| 306 | { |
| 307 | const slice = b.slice(100, 150); |
| 308 | strictEqual(slice.length, 50); |
| 309 | for (let i = 0; i < 50; i++) { |
| 310 | strictEqual(b[100 + i], slice[i]); |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | { |
| 315 | // Make sure only top level parent propagates from allocPool |
| 316 | // (We don't actually implement pooling, this is just carried over from Node.js) |
| 317 | const b = Buffer.allocUnsafe(5); |
| 318 | const c = b.slice(0, 4); |
| 319 | const d = c.slice(0, 2); |
| 320 | strictEqual(b.parent, c.parent); |
| 321 | strictEqual(b.parent, d.parent); |
| 322 | } |
| 323 | |
| 324 | { |
| 325 | // Also from a non-pooled instance |
| 326 | const b = Buffer.allocUnsafeSlow(5); |
| 327 | const c = b.slice(0, 4); |
| 328 | const d = c.slice(0, 2); |
| 329 | strictEqual(c.parent, d.parent); |
| 330 | } |
| 331 | |
| 332 | { |
| 333 | // Bug regression test |
| 334 | const testValue = '\u00F6\u65E5\u672C\u8A9E'; // ö日本語 |
| 335 | const buffer = Buffer.allocUnsafe(32); |
| 336 | const size = buffer.write(testValue, 0, 'utf8'); |
| 337 | const slice = buffer.toString('utf8', 0, size); |
| 338 | strictEqual(slice, testValue); |
| 339 | } |
| 340 | |
| 341 | { |
| 342 | // Test triple slice |
| 343 | const a = Buffer.allocUnsafe(8); |
| 344 | for (let i = 0; i < 8; i++) a[i] = i; |
| 345 | const b = a.slice(4, 8); |
| 346 | strictEqual(b[0], 4); |
| 347 | strictEqual(b[1], 5); |
| 348 | strictEqual(b[2], 6); |
| 349 | strictEqual(b[3], 7); |
| 350 | const c = b.slice(2, 4); |
| 351 | strictEqual(c[0], 6); |
| 352 | strictEqual(c[1], 7); |
| 353 | } |
| 354 | }, |
| 355 | }; |
| 356 | |
| 357 | export const bufferFrom = { |
| 358 | test(ctrl, env, ctx) { |
| 359 | { |
| 360 | const d = Buffer.from([23, 42, 255]); |
| 361 | strictEqual(d.length, 3); |
| 362 | strictEqual(d[0], 23); |
| 363 | strictEqual(d[1], 42); |
| 364 | strictEqual(d[2], 255); |
| 365 | deepStrictEqual(d, Buffer.from(d)); |
| 366 | } |
| 367 | { |
| 368 | // Test for proper UTF-8 Encoding |
| 369 | const e = Buffer.from('über'); |
| 370 | deepStrictEqual(e, Buffer.from([195, 188, 98, 101, 114])); |
| 371 | } |
| 372 | { |
| 373 | // Test for proper ascii Encoding, length should be 4 |
| 374 | const f = Buffer.from('über', 'ascii'); |
| 375 | deepStrictEqual(f, Buffer.from([252, 98, 101, 114])); |
| 376 | } |
| 377 | ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach((encoding) => { |
| 378 | { |
| 379 | // Test for proper UTF16LE encoding, length should be 8 |
| 380 | const f = Buffer.from('über', encoding); |
| 381 | deepStrictEqual(f, Buffer.from([252, 0, 98, 0, 101, 0, 114, 0])); |
| 382 | } |
| 383 | |
| 384 | { |
| 385 | // Length should be 12 |
| 386 | const f = Buffer.from('привет', encoding); |
| 387 | deepStrictEqual( |
| 388 | f, |
| 389 | Buffer.from([63, 4, 64, 4, 56, 4, 50, 4, 53, 4, 66, 4]) |
| 390 | ); |
| 391 | strictEqual(f.toString(encoding), 'привет'); |
| 392 | } |
| 393 | |
| 394 | { |
| 395 | const f = Buffer.from([0, 0, 0, 0, 0]); |
| 396 | strictEqual(f.length, 5); |
| 397 | const size = f.write('あいうえお', encoding); |
| 398 | strictEqual(size, 4); |
| 399 | deepStrictEqual(f, Buffer.from([0x42, 0x30, 0x44, 0x30, 0x00])); |
| 400 | } |
| 401 | |
| 402 | { |
| 403 | const f = Buffer.from('\uD83D\uDC4D', 'utf-16le'); // THUMBS UP SIGN (U+1F44D) |
| 404 | strictEqual(f.length, 4); |
| 405 | deepStrictEqual(f, Buffer.from('3DD84DDC', 'hex')); |
| 406 | } |
| 407 | |
| 408 | { |
| 409 | const arrayIsh = { 0: 0, 1: 1, 2: 2, 3: 3, length: 4 }; |
| 410 | let g = Buffer.from(arrayIsh); |
| 411 | deepStrictEqual(g, Buffer.from([0, 1, 2, 3])); |
| 412 | const strArrayIsh = { 0: '0', 1: '1', 2: '2', 3: '3', length: 4 }; |
| 413 | g = Buffer.from(strArrayIsh); |
| 414 | deepStrictEqual(g, Buffer.from([0, 1, 2, 3])); |
| 415 | } |
| 416 | }); |
| 417 | |
| 418 | { |
| 419 | const checkString = 'test'; |
| 420 | |
| 421 | const check = Buffer.from(checkString); |
| 422 | |
| 423 | class MyString extends String { |
| 424 | constructor() { |
| 425 | super(checkString); |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | class MyPrimitive { |
| 430 | [Symbol.toPrimitive]() { |
| 431 | return checkString; |
| 432 | } |
| 433 | } |
| 434 | |
| 435 | class MyBadPrimitive { |
| 436 | [Symbol.toPrimitive]() { |
| 437 | return 1; |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | deepStrictEqual(Buffer.from(new String(checkString)), check); |
| 442 | deepStrictEqual(Buffer.from(new MyString()), check); |
| 443 | deepStrictEqual(Buffer.from(new MyPrimitive()), check); |
| 444 | |
| 445 | [ |
| 446 | {}, |
| 447 | new Boolean(true), |
| 448 | { |
| 449 | valueOf() { |
| 450 | return null; |
| 451 | }, |
| 452 | }, |
| 453 | { |
| 454 | valueOf() { |
| 455 | return undefined; |
| 456 | }, |
| 457 | }, |
| 458 | { valueOf: null }, |
| 459 | { __proto__: null }, |
| 460 | new Number(true), |
| 461 | new MyBadPrimitive(), |
| 462 | Symbol(), |
| 463 | 5n, |
| 464 | (one, two, three) => {}, |
| 465 | undefined, |
| 466 | null, |
| 467 | ].forEach((input) => { |
| 468 | const errObj = { |
| 469 | name: 'TypeError', |
| 470 | }; |
| 471 | throws(() => Buffer.from(input), errObj); |
| 472 | throws(() => Buffer.from(input, 'hex'), errObj); |
| 473 | }); |
| 474 | |
| 475 | Buffer.allocUnsafe(10); // Should not throw. |
| 476 | Buffer.from('deadbeaf', 'hex'); // Should not throw. |
| 477 | } |
| 478 | }, |
| 479 | }; |
| 480 | |
| 481 | export const base64 = { |
| 482 | test(ctrl, env, ctx) { |
| 483 | const base64flavors = ['base64', 'base64url']; |
| 484 | { |
| 485 | strictEqual(Buffer.from('Man').toString('base64'), 'TWFu'); |
| 486 | strictEqual(Buffer.from('Woman').toString('base64'), 'V29tYW4='); |
| 487 | strictEqual(Buffer.from('Man').toString('base64url'), 'TWFu'); |
| 488 | strictEqual(Buffer.from('Woman').toString('base64url'), 'V29tYW4'); |
| 489 | } |
| 490 | |
| 491 | { |
| 492 | const expected = [0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff]; |
| 493 | deepStrictEqual( |
| 494 | Buffer.from('//++/++/++//', 'base64'), |
| 495 | Buffer.from(expected) |
| 496 | ); |
| 497 | deepStrictEqual( |
| 498 | Buffer.from('__--_--_--__', 'base64'), |
| 499 | Buffer.from(expected) |
| 500 | ); |
| 501 | deepStrictEqual( |
| 502 | Buffer.from('//++/++/++//', 'base64url'), |
| 503 | Buffer.from(expected) |
| 504 | ); |
| 505 | deepStrictEqual( |
| 506 | Buffer.from('__--_--_--__', 'base64url'), |
| 507 | Buffer.from(expected) |
| 508 | ); |
| 509 | } |
| 510 | |
| 511 | { |
| 512 | // Test that regular and URL-safe base64 both work both ways with padding |
| 513 | const expected = [ |
| 514 | 0xff, 0xff, 0xbe, 0xff, 0xef, 0xbf, 0xfb, 0xef, 0xff, 0xfb, |
| 515 | ]; |
| 516 | deepStrictEqual( |
| 517 | Buffer.from('//++/++/++//+w==', 'base64'), |
| 518 | Buffer.from(expected) |
| 519 | ); |
| 520 | deepStrictEqual( |
| 521 | Buffer.from('//++/++/++//+w==', 'base64'), |
| 522 | Buffer.from(expected) |
| 523 | ); |
| 524 | deepStrictEqual( |
| 525 | Buffer.from('//++/++/++//+w==', 'base64url'), |
| 526 | Buffer.from(expected) |
| 527 | ); |
| 528 | deepStrictEqual( |
| 529 | Buffer.from('//++/++/++//+w==', 'base64url'), |
| 530 | Buffer.from(expected) |
| 531 | ); |
| 532 | } |
| 533 | |
| 534 | { |
| 535 | // big example |
| 536 | const quote = |
| 537 | 'Man is distinguished, not only by his reason, but by this ' + |
| 538 | 'singular passion from other animals, which is a lust ' + |
| 539 | 'of the mind, that by a perseverance of delight in the ' + |
| 540 | 'continued and indefatigable generation of knowledge, ' + |
| 541 | 'exceeds the short vehemence of any carnal pleasure.'; |
| 542 | const expected = |
| 543 | 'TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb' + |
| 544 | '24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci' + |
| 545 | 'BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQ' + |
| 546 | 'gYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu' + |
| 547 | 'dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZ' + |
| 548 | 'GdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm' + |
| 549 | '5hbCBwbGVhc3VyZS4='; |
| 550 | strictEqual(Buffer.from(quote).toString('base64'), expected); |
| 551 | strictEqual( |
| 552 | Buffer.from(quote).toString('base64url'), |
| 553 | expected.replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '') |
| 554 | ); |
| 555 | |
| 556 | base64flavors.forEach((encoding) => { |
| 557 | let b = Buffer.allocUnsafe(1024); |
| 558 | let bytesWritten = b.write(expected, 0, encoding); |
| 559 | strictEqual(quote.length, bytesWritten); |
| 560 | strictEqual(quote, b.toString('ascii', 0, quote.length)); |
| 561 | |
| 562 | // Check that the base64 decoder ignores whitespace |
| 563 | const expectedWhite = |
| 564 | `${expected.slice(0, 60)} \n` + |
| 565 | `${expected.slice(60, 120)} \n` + |
| 566 | `${expected.slice(120, 180)} \n` + |
| 567 | `${expected.slice(180, 240)} \n` + |
| 568 | `${expected.slice(240, 300)}\n` + |
| 569 | `${expected.slice(300, 360)}\n`; |
| 570 | b = Buffer.allocUnsafe(1024); |
| 571 | bytesWritten = b.write(expectedWhite, 0, encoding); |
| 572 | strictEqual(quote.length, bytesWritten); |
| 573 | strictEqual(quote, b.toString('ascii', 0, quote.length)); |
| 574 | |
| 575 | // Check that the base64 decoder on the constructor works |
| 576 | // even in the presence of whitespace. |
| 577 | b = Buffer.from(expectedWhite, encoding); |
| 578 | strictEqual(quote.length, b.length); |
| 579 | strictEqual(quote, b.toString('ascii', 0, quote.length)); |
| 580 | |
| 581 | // Check that the base64 decoder ignores illegal chars |
| 582 | const expectedIllegal = |
| 583 | expected.slice(0, 60) + |
| 584 | ' \x80' + |
| 585 | expected.slice(60, 120) + |
| 586 | ' \xff' + |
| 587 | expected.slice(120, 180) + |
| 588 | ' \x00' + |
| 589 | expected.slice(180, 240) + |
| 590 | ' \x98' + |
| 591 | expected.slice(240, 300) + |
| 592 | '\x03' + |
| 593 | expected.slice(300, 360); |
| 594 | b = Buffer.from(expectedIllegal, encoding); |
| 595 | strictEqual(quote.length, b.length); |
| 596 | strictEqual(quote, b.toString('ascii', 0, quote.length)); |
| 597 | }); |
| 598 | } |
| 599 | |
| 600 | base64flavors.forEach((encoding) => { |
| 601 | strictEqual(Buffer.from('', encoding).toString(), ''); |
| 602 | strictEqual(Buffer.from('K', encoding).toString(), ''); |
| 603 | |
| 604 | // multiple-of-4 with padding |
| 605 | strictEqual(Buffer.from('Kg==', encoding).toString(), '*'); |
| 606 | strictEqual(Buffer.from('Kio=', encoding).toString(), '*'.repeat(2)); |
| 607 | strictEqual(Buffer.from('Kioq', encoding).toString(), '*'.repeat(3)); |
| 608 | strictEqual(Buffer.from('KioqKg==', encoding).toString(), '*'.repeat(4)); |
| 609 | strictEqual(Buffer.from('KioqKio=', encoding).toString(), '*'.repeat(5)); |
| 610 | strictEqual(Buffer.from('KioqKioq', encoding).toString(), '*'.repeat(6)); |
| 611 | strictEqual( |
| 612 | Buffer.from('KioqKioqKg==', encoding).toString(), |
| 613 | '*'.repeat(7) |
| 614 | ); |
| 615 | strictEqual( |
| 616 | Buffer.from('KioqKioqKio=', encoding).toString(), |
| 617 | '*'.repeat(8) |
| 618 | ); |
| 619 | strictEqual( |
| 620 | Buffer.from('KioqKioqKioq', encoding).toString(), |
| 621 | '*'.repeat(9) |
| 622 | ); |
| 623 | strictEqual( |
| 624 | Buffer.from('KioqKioqKioqKg==', encoding).toString(), |
| 625 | '*'.repeat(10) |
| 626 | ); |
| 627 | strictEqual( |
| 628 | Buffer.from('KioqKioqKioqKio=', encoding).toString(), |
| 629 | '*'.repeat(11) |
| 630 | ); |
| 631 | strictEqual( |
| 632 | Buffer.from('KioqKioqKioqKioq', encoding).toString(), |
| 633 | '*'.repeat(12) |
| 634 | ); |
| 635 | strictEqual( |
| 636 | Buffer.from('KioqKioqKioqKioqKg==', encoding).toString(), |
| 637 | '*'.repeat(13) |
| 638 | ); |
| 639 | strictEqual( |
| 640 | Buffer.from('KioqKioqKioqKioqKio=', encoding).toString(), |
| 641 | '*'.repeat(14) |
| 642 | ); |
| 643 | strictEqual( |
| 644 | Buffer.from('KioqKioqKioqKioqKioq', encoding).toString(), |
| 645 | '*'.repeat(15) |
| 646 | ); |
| 647 | strictEqual( |
| 648 | Buffer.from('KioqKioqKioqKioqKioqKg==', encoding).toString(), |
| 649 | '*'.repeat(16) |
| 650 | ); |
| 651 | strictEqual( |
| 652 | Buffer.from('KioqKioqKioqKioqKioqKio=', encoding).toString(), |
| 653 | '*'.repeat(17) |
| 654 | ); |
| 655 | strictEqual( |
| 656 | Buffer.from('KioqKioqKioqKioqKioqKioq', encoding).toString(), |
| 657 | '*'.repeat(18) |
| 658 | ); |
| 659 | strictEqual( |
| 660 | Buffer.from('KioqKioqKioqKioqKioqKioqKg==', encoding).toString(), |
| 661 | '*'.repeat(19) |
| 662 | ); |
| 663 | strictEqual( |
| 664 | Buffer.from('KioqKioqKioqKioqKioqKioqKio=', encoding).toString(), |
| 665 | '*'.repeat(20) |
| 666 | ); |
| 667 | |
| 668 | // No padding, not a multiple of 4 |
| 669 | strictEqual(Buffer.from('Kg', encoding).toString(), '*'); |
| 670 | strictEqual(Buffer.from('Kio', encoding).toString(), '*'.repeat(2)); |
| 671 | strictEqual(Buffer.from('KioqKg', encoding).toString(), '*'.repeat(4)); |
| 672 | strictEqual(Buffer.from('KioqKio', encoding).toString(), '*'.repeat(5)); |
| 673 | strictEqual( |
| 674 | Buffer.from('KioqKioqKg', encoding).toString(), |
| 675 | '*'.repeat(7) |
| 676 | ); |
| 677 | strictEqual( |
| 678 | Buffer.from('KioqKioqKio', encoding).toString(), |
| 679 | '*'.repeat(8) |
| 680 | ); |
| 681 | strictEqual( |
| 682 | Buffer.from('KioqKioqKioqKg', encoding).toString(), |
| 683 | '*'.repeat(10) |
| 684 | ); |
| 685 | strictEqual( |
| 686 | Buffer.from('KioqKioqKioqKio', encoding).toString(), |
| 687 | '*'.repeat(11) |
| 688 | ); |
| 689 | strictEqual( |
| 690 | Buffer.from('KioqKioqKioqKioqKg', encoding).toString(), |
| 691 | '*'.repeat(13) |
| 692 | ); |
| 693 | strictEqual( |
| 694 | Buffer.from('KioqKioqKioqKioqKio', encoding).toString(), |
| 695 | '*'.repeat(14) |
| 696 | ); |
| 697 | strictEqual( |
| 698 | Buffer.from('KioqKioqKioqKioqKioqKg', encoding).toString(), |
| 699 | '*'.repeat(16) |
| 700 | ); |
| 701 | strictEqual( |
| 702 | Buffer.from('KioqKioqKioqKioqKioqKio', encoding).toString(), |
| 703 | '*'.repeat(17) |
| 704 | ); |
| 705 | strictEqual( |
| 706 | Buffer.from('KioqKioqKioqKioqKioqKioqKg', encoding).toString(), |
| 707 | '*'.repeat(19) |
| 708 | ); |
| 709 | strictEqual( |
| 710 | Buffer.from('KioqKioqKioqKioqKioqKioqKio', encoding).toString(), |
| 711 | '*'.repeat(20) |
| 712 | ); |
| 713 | }); |
| 714 | |
| 715 | // Handle padding graciously, multiple-of-4 or not |
| 716 | strictEqual( |
| 717 | Buffer.from('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw==', 'base64') |
| 718 | .length, |
| 719 | 32 |
| 720 | ); |
| 721 | strictEqual( |
| 722 | Buffer.from('72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw==', 'base64url') |
| 723 | .length, |
| 724 | 32 |
| 725 | ); |
| 726 | strictEqual( |
| 727 | Buffer.from('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw=', 'base64') |
| 728 | .length, |
| 729 | 32 |
| 730 | ); |
| 731 | strictEqual( |
| 732 | Buffer.from('72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw=', 'base64url') |
| 733 | .length, |
| 734 | 32 |
| 735 | ); |
| 736 | strictEqual( |
| 737 | Buffer.from('72INjkR5fchcxk9+VgdGPFJDxUBFR5/rMFsghgxADiw', 'base64') |
| 738 | .length, |
| 739 | 32 |
| 740 | ); |
| 741 | strictEqual( |
| 742 | Buffer.from('72INjkR5fchcxk9-VgdGPFJDxUBFR5_rMFsghgxADiw', 'base64url') |
| 743 | .length, |
| 744 | 32 |
| 745 | ); |
| 746 | strictEqual( |
| 747 | Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==', 'base64') |
| 748 | .length, |
| 749 | 31 |
| 750 | ); |
| 751 | strictEqual( |
| 752 | Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg==', 'base64url') |
| 753 | .length, |
| 754 | 31 |
| 755 | ); |
| 756 | strictEqual( |
| 757 | Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=', 'base64') |
| 758 | .length, |
| 759 | 31 |
| 760 | ); |
| 761 | strictEqual( |
| 762 | Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg=', 'base64url') |
| 763 | .length, |
| 764 | 31 |
| 765 | ); |
| 766 | strictEqual( |
| 767 | Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg', 'base64') |
| 768 | .length, |
| 769 | 31 |
| 770 | ); |
| 771 | strictEqual( |
| 772 | Buffer.from('w69jACy6BgZmaFvv96HG6MYksWytuZu3T1FvGnulPg', 'base64url') |
| 773 | .length, |
| 774 | 31 |
| 775 | ); |
| 776 | |
| 777 | { |
| 778 | // This string encodes single '.' character in UTF-16 |
| 779 | const dot = Buffer.from('//4uAA==', 'base64'); |
| 780 | strictEqual(dot[0], 0xff); |
| 781 | strictEqual(dot[1], 0xfe); |
| 782 | strictEqual(dot[2], 0x2e); |
| 783 | strictEqual(dot[3], 0x00); |
| 784 | strictEqual(dot.toString('base64'), '//4uAA=='); |
| 785 | } |
| 786 | |
| 787 | { |
| 788 | // This string encodes single '.' character in UTF-16 |
| 789 | const dot = Buffer.from('//4uAA', 'base64url'); |
| 790 | strictEqual(dot[0], 0xff); |
| 791 | strictEqual(dot[1], 0xfe); |
| 792 | strictEqual(dot[2], 0x2e); |
| 793 | strictEqual(dot[3], 0x00); |
| 794 | strictEqual(dot.toString('base64url'), '__4uAA'); |
| 795 | } |
| 796 | |
| 797 | { |
| 798 | // Writing base64 at a position > 0 should not mangle the result. |
| 799 | // |
| 800 | // https://github.com/joyent/node/issues/402 |
| 801 | const segments = ['TWFkbmVzcz8h', 'IFRoaXM=', 'IGlz', 'IG5vZGUuanMh']; |
| 802 | const b = Buffer.allocUnsafe(64); |
| 803 | let pos = 0; |
| 804 | |
| 805 | for (let i = 0; i < segments.length; ++i) { |
| 806 | pos += b.write(segments[i], pos, 'base64'); |
| 807 | } |
| 808 | strictEqual(b.toString('latin1', 0, pos), 'Madness?! This is node.js!'); |
| 809 | } |
| 810 | |
| 811 | { |
| 812 | // Writing base64url at a position > 0 should not mangle the result. |
| 813 | // |
| 814 | // https://github.com/joyent/node/issues/402 |
| 815 | const segments = ['TWFkbmVzcz8h', 'IFRoaXM', 'IGlz', 'IG5vZGUuanMh']; |
| 816 | const b = Buffer.allocUnsafe(64); |
| 817 | let pos = 0; |
| 818 | |
| 819 | for (let i = 0; i < segments.length; ++i) { |
| 820 | pos += b.write(segments[i], pos, 'base64url'); |
| 821 | } |
| 822 | strictEqual(b.toString('latin1', 0, pos), 'Madness?! This is node.js!'); |
| 823 | } |
| 824 | |
| 825 | // Regression test for https://github.com/nodejs/node/issues/3496. |
| 826 | strictEqual(Buffer.from('=bad'.repeat(1e4), 'base64').length, 0); |
| 827 | |
| 828 | // // Regression test for https://github.com/nodejs/node/issues/11987. |
| 829 | deepStrictEqual(Buffer.from('w0 ', 'base64'), Buffer.from('w0', 'base64')); |
| 830 | |
| 831 | // // Regression test for https://github.com/nodejs/node/issues/13657. |
| 832 | deepStrictEqual( |
| 833 | Buffer.from(' YWJvcnVtLg', 'base64'), |
| 834 | Buffer.from('YWJvcnVtLg', 'base64') |
| 835 | ); |
| 836 | }, |
| 837 | }; |
| 838 | |
| 839 | export const hex = { |
| 840 | test(ctrl, env, ctx) { |
| 841 | { |
| 842 | // test hex toString |
| 843 | const hexb = Buffer.allocUnsafe(256); |
| 844 | for (let i = 0; i < 256; i++) { |
| 845 | hexb[i] = i; |
| 846 | } |
| 847 | const hexStr = hexb.toString('hex'); |
| 848 | strictEqual( |
| 849 | hexStr, |
| 850 | '000102030405060708090a0b0c0d0e0f' + |
| 851 | '101112131415161718191a1b1c1d1e1f' + |
| 852 | '202122232425262728292a2b2c2d2e2f' + |
| 853 | '303132333435363738393a3b3c3d3e3f' + |
| 854 | '404142434445464748494a4b4c4d4e4f' + |
| 855 | '505152535455565758595a5b5c5d5e5f' + |
| 856 | '606162636465666768696a6b6c6d6e6f' + |
| 857 | '707172737475767778797a7b7c7d7e7f' + |
| 858 | '808182838485868788898a8b8c8d8e8f' + |
| 859 | '909192939495969798999a9b9c9d9e9f' + |
| 860 | 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf' + |
| 861 | 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf' + |
| 862 | 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf' + |
| 863 | 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf' + |
| 864 | 'e0e1e2e3e4e5e6e7e8e9eaebecedeeef' + |
| 865 | 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff' |
| 866 | ); |
| 867 | |
| 868 | const hexb2 = Buffer.from(hexStr, 'hex'); |
| 869 | for (let i = 0; i < 256; i++) { |
| 870 | strictEqual(hexb2[i], hexb[i]); |
| 871 | } |
| 872 | } |
| 873 | |
| 874 | // Test single hex character is discarded. |
| 875 | strictEqual(Buffer.from('A', 'hex').length, 0); |
| 876 | |
| 877 | // Test that if a trailing character is discarded, rest of string is processed. |
| 878 | deepStrictEqual(Buffer.from('Abx', 'hex'), Buffer.from('Ab', 'hex')); |
| 879 | |
| 880 | // Test single base64 char encodes as 0. |
| 881 | strictEqual(Buffer.from('A', 'base64').length, 0); |
| 882 | |
| 883 | { |
| 884 | // Test an invalid slice end. |
| 885 | const b = Buffer.from([1, 2, 3, 4, 5]); |
| 886 | const b2 = b.toString('hex', 1, 10000); |
| 887 | const b3 = b.toString('hex', 1, 5); |
| 888 | const b4 = b.toString('hex', 1); |
| 889 | strictEqual(b2, b3); |
| 890 | strictEqual(b2, b4); |
| 891 | } |
| 892 | }, |
| 893 | }; |
| 894 | |
| 895 | export const slicing = { |
| 896 | test(ctrl, env, ctx) { |
| 897 | function buildBuffer(data) { |
| 898 | if (Array.isArray(data)) { |
| 899 | const buffer = Buffer.allocUnsafe(data.length); |
| 900 | data.forEach((v, k) => (buffer[k] = v)); |
| 901 | return buffer; |
| 902 | } |
| 903 | return null; |
| 904 | } |
| 905 | |
| 906 | const x = buildBuffer([ |
| 907 | 0x81, 0xa3, 0x66, 0x6f, 0x6f, 0xa3, 0x62, 0x61, 0x72, |
| 908 | ]); |
| 909 | |
| 910 | { |
| 911 | const z = x.slice(4); |
| 912 | strictEqual(z.length, 5); |
| 913 | strictEqual(z[0], 0x6f); |
| 914 | strictEqual(z[1], 0xa3); |
| 915 | strictEqual(z[2], 0x62); |
| 916 | strictEqual(z[3], 0x61); |
| 917 | strictEqual(z[4], 0x72); |
| 918 | } |
| 919 | |
| 920 | { |
| 921 | const z = x.slice(0); |
| 922 | strictEqual(z.length, x.length); |
| 923 | } |
| 924 | |
| 925 | { |
| 926 | const z = x.slice(0, 4); |
| 927 | strictEqual(z.length, 4); |
| 928 | strictEqual(z[0], 0x81); |
| 929 | strictEqual(z[1], 0xa3); |
| 930 | } |
| 931 | |
| 932 | { |
| 933 | const z = x.slice(0, 9); |
| 934 | strictEqual(z.length, 9); |
| 935 | } |
| 936 | |
| 937 | { |
| 938 | const z = x.slice(1, 4); |
| 939 | strictEqual(z.length, 3); |
| 940 | strictEqual(z[0], 0xa3); |
| 941 | } |
| 942 | |
| 943 | { |
| 944 | const z = x.slice(2, 4); |
| 945 | strictEqual(z.length, 2); |
| 946 | strictEqual(z[0], 0x66); |
| 947 | strictEqual(z[1], 0x6f); |
| 948 | } |
| 949 | }, |
| 950 | }; |
| 951 | |
| 952 | export const writing = { |
| 953 | test(ctrl, env, ctx) { |
| 954 | ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach((encoding) => { |
| 955 | const b = Buffer.allocUnsafe(10); |
| 956 | b.write('あいうえお', encoding); |
| 957 | strictEqual(b.toString(encoding), 'あいうえお'); |
| 958 | }); |
| 959 | |
| 960 | ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach((encoding) => { |
| 961 | const b = Buffer.allocUnsafe(11); |
| 962 | b.write('あいうえお', 1, encoding); |
| 963 | strictEqual(b.toString(encoding, 1), 'あいうえお'); |
| 964 | }); |
| 965 | |
| 966 | { |
| 967 | // latin1 encoding should write only one byte per character. |
| 968 | const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]); |
| 969 | let s = String.fromCharCode(0xffff); |
| 970 | b.write(s, 0, 'latin1'); |
| 971 | strictEqual(b[0], 0xff); |
| 972 | strictEqual(b[1], 0xad); |
| 973 | strictEqual(b[2], 0xbe); |
| 974 | strictEqual(b[3], 0xef); |
| 975 | s = String.fromCharCode(0xaaee); |
| 976 | b.write(s, 0, 'latin1'); |
| 977 | strictEqual(b[0], 0xee); |
| 978 | strictEqual(b[1], 0xad); |
| 979 | strictEqual(b[2], 0xbe); |
| 980 | strictEqual(b[3], 0xef); |
| 981 | } |
| 982 | |
| 983 | { |
| 984 | // Binary encoding should write only one byte per character. |
| 985 | const b = Buffer.from([0xde, 0xad, 0xbe, 0xef]); |
| 986 | let s = String.fromCharCode(0xffff); |
| 987 | b.write(s, 0, 'latin1'); |
| 988 | strictEqual(b[0], 0xff); |
| 989 | strictEqual(b[1], 0xad); |
| 990 | strictEqual(b[2], 0xbe); |
| 991 | strictEqual(b[3], 0xef); |
| 992 | s = String.fromCharCode(0xaaee); |
| 993 | b.write(s, 0, 'latin1'); |
| 994 | strictEqual(b[0], 0xee); |
| 995 | strictEqual(b[1], 0xad); |
| 996 | strictEqual(b[2], 0xbe); |
| 997 | strictEqual(b[3], 0xef); |
| 998 | } |
| 999 | |
| 1000 | { |
| 1001 | const buf = Buffer.allocUnsafe(2); |
| 1002 | strictEqual(buf.write(''), 0); // 0bytes |
| 1003 | strictEqual(buf.write('\0'), 1); // 1byte (v8 adds null terminator) |
| 1004 | strictEqual(buf.write('a\0'), 2); // 1byte * 2 |
| 1005 | strictEqual(buf.write('あ'), 0); // 3bytes |
| 1006 | strictEqual(buf.write('\0あ'), 1); // 1byte + 3bytes |
| 1007 | strictEqual(buf.write('\0\0あ'), 2); // 1byte * 2 + 3bytes |
| 1008 | } |
| 1009 | |
| 1010 | { |
| 1011 | const buf = Buffer.allocUnsafe(10); |
| 1012 | strictEqual(buf.write('あいう'), 9); // 3bytes * 3 (v8 adds null term.) |
| 1013 | strictEqual(buf.write('あいう\0'), 10); // 3bytes * 3 + 1byte |
| 1014 | } |
| 1015 | |
| 1016 | { |
| 1017 | // https://github.com/nodejs/node-v0.x-archive/issues/243 |
| 1018 | // Test write() with maxLength |
| 1019 | const buf = Buffer.allocUnsafe(4); |
| 1020 | buf.fill(0xff); |
| 1021 | strictEqual(buf.write('abcd', 1, 2, 'utf8'), 2); |
| 1022 | strictEqual(buf[0], 0xff); |
| 1023 | strictEqual(buf[1], 0x61); |
| 1024 | strictEqual(buf[2], 0x62); |
| 1025 | strictEqual(buf[3], 0xff); |
| 1026 | |
| 1027 | buf.fill(0xff); |
| 1028 | strictEqual(buf.write('abcd', 1, 4), 3); |
| 1029 | strictEqual(buf[0], 0xff); |
| 1030 | strictEqual(buf[1], 0x61); |
| 1031 | strictEqual(buf[2], 0x62); |
| 1032 | strictEqual(buf[3], 0x63); |
| 1033 | |
| 1034 | buf.fill(0xff); |
| 1035 | strictEqual(buf.write('abcd', 1, 2, 'utf8'), 2); |
| 1036 | strictEqual(buf[0], 0xff); |
| 1037 | strictEqual(buf[1], 0x61); |
| 1038 | strictEqual(buf[2], 0x62); |
| 1039 | strictEqual(buf[3], 0xff); |
| 1040 | |
| 1041 | buf.fill(0xff); |
| 1042 | strictEqual(buf.write('abcdef', 1, 2, 'hex'), 2); |
| 1043 | strictEqual(buf[0], 0xff); |
| 1044 | strictEqual(buf[1], 0xab); |
| 1045 | strictEqual(buf[2], 0xcd); |
| 1046 | strictEqual(buf[3], 0xff); |
| 1047 | |
| 1048 | ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'].forEach((encoding) => { |
| 1049 | buf.fill(0xff); |
| 1050 | strictEqual(buf.write('abcd', 0, 2, encoding), 2); |
| 1051 | strictEqual(buf[0], 0x61); |
| 1052 | strictEqual(buf[1], 0x00); |
| 1053 | strictEqual(buf[2], 0xff); |
| 1054 | strictEqual(buf[3], 0xff); |
| 1055 | }); |
| 1056 | } |
| 1057 | |
| 1058 | { |
| 1059 | // Test offset returns are correct |
| 1060 | const b = Buffer.allocUnsafe(16); |
| 1061 | strictEqual(b.writeUInt32LE(0, 0), 4); |
| 1062 | strictEqual(b.writeUInt16LE(0, 4), 6); |
| 1063 | strictEqual(b.writeUInt8(0, 6), 7); |
| 1064 | strictEqual(b.writeInt8(0, 7), 8); |
| 1065 | strictEqual(b.writeDoubleLE(0, 8), 16); |
| 1066 | } |
| 1067 | |
| 1068 | { |
| 1069 | // Test for buffer overrun |
| 1070 | const buf = Buffer.from([0, 0, 0, 0, 0]); // length: 5 |
| 1071 | const sub = buf.slice(0, 4); // length: 4 |
| 1072 | strictEqual(sub.write('12345', 'latin1'), 4); |
| 1073 | strictEqual(buf[4], 0); |
| 1074 | strictEqual(sub.write('12345', 'binary'), 4); |
| 1075 | strictEqual(buf[4], 0); |
| 1076 | } |
| 1077 | |
| 1078 | // Test for common write(U)IntLE/BE |
| 1079 | { |
| 1080 | let buf = Buffer.allocUnsafe(3); |
| 1081 | buf.writeUIntLE(0x123456, 0, 3); |
| 1082 | deepStrictEqual(buf.toJSON().data, [0x56, 0x34, 0x12]); |
| 1083 | strictEqual(buf.readUIntLE(0, 3), 0x123456); |
| 1084 | |
| 1085 | buf.fill(0xff); |
| 1086 | buf.writeUIntBE(0x123456, 0, 3); |
| 1087 | deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56]); |
| 1088 | strictEqual(buf.readUIntBE(0, 3), 0x123456); |
| 1089 | |
| 1090 | buf.fill(0xff); |
| 1091 | buf.writeIntLE(0x123456, 0, 3); |
| 1092 | deepStrictEqual(buf.toJSON().data, [0x56, 0x34, 0x12]); |
| 1093 | strictEqual(buf.readIntLE(0, 3), 0x123456); |
| 1094 | |
| 1095 | buf.fill(0xff); |
| 1096 | buf.writeIntBE(0x123456, 0, 3); |
| 1097 | deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56]); |
| 1098 | strictEqual(buf.readIntBE(0, 3), 0x123456); |
| 1099 | |
| 1100 | buf.fill(0xff); |
| 1101 | buf.writeIntLE(-0x123456, 0, 3); |
| 1102 | deepStrictEqual(buf.toJSON().data, [0xaa, 0xcb, 0xed]); |
| 1103 | strictEqual(buf.readIntLE(0, 3), -0x123456); |
| 1104 | |
| 1105 | buf.fill(0xff); |
| 1106 | buf.writeIntBE(-0x123456, 0, 3); |
| 1107 | deepStrictEqual(buf.toJSON().data, [0xed, 0xcb, 0xaa]); |
| 1108 | strictEqual(buf.readIntBE(0, 3), -0x123456); |
| 1109 | |
| 1110 | buf.fill(0xff); |
| 1111 | buf.writeIntLE(-0x123400, 0, 3); |
| 1112 | deepStrictEqual(buf.toJSON().data, [0x00, 0xcc, 0xed]); |
| 1113 | strictEqual(buf.readIntLE(0, 3), -0x123400); |
| 1114 | |
| 1115 | buf.fill(0xff); |
| 1116 | buf.writeIntBE(-0x123400, 0, 3); |
| 1117 | deepStrictEqual(buf.toJSON().data, [0xed, 0xcc, 0x00]); |
| 1118 | strictEqual(buf.readIntBE(0, 3), -0x123400); |
| 1119 | |
| 1120 | buf.fill(0xff); |
| 1121 | buf.writeIntLE(-0x120000, 0, 3); |
| 1122 | deepStrictEqual(buf.toJSON().data, [0x00, 0x00, 0xee]); |
| 1123 | strictEqual(buf.readIntLE(0, 3), -0x120000); |
| 1124 | |
| 1125 | buf.fill(0xff); |
| 1126 | buf.writeIntBE(-0x120000, 0, 3); |
| 1127 | deepStrictEqual(buf.toJSON().data, [0xee, 0x00, 0x00]); |
| 1128 | strictEqual(buf.readIntBE(0, 3), -0x120000); |
| 1129 | |
| 1130 | buf = Buffer.allocUnsafe(5); |
| 1131 | buf.writeUIntLE(0x1234567890, 0, 5); |
| 1132 | deepStrictEqual(buf.toJSON().data, [0x90, 0x78, 0x56, 0x34, 0x12]); |
| 1133 | strictEqual(buf.readUIntLE(0, 5), 0x1234567890); |
| 1134 | |
| 1135 | buf.fill(0xff); |
| 1136 | buf.writeUIntBE(0x1234567890, 0, 5); |
| 1137 | deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56, 0x78, 0x90]); |
| 1138 | strictEqual(buf.readUIntBE(0, 5), 0x1234567890); |
| 1139 | |
| 1140 | buf.fill(0xff); |
| 1141 | buf.writeIntLE(0x1234567890, 0, 5); |
| 1142 | deepStrictEqual(buf.toJSON().data, [0x90, 0x78, 0x56, 0x34, 0x12]); |
| 1143 | strictEqual(buf.readIntLE(0, 5), 0x1234567890); |
| 1144 | |
| 1145 | buf.fill(0xff); |
| 1146 | buf.writeIntBE(0x1234567890, 0, 5); |
| 1147 | deepStrictEqual(buf.toJSON().data, [0x12, 0x34, 0x56, 0x78, 0x90]); |
| 1148 | strictEqual(buf.readIntBE(0, 5), 0x1234567890); |
| 1149 | |
| 1150 | buf.fill(0xff); |
| 1151 | buf.writeIntLE(-0x1234567890, 0, 5); |
| 1152 | deepStrictEqual(buf.toJSON().data, [0x70, 0x87, 0xa9, 0xcb, 0xed]); |
| 1153 | strictEqual(buf.readIntLE(0, 5), -0x1234567890); |
| 1154 | |
| 1155 | buf.fill(0xff); |
| 1156 | buf.writeIntBE(-0x1234567890, 0, 5); |
| 1157 | deepStrictEqual(buf.toJSON().data, [0xed, 0xcb, 0xa9, 0x87, 0x70]); |
| 1158 | strictEqual(buf.readIntBE(0, 5), -0x1234567890); |
| 1159 | |
| 1160 | buf.fill(0xff); |
| 1161 | buf.writeIntLE(-0x0012000000, 0, 5); |
| 1162 | deepStrictEqual(buf.toJSON().data, [0x00, 0x00, 0x00, 0xee, 0xff]); |
| 1163 | strictEqual(buf.readIntLE(0, 5), -0x0012000000); |
| 1164 | |
| 1165 | buf.fill(0xff); |
| 1166 | buf.writeIntBE(-0x0012000000, 0, 5); |
| 1167 | deepStrictEqual(buf.toJSON().data, [0xff, 0xee, 0x00, 0x00, 0x00]); |
| 1168 | strictEqual(buf.readIntBE(0, 5), -0x0012000000); |
| 1169 | } |
| 1170 | }, |
| 1171 | }; |
| 1172 | |
| 1173 | export const misc = { |
| 1174 | test(ctrl, env, ctx) { |
| 1175 | { |
| 1176 | // https://github.com/nodejs/node-v0.x-archive/pull/1210 |
| 1177 | // Test UTF-8 string includes null character |
| 1178 | let buf = Buffer.from('\0'); |
| 1179 | strictEqual(buf.length, 1); |
| 1180 | buf = Buffer.from('\0\0'); |
| 1181 | strictEqual(buf.length, 2); |
| 1182 | } |
| 1183 | |
| 1184 | { |
| 1185 | // Test unmatched surrogates not producing invalid utf8 output |
| 1186 | // ef bf bd = utf-8 representation of unicode replacement character |
| 1187 | // see https://codereview.chromium.org/121173009/ |
| 1188 | const buf = Buffer.from('ab\ud800cd', 'utf8'); |
| 1189 | strictEqual(buf[0], 0x61); |
| 1190 | strictEqual(buf[1], 0x62); |
| 1191 | strictEqual(buf[2], 0xef); |
| 1192 | strictEqual(buf[3], 0xbf); |
| 1193 | strictEqual(buf[4], 0xbd); |
| 1194 | strictEqual(buf[5], 0x63); |
| 1195 | strictEqual(buf[6], 0x64); |
| 1196 | } |
| 1197 | |
| 1198 | { |
| 1199 | // Test alloc with fill option |
| 1200 | const buf = Buffer.alloc(5, '800A', 'hex'); |
| 1201 | strictEqual(buf[0], 128); |
| 1202 | strictEqual(buf[1], 10); |
| 1203 | strictEqual(buf[2], 128); |
| 1204 | strictEqual(buf[3], 10); |
| 1205 | strictEqual(buf[4], 128); |
| 1206 | } |
| 1207 | |
| 1208 | // Call .fill() first, stops Valgrind warning about uninitialized memory reads. |
| 1209 | Buffer.allocUnsafe(3.3).fill().toString(); |
| 1210 | // Throws bad argument error in commit 43cb4ec |
| 1211 | Buffer.alloc(3.3).fill().toString(); |
| 1212 | strictEqual(Buffer.allocUnsafe(3.3).length, 3); |
| 1213 | strictEqual(Buffer.from({ length: 3.3 }).length, 3); |
| 1214 | strictEqual(Buffer.from({ length: 'BAM' }).length, 0); |
| 1215 | |
| 1216 | strictEqual(Buffer.from('99').length, 2); |
| 1217 | strictEqual(Buffer.from('13.37').length, 5); |
| 1218 | |
| 1219 | // Ensure that the length argument is respected. |
| 1220 | ['ascii', 'utf8', 'hex', 'base64', 'latin1', 'binary'].forEach((enc) => { |
| 1221 | strictEqual(Buffer.allocUnsafe(1).write('aaaaaa', 0, 1, enc), 1); |
| 1222 | }); |
| 1223 | |
| 1224 | { |
| 1225 | // Regression test, guard against buffer overrun in the base64 decoder. |
| 1226 | const a = Buffer.allocUnsafe(3); |
| 1227 | const b = Buffer.from('xxx'); |
| 1228 | a.write('aaaaaaaa', 'base64'); |
| 1229 | strictEqual(b.toString(), 'xxx'); |
| 1230 | } |
| 1231 | |
| 1232 | // issue GH-3416 |
| 1233 | Buffer.from(Buffer.allocUnsafe(0), 0, 0); |
| 1234 | |
| 1235 | const outOfRangeError = { |
| 1236 | code: 'ERR_OUT_OF_RANGE', |
| 1237 | name: 'RangeError', |
| 1238 | }; |
| 1239 | |
| 1240 | // issue GH-5587 |
| 1241 | throws(() => Buffer.alloc(8).writeFloatLE(0, 5), outOfRangeError); |
| 1242 | throws(() => Buffer.alloc(16).writeDoubleLE(0, 9), outOfRangeError); |
| 1243 | |
| 1244 | // Attempt to overflow buffers, similar to previous bug in array buffers |
| 1245 | throws( |
| 1246 | () => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), |
| 1247 | outOfRangeError |
| 1248 | ); |
| 1249 | throws( |
| 1250 | () => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), |
| 1251 | outOfRangeError |
| 1252 | ); |
| 1253 | |
| 1254 | // Ensure negative values can't get past offset |
| 1255 | throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), outOfRangeError); |
| 1256 | throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), outOfRangeError); |
| 1257 | |
| 1258 | // Regression test for https://github.com/nodejs/node-v0.x-archive/issues/5482: |
| 1259 | // should throw but not assert in C++ land. |
| 1260 | throws(() => Buffer.from('', 'buffer'), { |
| 1261 | code: 'ERR_UNKNOWN_ENCODING', |
| 1262 | name: 'TypeError', |
| 1263 | message: 'Unknown encoding: buffer', |
| 1264 | }); |
| 1265 | |
| 1266 | // Regression test for https://github.com/nodejs/node-v0.x-archive/issues/6111. |
| 1267 | // Constructing a buffer from another buffer should a) work, and b) not corrupt |
| 1268 | // the source buffer. |
| 1269 | { |
| 1270 | const a = [...Array(128).keys()]; // [0, 1, 2, 3, ... 126, 127] |
| 1271 | const b = Buffer.from(a); |
| 1272 | const c = Buffer.from(b); |
| 1273 | strictEqual(b.length, a.length); |
| 1274 | strictEqual(c.length, a.length); |
| 1275 | for (let i = 0, k = a.length; i < k; ++i) { |
| 1276 | strictEqual(a[i], i); |
| 1277 | strictEqual(b[i], i); |
| 1278 | strictEqual(c[i], i); |
| 1279 | } |
| 1280 | } |
| 1281 | |
| 1282 | throws(() => Buffer.allocUnsafe(10).copy(), { |
| 1283 | code: 'ERR_INVALID_ARG_TYPE', |
| 1284 | name: 'TypeError', |
| 1285 | message: |
| 1286 | 'The "target" argument must be an instance of Buffer or ' + |
| 1287 | 'Uint8Array. Received undefined', |
| 1288 | }); |
| 1289 | |
| 1290 | throws(() => Buffer.from(), { |
| 1291 | name: 'TypeError', |
| 1292 | }); |
| 1293 | throws(() => Buffer.from(null), { |
| 1294 | name: 'TypeError', |
| 1295 | }); |
| 1296 | |
| 1297 | // Test prototype getters don't throw |
| 1298 | strictEqual(Buffer.prototype.parent, undefined); |
| 1299 | strictEqual(Buffer.prototype.offset, undefined); |
| 1300 | strictEqual(SlowBuffer.prototype.parent, undefined); |
| 1301 | strictEqual(SlowBuffer.prototype.offset, undefined); |
| 1302 | |
| 1303 | { |
| 1304 | // Test that large negative Buffer length inputs don't affect the pool offset. |
| 1305 | // Use the fromArrayLike() variant here because it's more lenient |
| 1306 | // about its input and passes the length directly to allocate(). |
| 1307 | deepStrictEqual(Buffer.from({ length: -3456 }), Buffer.from('')); |
| 1308 | deepStrictEqual(Buffer.from({ length: -100 }), Buffer.from('')); |
| 1309 | |
| 1310 | // Check pool offset after that by trying to write string into the pool. |
| 1311 | Buffer.from('abc'); |
| 1312 | } |
| 1313 | |
| 1314 | // Test that ParseArrayIndex handles full uint32 |
| 1315 | { |
| 1316 | throws(() => Buffer.from(new ArrayBuffer(0), -1 >>> 0), { |
| 1317 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 1318 | name: 'RangeError', |
| 1319 | message: '"offset" is outside of buffer bounds', |
| 1320 | }); |
| 1321 | } |
| 1322 | |
| 1323 | // ParseArrayIndex() should reject values that don't fit in a 32 bits size_t. |
| 1324 | throws(() => { |
| 1325 | const a = Buffer.alloc(1); |
| 1326 | const b = Buffer.alloc(1); |
| 1327 | a.copy(b, 0, 0x100000000, 0x100000001); |
| 1328 | }, outOfRangeError); |
| 1329 | |
| 1330 | // Unpooled buffer (replaces SlowBuffer) |
| 1331 | { |
| 1332 | const ubuf = Buffer.allocUnsafeSlow(10); |
| 1333 | ok(ubuf); |
| 1334 | ok(ubuf.buffer); |
| 1335 | strictEqual(ubuf.buffer.byteLength, 10); |
| 1336 | } |
| 1337 | |
| 1338 | // Regression test to verify that an empty ArrayBuffer does not throw. |
| 1339 | Buffer.from(new ArrayBuffer()); |
| 1340 | |
| 1341 | throws( |
| 1342 | () => Buffer.alloc({ valueOf: () => 1 }), |
| 1343 | /"size" argument must be of type number/ |
| 1344 | ); |
| 1345 | throws( |
| 1346 | () => Buffer.alloc({ valueOf: () => -1 }), |
| 1347 | /"size" argument must be of type number/ |
| 1348 | ); |
| 1349 | |
| 1350 | strictEqual(Buffer.prototype.toLocaleString, Buffer.prototype.toString); |
| 1351 | { |
| 1352 | const buf = Buffer.from('test'); |
| 1353 | strictEqual(buf.toLocaleString(), buf.toString()); |
| 1354 | } |
| 1355 | |
| 1356 | throws( |
| 1357 | () => { |
| 1358 | Buffer.alloc(0x1000, 'This is not correctly encoded', 'hex'); |
| 1359 | }, |
| 1360 | { |
| 1361 | name: 'TypeError', |
| 1362 | } |
| 1363 | ); |
| 1364 | |
| 1365 | throws( |
| 1366 | () => { |
| 1367 | Buffer.alloc(0x1000, 'c', 'hex'); |
| 1368 | }, |
| 1369 | { |
| 1370 | name: 'TypeError', |
| 1371 | } |
| 1372 | ); |
| 1373 | |
| 1374 | throws( |
| 1375 | () => { |
| 1376 | Buffer.alloc(1, Buffer.alloc(0)); |
| 1377 | }, |
| 1378 | { |
| 1379 | code: 'ERR_INVALID_ARG_VALUE', |
| 1380 | name: 'TypeError', |
| 1381 | } |
| 1382 | ); |
| 1383 | |
| 1384 | throws( |
| 1385 | () => { |
| 1386 | Buffer.alloc(40, 'x', 20); |
| 1387 | }, |
| 1388 | { |
| 1389 | code: 'ERR_INVALID_ARG_TYPE', |
| 1390 | name: 'TypeError', |
| 1391 | } |
| 1392 | ); |
| 1393 | }, |
| 1394 | }; |
| 1395 | |
| 1396 | export const arrayBuffers = { |
| 1397 | test(ctrl, env, ctx) { |
| 1398 | const LENGTH = 16; |
| 1399 | |
| 1400 | const ab = new ArrayBuffer(LENGTH); |
| 1401 | const dv = new DataView(ab); |
| 1402 | const ui = new Uint8Array(ab); |
| 1403 | const buf = Buffer.from(ab); |
| 1404 | |
| 1405 | ok(buf instanceof Buffer); |
| 1406 | strictEqual(buf.parent, buf.buffer); |
| 1407 | strictEqual(buf.buffer, ab); |
| 1408 | strictEqual(buf.length, ab.byteLength); |
| 1409 | |
| 1410 | buf.fill(0xc); |
| 1411 | for (let i = 0; i < LENGTH; i++) { |
| 1412 | strictEqual(ui[i], 0xc); |
| 1413 | ui[i] = 0xf; |
| 1414 | strictEqual(buf[i], 0xf); |
| 1415 | } |
| 1416 | |
| 1417 | buf.writeUInt32LE(0xf00, 0); |
| 1418 | buf.writeUInt32BE(0xb47, 4); |
| 1419 | buf.writeDoubleLE(3.1415, 8); |
| 1420 | |
| 1421 | strictEqual(dv.getUint32(0, true), 0xf00); |
| 1422 | strictEqual(dv.getUint32(4), 0xb47); |
| 1423 | strictEqual(dv.getFloat64(8, true), 3.1415); |
| 1424 | |
| 1425 | // Now test protecting users from doing stupid things |
| 1426 | |
| 1427 | throws( |
| 1428 | function () { |
| 1429 | function AB() {} |
| 1430 | Object.setPrototypeOf(AB, ArrayBuffer); |
| 1431 | Object.setPrototypeOf(AB.prototype, ArrayBuffer.prototype); |
| 1432 | Buffer.from(new AB()); |
| 1433 | }, |
| 1434 | { |
| 1435 | name: 'TypeError', |
| 1436 | } |
| 1437 | ); |
| 1438 | |
| 1439 | // Test the byteOffset and length arguments |
| 1440 | { |
| 1441 | const ab = new Uint8Array(5); |
| 1442 | ab[0] = 1; |
| 1443 | ab[1] = 2; |
| 1444 | ab[2] = 3; |
| 1445 | ab[3] = 4; |
| 1446 | ab[4] = 5; |
| 1447 | const buf = Buffer.from(ab.buffer, 1, 3); |
| 1448 | strictEqual(buf.length, 3); |
| 1449 | strictEqual(buf[0], 2); |
| 1450 | strictEqual(buf[1], 3); |
| 1451 | strictEqual(buf[2], 4); |
| 1452 | buf[0] = 9; |
| 1453 | strictEqual(ab[1], 9); |
| 1454 | |
| 1455 | throws(() => Buffer.from(ab.buffer, 6), { |
| 1456 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 1457 | name: 'RangeError', |
| 1458 | message: '"offset" is outside of buffer bounds', |
| 1459 | }); |
| 1460 | throws(() => Buffer.from(ab.buffer, 3, 6), { |
| 1461 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 1462 | name: 'RangeError', |
| 1463 | message: '"length" is outside of buffer bounds', |
| 1464 | }); |
| 1465 | } |
| 1466 | |
| 1467 | // Test the deprecated Buffer() version also |
| 1468 | { |
| 1469 | const ab = new Uint8Array(5); |
| 1470 | ab[0] = 1; |
| 1471 | ab[1] = 2; |
| 1472 | ab[2] = 3; |
| 1473 | ab[3] = 4; |
| 1474 | ab[4] = 5; |
| 1475 | const buf = Buffer(ab.buffer, 1, 3); |
| 1476 | strictEqual(buf.length, 3); |
| 1477 | strictEqual(buf[0], 2); |
| 1478 | strictEqual(buf[1], 3); |
| 1479 | strictEqual(buf[2], 4); |
| 1480 | buf[0] = 9; |
| 1481 | strictEqual(ab[1], 9); |
| 1482 | |
| 1483 | throws(() => Buffer(ab.buffer, 6), { |
| 1484 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 1485 | name: 'RangeError', |
| 1486 | message: '"offset" is outside of buffer bounds', |
| 1487 | }); |
| 1488 | throws(() => Buffer(ab.buffer, 3, 6), { |
| 1489 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 1490 | name: 'RangeError', |
| 1491 | message: '"length" is outside of buffer bounds', |
| 1492 | }); |
| 1493 | } |
| 1494 | |
| 1495 | { |
| 1496 | // If byteOffset is not numeric, it defaults to 0. |
| 1497 | const ab = new ArrayBuffer(10); |
| 1498 | const expected = Buffer.from(ab, 0); |
| 1499 | deepStrictEqual(Buffer.from(ab, 'fhqwhgads'), expected); |
| 1500 | deepStrictEqual(Buffer.from(ab, NaN), expected); |
| 1501 | deepStrictEqual(Buffer.from(ab, {}), expected); |
| 1502 | deepStrictEqual(Buffer.from(ab, []), expected); |
| 1503 | |
| 1504 | // If byteOffset can be converted to a number, it will be. |
| 1505 | deepStrictEqual(Buffer.from(ab, [1]), Buffer.from(ab, 1)); |
| 1506 | |
| 1507 | // If byteOffset is Infinity, throw. |
| 1508 | throws( |
| 1509 | () => { |
| 1510 | Buffer.from(ab, Infinity); |
| 1511 | }, |
| 1512 | { |
| 1513 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 1514 | name: 'RangeError', |
| 1515 | message: '"offset" is outside of buffer bounds', |
| 1516 | } |
| 1517 | ); |
| 1518 | } |
| 1519 | |
| 1520 | { |
| 1521 | // If length is not numeric, it defaults to 0. |
| 1522 | const ab = new ArrayBuffer(10); |
| 1523 | const expected = Buffer.from(ab, 0, 0); |
| 1524 | deepStrictEqual(Buffer.from(ab, 0, 'fhqwhgads'), expected); |
| 1525 | deepStrictEqual(Buffer.from(ab, 0, NaN), expected); |
| 1526 | deepStrictEqual(Buffer.from(ab, 0, {}), expected); |
| 1527 | deepStrictEqual(Buffer.from(ab, 0, []), expected); |
| 1528 | |
| 1529 | // If length can be converted to a number, it will be. |
| 1530 | deepStrictEqual(Buffer.from(ab, 0, [1]), Buffer.from(ab, 0, 1)); |
| 1531 | |
| 1532 | // If length is Infinity, throw. |
| 1533 | throws( |
| 1534 | () => { |
| 1535 | Buffer.from(ab, 0, Infinity); |
| 1536 | }, |
| 1537 | { |
| 1538 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 1539 | name: 'RangeError', |
| 1540 | message: '"length" is outside of buffer bounds', |
| 1541 | } |
| 1542 | ); |
| 1543 | } |
| 1544 | |
| 1545 | // Test an array like entry with the length set to NaN. |
| 1546 | deepStrictEqual(Buffer.from({ length: NaN }), Buffer.alloc(0)); |
| 1547 | }, |
| 1548 | }; |
| 1549 | |
| 1550 | export const ascii = { |
| 1551 | test(ctrl, env, ctx) { |
| 1552 | // ASCII conversion in node.js simply masks off the high bits, |
| 1553 | // it doesn't do transliteration. |
| 1554 | strictEqual(Buffer.from('hérité').toString('ascii'), 'hC)ritC)'); |
| 1555 | // 71 characters, 78 bytes. The ’ character is a triple-byte sequence. |
| 1556 | const input = |
| 1557 | 'C’est, graphiquement, la réunion d’un accent aigu ' + |
| 1558 | 'et d’un accent grave.'; |
| 1559 | |
| 1560 | const expected = |
| 1561 | 'Cb\u0000\u0019est, graphiquement, la rC)union ' + |
| 1562 | 'db\u0000\u0019un accent aigu et db\u0000\u0019un ' + |
| 1563 | 'accent grave.'; |
| 1564 | |
| 1565 | const buf = Buffer.from(input); |
| 1566 | |
| 1567 | for (let i = 0; i < expected.length; ++i) { |
| 1568 | strictEqual(buf.slice(i).toString('ascii'), expected.slice(i)); |
| 1569 | |
| 1570 | // Skip remainder of multi-byte sequence. |
| 1571 | if (input.charCodeAt(i) > 65535) ++i; |
| 1572 | if (input.charCodeAt(i) > 127) ++i; |
| 1573 | } |
| 1574 | }, |
| 1575 | }; |
| 1576 | |
| 1577 | export const badHex = { |
| 1578 | test(ctrl, env, ctx) { |
| 1579 | // Test hex strings and bad hex strings |
| 1580 | { |
| 1581 | const buf = Buffer.alloc(4); |
| 1582 | strictEqual(buf.length, 4); |
| 1583 | deepStrictEqual(buf, Buffer.from([0, 0, 0, 0])); |
| 1584 | strictEqual(buf.write('abcdxx', 0, 'hex'), 2); |
| 1585 | deepStrictEqual(buf, Buffer.from([0xab, 0xcd, 0x00, 0x00])); |
| 1586 | strictEqual(buf.toString('hex'), 'abcd0000'); |
| 1587 | strictEqual(buf.write('abcdef01', 0, 'hex'), 4); |
| 1588 | deepStrictEqual(buf, Buffer.from([0xab, 0xcd, 0xef, 0x01])); |
| 1589 | strictEqual(buf.toString('hex'), 'abcdef01'); |
| 1590 | |
| 1591 | const copy = Buffer.from(buf.toString('hex'), 'hex'); |
| 1592 | strictEqual(buf.toString('hex'), copy.toString('hex')); |
| 1593 | } |
| 1594 | |
| 1595 | { |
| 1596 | const buf = Buffer.alloc(5); |
| 1597 | strictEqual(buf.write('abcdxx', 1, 'hex'), 2); |
| 1598 | strictEqual(buf.toString('hex'), '00abcd0000'); |
| 1599 | } |
| 1600 | |
| 1601 | { |
| 1602 | const buf = Buffer.alloc(4); |
| 1603 | deepStrictEqual(buf, Buffer.from([0, 0, 0, 0])); |
| 1604 | strictEqual(buf.write('xxabcd', 0, 'hex'), 0); |
| 1605 | deepStrictEqual(buf, Buffer.from([0, 0, 0, 0])); |
| 1606 | strictEqual(buf.write('xxab', 1, 'hex'), 0); |
| 1607 | deepStrictEqual(buf, Buffer.from([0, 0, 0, 0])); |
| 1608 | strictEqual(buf.write('cdxxab', 0, 'hex'), 1); |
| 1609 | deepStrictEqual(buf, Buffer.from([0xcd, 0, 0, 0])); |
| 1610 | } |
| 1611 | |
| 1612 | { |
| 1613 | const buf = Buffer.alloc(256); |
| 1614 | for (let i = 0; i < 256; i++) buf[i] = i; |
| 1615 | |
| 1616 | const hex = buf.toString('hex'); |
| 1617 | deepStrictEqual(Buffer.from(hex, 'hex'), buf); |
| 1618 | |
| 1619 | const badHex = `${hex.slice(0, 256)}xx${hex.slice(256, 510)}`; |
| 1620 | deepStrictEqual(Buffer.from(badHex, 'hex'), buf.slice(0, 128)); |
| 1621 | } |
| 1622 | }, |
| 1623 | }; |
| 1624 | |
| 1625 | export const bigint64 = { |
| 1626 | test(ctrl, env, ctx) { |
| 1627 | const buf = Buffer.allocUnsafe(8); |
| 1628 | |
| 1629 | ['LE', 'BE'].forEach(function (endianness) { |
| 1630 | // Should allow simple BigInts to be written and read |
| 1631 | let val = 123456789n; |
| 1632 | buf[`writeBigInt64${endianness}`](val, 0); |
| 1633 | let rtn = buf[`readBigInt64${endianness}`](0); |
| 1634 | strictEqual(val, rtn); |
| 1635 | |
| 1636 | // Should allow INT64_MAX to be written and read |
| 1637 | val = 0x7fffffffffffffffn; |
| 1638 | buf[`writeBigInt64${endianness}`](val, 0); |
| 1639 | rtn = buf[`readBigInt64${endianness}`](0); |
| 1640 | strictEqual(val, rtn); |
| 1641 | |
| 1642 | // Should read and write a negative signed 64-bit integer |
| 1643 | val = -123456789n; |
| 1644 | buf[`writeBigInt64${endianness}`](val, 0); |
| 1645 | strictEqual(val, buf[`readBigInt64${endianness}`](0)); |
| 1646 | |
| 1647 | // Should read and write an unsigned 64-bit integer |
| 1648 | val = 123456789n; |
| 1649 | buf[`writeBigUInt64${endianness}`](val, 0); |
| 1650 | strictEqual(val, buf[`readBigUInt64${endianness}`](0)); |
| 1651 | |
| 1652 | // Should throw a RangeError upon INT64_MAX+1 being written |
| 1653 | throws(function () { |
| 1654 | const val = 0x8000000000000000n; |
| 1655 | buf[`writeBigInt64${endianness}`](val, 0); |
| 1656 | }, RangeError); |
| 1657 | |
| 1658 | // Should throw a RangeError upon UINT64_MAX+1 being written |
| 1659 | throws( |
| 1660 | function () { |
| 1661 | const val = 0x10000000000000000n; |
| 1662 | buf[`writeBigUInt64${endianness}`](val, 0); |
| 1663 | }, |
| 1664 | { |
| 1665 | code: 'ERR_OUT_OF_RANGE', |
| 1666 | message: |
| 1667 | 'The value of "value" is out of range. It must be ' + |
| 1668 | '>= 0n and < 2n ** 64n. Received 18_446_744_073_709_551_616n', |
| 1669 | } |
| 1670 | ); |
| 1671 | |
| 1672 | // Should throw a TypeError upon invalid input |
| 1673 | throws(function () { |
| 1674 | buf[`writeBigInt64${endianness}`]('bad', 0); |
| 1675 | }, TypeError); |
| 1676 | |
| 1677 | // Should throw a TypeError upon invalid input |
| 1678 | throws(function () { |
| 1679 | buf[`writeBigUInt64${endianness}`]('bad', 0); |
| 1680 | }, TypeError); |
| 1681 | }); |
| 1682 | }, |
| 1683 | }; |
| 1684 | |
| 1685 | export const byteLength = { |
| 1686 | test(ctrl, env, ctx) { |
| 1687 | [[32, 'latin1'], [NaN, 'utf8'], [{}, 'latin1'], []].forEach((args) => { |
| 1688 | throws(() => Buffer.byteLength(...args), { |
| 1689 | code: 'ERR_INVALID_ARG_TYPE', |
| 1690 | name: 'TypeError', |
| 1691 | }); |
| 1692 | }); |
| 1693 | |
| 1694 | ok(ArrayBuffer.isView(new Buffer(10))); |
| 1695 | ok(ArrayBuffer.isView(new SlowBuffer(10))); |
| 1696 | ok(ArrayBuffer.isView(Buffer.alloc(10))); |
| 1697 | ok(ArrayBuffer.isView(Buffer.allocUnsafe(10))); |
| 1698 | ok(ArrayBuffer.isView(Buffer.allocUnsafeSlow(10))); |
| 1699 | ok(ArrayBuffer.isView(Buffer.from(''))); |
| 1700 | |
| 1701 | // buffer |
| 1702 | const incomplete = Buffer.from([0xe4, 0xb8, 0xad, 0xe6, 0x96]); |
| 1703 | strictEqual(Buffer.byteLength(incomplete), 5); |
| 1704 | const ascii = Buffer.from('abc'); |
| 1705 | strictEqual(Buffer.byteLength(ascii), 3); |
| 1706 | |
| 1707 | // ArrayBuffer |
| 1708 | const buffer = new ArrayBuffer(8); |
| 1709 | strictEqual(Buffer.byteLength(buffer), 8); |
| 1710 | |
| 1711 | // TypedArray |
| 1712 | const int8 = new Int8Array(8); |
| 1713 | strictEqual(Buffer.byteLength(int8), 8); |
| 1714 | const uint8 = new Uint8Array(8); |
| 1715 | strictEqual(Buffer.byteLength(uint8), 8); |
| 1716 | const uintc8 = new Uint8ClampedArray(2); |
| 1717 | strictEqual(Buffer.byteLength(uintc8), 2); |
| 1718 | const int16 = new Int16Array(8); |
| 1719 | strictEqual(Buffer.byteLength(int16), 16); |
| 1720 | const uint16 = new Uint16Array(8); |
| 1721 | strictEqual(Buffer.byteLength(uint16), 16); |
| 1722 | const int32 = new Int32Array(8); |
| 1723 | strictEqual(Buffer.byteLength(int32), 32); |
| 1724 | const uint32 = new Uint32Array(8); |
| 1725 | strictEqual(Buffer.byteLength(uint32), 32); |
| 1726 | const float16 = new Float16Array(8); |
| 1727 | strictEqual(Buffer.byteLength(float16), 16); |
| 1728 | const float32 = new Float32Array(8); |
| 1729 | strictEqual(Buffer.byteLength(float32), 32); |
| 1730 | const float64 = new Float64Array(8); |
| 1731 | strictEqual(Buffer.byteLength(float64), 64); |
| 1732 | |
| 1733 | // DataView |
| 1734 | const dv = new DataView(new ArrayBuffer(2)); |
| 1735 | strictEqual(Buffer.byteLength(dv), 2); |
| 1736 | |
| 1737 | // Special case: zero length string |
| 1738 | strictEqual(Buffer.byteLength('', 'ascii'), 0); |
| 1739 | strictEqual(Buffer.byteLength('', 'HeX'), 0); |
| 1740 | |
| 1741 | // utf8 |
| 1742 | strictEqual(Buffer.byteLength('∑éllö wørl∂!', 'utf-8'), 19); |
| 1743 | strictEqual(Buffer.byteLength('κλμνξο', 'utf8'), 12); |
| 1744 | strictEqual(Buffer.byteLength('挵挶挷挸挹', 'utf-8'), 15); |
| 1745 | strictEqual(Buffer.byteLength('𠝹𠱓𠱸', 'UTF8'), 12); |
| 1746 | // Without an encoding, utf8 should be assumed |
| 1747 | strictEqual(Buffer.byteLength('hey there'), 9); |
| 1748 | strictEqual(Buffer.byteLength('𠱸挶νξ#xx :)'), 17); |
| 1749 | strictEqual(Buffer.byteLength('hello world', ''), 11); |
| 1750 | // It should also be assumed with unrecognized encoding |
| 1751 | |
| 1752 | strictEqual(Buffer.byteLength('hello world', 'abc'), 11); |
| 1753 | strictEqual(Buffer.byteLength('ßœ∑≈', 'unkn0wn enc0ding'), 10); |
| 1754 | |
| 1755 | // base64 |
| 1756 | strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ=', 'base64'), 11); |
| 1757 | strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ=', 'BASE64'), 11); |
| 1758 | strictEqual(Buffer.byteLength('bm9kZS5qcyByb2NrcyE=', 'base64'), 14); |
| 1759 | strictEqual(Buffer.byteLength('aGkk', 'base64'), 3); |
| 1760 | strictEqual( |
| 1761 | Buffer.byteLength('bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw==', 'base64'), |
| 1762 | 25 |
| 1763 | ); |
| 1764 | // base64url |
| 1765 | strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ', 'base64url'), 11); |
| 1766 | strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ', 'BASE64URL'), 11); |
| 1767 | strictEqual(Buffer.byteLength('bm9kZS5qcyByb2NrcyE', 'base64url'), 14); |
| 1768 | strictEqual(Buffer.byteLength('aGkk', 'base64url'), 3); |
| 1769 | strictEqual( |
| 1770 | Buffer.byteLength('bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw', 'base64url'), |
| 1771 | 25 |
| 1772 | ); |
| 1773 | // special padding |
| 1774 | strictEqual(Buffer.byteLength('aaa=', 'base64'), 2); |
| 1775 | strictEqual(Buffer.byteLength('aaaa==', 'base64'), 3); |
| 1776 | strictEqual(Buffer.byteLength('aaa=', 'base64url'), 2); |
| 1777 | strictEqual(Buffer.byteLength('aaaa==', 'base64url'), 3); |
| 1778 | |
| 1779 | strictEqual(Buffer.byteLength('Il était tué'), 14); |
| 1780 | strictEqual(Buffer.byteLength('Il était tué', 'utf8'), 14); |
| 1781 | |
| 1782 | ['ascii', 'latin1', 'binary'] |
| 1783 | .reduce((es, e) => es.concat(e, e.toUpperCase()), []) |
| 1784 | .forEach((encoding) => { |
| 1785 | strictEqual(Buffer.byteLength('Il était tué', encoding), 12); |
| 1786 | }); |
| 1787 | |
| 1788 | ['ucs2', 'ucs-2', 'utf16le', 'utf-16le'] |
| 1789 | .reduce((es, e) => es.concat(e, e.toUpperCase()), []) |
| 1790 | .forEach((encoding) => { |
| 1791 | strictEqual(Buffer.byteLength('Il était tué', encoding), 24); |
| 1792 | }); |
| 1793 | |
| 1794 | // Verify that invalid encodings are treated as utf8 |
| 1795 | for (let i = 1; i < 10; i++) { |
| 1796 | const encoding = String(i).repeat(i); |
| 1797 | |
| 1798 | ok(!Buffer.isEncoding(encoding)); |
| 1799 | strictEqual( |
| 1800 | Buffer.byteLength('foo', encoding), |
| 1801 | Buffer.byteLength('foo', 'utf8') |
| 1802 | ); |
| 1803 | } |
| 1804 | }, |
| 1805 | }; |
| 1806 | |
| 1807 | export const compareOffset = { |
| 1808 | test(ctrl, env, ctx) { |
| 1809 | const a = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); |
| 1810 | const b = Buffer.from([5, 6, 7, 8, 9, 0, 1, 2, 3, 4]); |
| 1811 | |
| 1812 | strictEqual(a.compare(b), -1); |
| 1813 | |
| 1814 | // Equivalent to a.compare(b). |
| 1815 | strictEqual(a.compare(b, 0), -1); |
| 1816 | throws(() => a.compare(b, '0'), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 1817 | strictEqual(a.compare(b, undefined), -1); |
| 1818 | |
| 1819 | // Equivalent to a.compare(b). |
| 1820 | strictEqual(a.compare(b, 0, undefined, 0), -1); |
| 1821 | |
| 1822 | // Zero-length target, return 1 |
| 1823 | strictEqual(a.compare(b, 0, 0, 0), 1); |
| 1824 | throws(() => a.compare(b, 0, '0', '0'), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 1825 | |
| 1826 | // Equivalent to Buffer.compare(a, b.slice(6, 10)) |
| 1827 | strictEqual(a.compare(b, 6, 10), 1); |
| 1828 | |
| 1829 | // Zero-length source, return -1 |
| 1830 | strictEqual(a.compare(b, 6, 10, 0, 0), -1); |
| 1831 | |
| 1832 | // Zero-length source and target, return 0 |
| 1833 | strictEqual(a.compare(b, 0, 0, 0, 0), 0); |
| 1834 | strictEqual(a.compare(b, 1, 1, 2, 2), 0); |
| 1835 | |
| 1836 | // Equivalent to Buffer.compare(a.slice(4), b.slice(0, 5)) |
| 1837 | strictEqual(a.compare(b, 0, 5, 4), 1); |
| 1838 | |
| 1839 | // Equivalent to Buffer.compare(a.slice(1), b.slice(5)) |
| 1840 | strictEqual(a.compare(b, 5, undefined, 1), 1); |
| 1841 | |
| 1842 | // Equivalent to Buffer.compare(a.slice(2), b.slice(2, 4)) |
| 1843 | strictEqual(a.compare(b, 2, 4, 2), -1); |
| 1844 | |
| 1845 | // Equivalent to Buffer.compare(a.slice(4), b.slice(0, 7)) |
| 1846 | strictEqual(a.compare(b, 0, 7, 4), -1); |
| 1847 | |
| 1848 | // Equivalent to Buffer.compare(a.slice(4, 6), b.slice(0, 7)); |
| 1849 | strictEqual(a.compare(b, 0, 7, 4, 6), -1); |
| 1850 | |
| 1851 | // Null is ambiguous. |
| 1852 | throws(() => a.compare(b, 0, null), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 1853 | |
| 1854 | // Values do not get coerced. |
| 1855 | throws(() => a.compare(b, 0, { valueOf: () => 5 }), { |
| 1856 | code: 'ERR_INVALID_ARG_TYPE', |
| 1857 | }); |
| 1858 | |
| 1859 | // Infinity should not be coerced. |
| 1860 | throws(() => a.compare(b, Infinity, -Infinity), { |
| 1861 | code: 'ERR_OUT_OF_RANGE', |
| 1862 | }); |
| 1863 | |
| 1864 | // Zero length target because default for targetEnd <= targetSource |
| 1865 | strictEqual(a.compare(b, 0xff), 1); |
| 1866 | |
| 1867 | throws(() => a.compare(b, '0xff'), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 1868 | throws(() => a.compare(b, 0, '0xff'), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 1869 | |
| 1870 | const oor = { code: 'ERR_OUT_OF_RANGE' }; |
| 1871 | |
| 1872 | throws(() => a.compare(b, 0, 100, 0), oor); |
| 1873 | throws(() => a.compare(b, 0, 1, 0, 100), oor); |
| 1874 | throws(() => a.compare(b, -1), oor); |
| 1875 | throws(() => a.compare(b, 0, Infinity), oor); |
| 1876 | throws(() => a.compare(b, 0, 1, -1), oor); |
| 1877 | throws(() => a.compare(b, -Infinity, Infinity), oor); |
| 1878 | throws(() => a.compare(), { |
| 1879 | code: 'ERR_INVALID_ARG_TYPE', |
| 1880 | name: 'TypeError', |
| 1881 | message: |
| 1882 | 'The "target" argument must be an instance of ' + |
| 1883 | 'Buffer or Uint8Array. Received undefined', |
| 1884 | }); |
| 1885 | }, |
| 1886 | }; |
| 1887 | |
| 1888 | export const compare = { |
| 1889 | test(ctrl, env, ctx) { |
| 1890 | const b = Buffer.alloc(1, 'a'); |
| 1891 | const c = Buffer.alloc(1, 'c'); |
| 1892 | const d = Buffer.alloc(2, 'aa'); |
| 1893 | const e = new Uint8Array([0x61, 0x61]); // ASCII 'aa', same as d |
| 1894 | |
| 1895 | strictEqual(b.compare(c), -1); |
| 1896 | strictEqual(c.compare(d), 1); |
| 1897 | strictEqual(d.compare(b), 1); |
| 1898 | strictEqual(d.compare(e), 0); |
| 1899 | strictEqual(b.compare(d), -1); |
| 1900 | strictEqual(b.compare(b), 0); |
| 1901 | |
| 1902 | strictEqual(Buffer.compare(b, c), -1); |
| 1903 | strictEqual(Buffer.compare(c, d), 1); |
| 1904 | strictEqual(Buffer.compare(d, b), 1); |
| 1905 | strictEqual(Buffer.compare(b, d), -1); |
| 1906 | strictEqual(Buffer.compare(c, c), 0); |
| 1907 | strictEqual(Buffer.compare(e, e), 0); |
| 1908 | strictEqual(Buffer.compare(d, e), 0); |
| 1909 | strictEqual(Buffer.compare(d, b), 1); |
| 1910 | |
| 1911 | strictEqual(Buffer.compare(Buffer.alloc(0), Buffer.alloc(0)), 0); |
| 1912 | strictEqual(Buffer.compare(Buffer.alloc(0), Buffer.alloc(1)), -1); |
| 1913 | strictEqual(Buffer.compare(Buffer.alloc(1), Buffer.alloc(0)), 1); |
| 1914 | |
| 1915 | throws(() => Buffer.compare(Buffer.alloc(1), 'abc'), { |
| 1916 | code: 'ERR_INVALID_ARG_TYPE', |
| 1917 | }); |
| 1918 | throws(() => Buffer.compare('abc', Buffer.alloc(1)), { |
| 1919 | code: 'ERR_INVALID_ARG_TYPE', |
| 1920 | }); |
| 1921 | |
| 1922 | throws(() => Buffer.alloc(1).compare('abc'), { |
| 1923 | code: 'ERR_INVALID_ARG_TYPE', |
| 1924 | name: 'TypeError', |
| 1925 | }); |
| 1926 | }, |
| 1927 | }; |
| 1928 | |
| 1929 | export const concat = { |
| 1930 | test(ctrl, env, ctx) { |
| 1931 | const zero = []; |
| 1932 | const one = [Buffer.from('asdf')]; |
| 1933 | const long = []; |
| 1934 | for (let i = 0; i < 10; i++) long.push(Buffer.from('asdf')); |
| 1935 | |
| 1936 | const flatZero = Buffer.concat(zero); |
| 1937 | const flatOne = Buffer.concat(one); |
| 1938 | const flatLong = Buffer.concat(long); |
| 1939 | const flatLongLen = Buffer.concat(long, 40); |
| 1940 | |
| 1941 | strictEqual(flatZero.length, 0); |
| 1942 | strictEqual(flatOne.toString(), 'asdf'); |
| 1943 | |
| 1944 | const check = 'asdf'.repeat(10); |
| 1945 | |
| 1946 | // A special case where concat used to return the first item, |
| 1947 | // if the length is one. This check is to make sure that we don't do that. |
| 1948 | notStrictEqual(flatOne, one[0]); |
| 1949 | strictEqual(flatLong.toString(), check); |
| 1950 | strictEqual(flatLongLen.toString(), check); |
| 1951 | |
| 1952 | [undefined, null, Buffer.from('hello')].forEach((value) => { |
| 1953 | throws( |
| 1954 | () => { |
| 1955 | Buffer.concat(value); |
| 1956 | }, |
| 1957 | { |
| 1958 | name: 'TypeError', |
| 1959 | } |
| 1960 | ); |
| 1961 | }); |
| 1962 | |
| 1963 | [[42], ['hello', Buffer.from('world')]].forEach((value) => { |
| 1964 | throws( |
| 1965 | () => { |
| 1966 | Buffer.concat(value); |
| 1967 | }, |
| 1968 | { |
| 1969 | name: 'TypeError', |
| 1970 | //code: 'ERR_INVALID_ARG_TYPE', |
| 1971 | } |
| 1972 | ); |
| 1973 | }); |
| 1974 | |
| 1975 | throws( |
| 1976 | () => { |
| 1977 | Buffer.concat([Buffer.from('hello'), 3]); |
| 1978 | }, |
| 1979 | { |
| 1980 | name: 'TypeError', |
| 1981 | //code: 'ERR_INVALID_ARG_TYPE', |
| 1982 | } |
| 1983 | ); |
| 1984 | |
| 1985 | const random10 = Buffer.alloc(10); |
| 1986 | crypto.getRandomValues(random10); |
| 1987 | const empty = Buffer.alloc(0); |
| 1988 | |
| 1989 | notDeepStrictEqual(random10, empty); |
| 1990 | notDeepStrictEqual(random10, Buffer.alloc(10)); |
| 1991 | |
| 1992 | deepStrictEqual(Buffer.concat([], 100), empty); |
| 1993 | deepStrictEqual(Buffer.concat([random10], 0), empty); |
| 1994 | deepStrictEqual(Buffer.concat([random10], 10), random10); |
| 1995 | deepStrictEqual(Buffer.concat([random10, random10], 10), random10); |
| 1996 | deepStrictEqual(Buffer.concat([empty, random10]), random10); |
| 1997 | deepStrictEqual(Buffer.concat([random10, empty, empty]), random10); |
| 1998 | |
| 1999 | // The tail should be zero-filled |
| 2000 | deepStrictEqual(Buffer.concat([empty], 100), Buffer.alloc(100)); |
| 2001 | deepStrictEqual(Buffer.concat([empty], 4096), Buffer.alloc(4096)); |
| 2002 | deepStrictEqual( |
| 2003 | Buffer.concat([random10], 40), |
| 2004 | Buffer.concat([random10, Buffer.alloc(30)]) |
| 2005 | ); |
| 2006 | |
| 2007 | deepStrictEqual( |
| 2008 | Buffer.concat([ |
| 2009 | new Uint8Array([0x41, 0x42]), |
| 2010 | new Uint8Array([0x43, 0x44]), |
| 2011 | ]), |
| 2012 | Buffer.from('ABCD') |
| 2013 | ); |
| 2014 | }, |
| 2015 | }; |
| 2016 | |
| 2017 | export const konstants = { |
| 2018 | test(ctrl, env, ctx) { |
| 2019 | strictEqual(typeof MAX_LENGTH, 'number'); |
| 2020 | strictEqual(typeof MAX_STRING_LENGTH, 'number'); |
| 2021 | ok(MAX_STRING_LENGTH <= MAX_LENGTH); |
| 2022 | throws( |
| 2023 | () => ' '.repeat(MAX_STRING_LENGTH + 1), |
| 2024 | /^RangeError: Invalid string length$/ |
| 2025 | ); |
| 2026 | ' '.repeat(MAX_STRING_LENGTH); // Should not throw. |
| 2027 | // Legacy values match: |
| 2028 | strictEqual(kMaxLength, MAX_LENGTH); |
| 2029 | strictEqual(kStringMaxLength, MAX_STRING_LENGTH); |
| 2030 | }, |
| 2031 | }; |
| 2032 | |
| 2033 | export const copy = { |
| 2034 | test(ctrl, env, ctx) { |
| 2035 | const b = Buffer.allocUnsafe(1024); |
| 2036 | const c = Buffer.allocUnsafe(512); |
| 2037 | |
| 2038 | let cntr = 0; |
| 2039 | |
| 2040 | { |
| 2041 | // copy 512 bytes, from 0 to 512. |
| 2042 | b.fill(++cntr); |
| 2043 | c.fill(++cntr); |
| 2044 | const copied = b.copy(c, 0, 0, 512); |
| 2045 | strictEqual(copied, 512); |
| 2046 | for (let i = 0; i < c.length; i++) { |
| 2047 | strictEqual(c[i], b[i]); |
| 2048 | } |
| 2049 | } |
| 2050 | |
| 2051 | { |
| 2052 | // Current behavior is to coerce values to integers. |
| 2053 | b.fill(++cntr); |
| 2054 | c.fill(++cntr); |
| 2055 | const copied = b.copy(c, '0', '0', '512'); |
| 2056 | strictEqual(copied, 512); |
| 2057 | for (let i = 0; i < c.length; i++) { |
| 2058 | strictEqual(c[i], b[i]); |
| 2059 | } |
| 2060 | } |
| 2061 | |
| 2062 | { |
| 2063 | // Floats will be converted to integers via `Math.floor` |
| 2064 | b.fill(++cntr); |
| 2065 | c.fill(++cntr); |
| 2066 | const copied = b.copy(c, 0, 0, 512.5); |
| 2067 | strictEqual(copied, 512); |
| 2068 | for (let i = 0; i < c.length; i++) { |
| 2069 | strictEqual(c[i], b[i]); |
| 2070 | } |
| 2071 | } |
| 2072 | |
| 2073 | { |
| 2074 | // Copy c into b, without specifying sourceEnd |
| 2075 | b.fill(++cntr); |
| 2076 | c.fill(++cntr); |
| 2077 | const copied = c.copy(b, 0, 0); |
| 2078 | strictEqual(copied, c.length); |
| 2079 | for (let i = 0; i < c.length; i++) { |
| 2080 | strictEqual(b[i], c[i]); |
| 2081 | } |
| 2082 | } |
| 2083 | |
| 2084 | { |
| 2085 | // Copy c into b, without specifying sourceStart |
| 2086 | b.fill(++cntr); |
| 2087 | c.fill(++cntr); |
| 2088 | const copied = c.copy(b, 0); |
| 2089 | strictEqual(copied, c.length); |
| 2090 | for (let i = 0; i < c.length; i++) { |
| 2091 | strictEqual(b[i], c[i]); |
| 2092 | } |
| 2093 | } |
| 2094 | |
| 2095 | { |
| 2096 | // Copied source range greater than source length |
| 2097 | b.fill(++cntr); |
| 2098 | c.fill(++cntr); |
| 2099 | const copied = c.copy(b, 0, 0, c.length + 1); |
| 2100 | strictEqual(copied, c.length); |
| 2101 | for (let i = 0; i < c.length; i++) { |
| 2102 | strictEqual(b[i], c[i]); |
| 2103 | } |
| 2104 | } |
| 2105 | |
| 2106 | { |
| 2107 | // Copy longer buffer b to shorter c without targetStart |
| 2108 | b.fill(++cntr); |
| 2109 | c.fill(++cntr); |
| 2110 | const copied = b.copy(c); |
| 2111 | strictEqual(copied, c.length); |
| 2112 | for (let i = 0; i < c.length; i++) { |
| 2113 | strictEqual(c[i], b[i]); |
| 2114 | } |
| 2115 | } |
| 2116 | |
| 2117 | { |
| 2118 | // Copy starting near end of b to c |
| 2119 | b.fill(++cntr); |
| 2120 | c.fill(++cntr); |
| 2121 | const copied = b.copy(c, 0, b.length - Math.floor(c.length / 2)); |
| 2122 | strictEqual(copied, Math.floor(c.length / 2)); |
| 2123 | for (let i = 0; i < Math.floor(c.length / 2); i++) { |
| 2124 | strictEqual(c[i], b[b.length - Math.floor(c.length / 2) + i]); |
| 2125 | } |
| 2126 | for (let i = Math.floor(c.length / 2) + 1; i < c.length; i++) { |
| 2127 | strictEqual(c[c.length - 1], c[i]); |
| 2128 | } |
| 2129 | } |
| 2130 | |
| 2131 | { |
| 2132 | // Try to copy 513 bytes, and check we don't overrun c |
| 2133 | b.fill(++cntr); |
| 2134 | c.fill(++cntr); |
| 2135 | const copied = b.copy(c, 0, 0, 513); |
| 2136 | strictEqual(copied, c.length); |
| 2137 | for (let i = 0; i < c.length; i++) { |
| 2138 | strictEqual(c[i], b[i]); |
| 2139 | } |
| 2140 | } |
| 2141 | |
| 2142 | { |
| 2143 | // copy 768 bytes from b into b |
| 2144 | b.fill(++cntr); |
| 2145 | b.fill(++cntr, 256); |
| 2146 | const copied = b.copy(b, 0, 256, 1024); |
| 2147 | strictEqual(copied, 768); |
| 2148 | for (let i = 0; i < b.length; i++) { |
| 2149 | strictEqual(b[i], cntr); |
| 2150 | } |
| 2151 | } |
| 2152 | |
| 2153 | // Copy string longer than buffer length (failure will segfault) |
| 2154 | const bb = Buffer.allocUnsafe(10); |
| 2155 | bb.fill('hello crazy world'); |
| 2156 | |
| 2157 | // Try to copy from before the beginning of b. Should not throw. |
| 2158 | b.copy(c, 0, 100, 10); |
| 2159 | |
| 2160 | // Throw with invalid source type |
| 2161 | throws(() => Buffer.prototype.copy.call(0), { |
| 2162 | code: 'ERR_INVALID_ARG_TYPE', |
| 2163 | name: 'TypeError', |
| 2164 | }); |
| 2165 | |
| 2166 | // Copy throws at negative targetStart |
| 2167 | throws(() => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), -1, 0), { |
| 2168 | code: 'ERR_OUT_OF_RANGE', |
| 2169 | name: 'RangeError', |
| 2170 | message: |
| 2171 | 'The value of "targetStart" is out of range. ' + |
| 2172 | 'It must be >= 0. Received -1', |
| 2173 | }); |
| 2174 | |
| 2175 | // Copy throws at negative sourceStart |
| 2176 | throws(() => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), 0, -1), { |
| 2177 | code: 'ERR_OUT_OF_RANGE', |
| 2178 | name: 'RangeError', |
| 2179 | message: |
| 2180 | 'The value of "sourceStart" is out of range. ' + |
| 2181 | 'It must be >= 0. Received -1', |
| 2182 | }); |
| 2183 | |
| 2184 | { |
| 2185 | // Check sourceEnd resets to targetEnd if former is greater than the latter |
| 2186 | b.fill(++cntr); |
| 2187 | c.fill(++cntr); |
| 2188 | b.copy(c, 0, 0, 1025); |
| 2189 | for (let i = 0; i < c.length; i++) { |
| 2190 | strictEqual(c[i], b[i]); |
| 2191 | } |
| 2192 | } |
| 2193 | |
| 2194 | // Throw with negative sourceEnd |
| 2195 | throws(() => b.copy(c, 0, 0, -1), { |
| 2196 | code: 'ERR_OUT_OF_RANGE', |
| 2197 | name: 'RangeError', |
| 2198 | message: |
| 2199 | 'The value of "sourceEnd" is out of range. ' + |
| 2200 | 'It must be >= 0. Received -1', |
| 2201 | }); |
| 2202 | |
| 2203 | // When sourceStart is greater than sourceEnd, zero copied |
| 2204 | strictEqual(b.copy(c, 0, 100, 10), 0); |
| 2205 | |
| 2206 | // When targetStart > targetLength, zero copied |
| 2207 | strictEqual(b.copy(c, 512, 0, 10), 0); |
| 2208 | |
| 2209 | // Test that the `target` can be a Uint8Array. |
| 2210 | { |
| 2211 | const d = new Uint8Array(c); |
| 2212 | // copy 512 bytes, from 0 to 512. |
| 2213 | b.fill(++cntr); |
| 2214 | d.fill(++cntr); |
| 2215 | const copied = b.copy(d, 0, 0, 512); |
| 2216 | strictEqual(copied, 512); |
| 2217 | for (let i = 0; i < d.length; i++) { |
| 2218 | strictEqual(d[i], b[i]); |
| 2219 | } |
| 2220 | } |
| 2221 | |
| 2222 | // Test that the source can be a Uint8Array, too. |
| 2223 | { |
| 2224 | const e = new Uint8Array(b); |
| 2225 | // copy 512 bytes, from 0 to 512. |
| 2226 | e.fill(++cntr); |
| 2227 | c.fill(++cntr); |
| 2228 | const copied = Buffer.prototype.copy.call(e, c, 0, 0, 512); |
| 2229 | strictEqual(copied, 512); |
| 2230 | for (let i = 0; i < c.length; i++) { |
| 2231 | strictEqual(c[i], e[i]); |
| 2232 | } |
| 2233 | } |
| 2234 | |
| 2235 | // https://github.com/nodejs/node/issues/23668: Do not crash for invalid input. |
| 2236 | c.fill('c'); |
| 2237 | b.copy(c, 'not a valid offset'); |
| 2238 | // Make sure this acted like a regular copy with `0` offset. |
| 2239 | deepStrictEqual(c, b.slice(0, c.length)); |
| 2240 | |
| 2241 | { |
| 2242 | c.fill('C'); |
| 2243 | throws(() => { |
| 2244 | b.copy(c, { |
| 2245 | [Symbol.toPrimitive]() { |
| 2246 | throw new Error('foo'); |
| 2247 | }, |
| 2248 | }); |
| 2249 | }, /foo/); |
| 2250 | // No copying took place: |
| 2251 | deepStrictEqual(c.toString(), 'C'.repeat(c.length)); |
| 2252 | } |
| 2253 | }, |
| 2254 | }; |
| 2255 | |
| 2256 | export const equals = { |
| 2257 | test(ctrl, env, ctx) { |
| 2258 | const b = Buffer.from('abcdf'); |
| 2259 | const c = Buffer.from('abcdf'); |
| 2260 | const d = Buffer.from('abcde'); |
| 2261 | const e = Buffer.from('abcdef'); |
| 2262 | |
| 2263 | ok(b.equals(c)); |
| 2264 | ok(!c.equals(d)); |
| 2265 | ok(!d.equals(e)); |
| 2266 | ok(d.equals(d)); |
| 2267 | ok(d.equals(new Uint8Array([0x61, 0x62, 0x63, 0x64, 0x65]))); |
| 2268 | |
| 2269 | throws(() => Buffer.alloc(1).equals('abc'), { |
| 2270 | code: 'ERR_INVALID_ARG_TYPE', |
| 2271 | name: 'TypeError', |
| 2272 | }); |
| 2273 | }, |
| 2274 | }; |
| 2275 | |
| 2276 | export const failedAllocTypedArrays = { |
| 2277 | test(ctrl, env, ctx) { |
| 2278 | // Test failed or zero-sized Buffer allocations not affecting typed arrays. |
| 2279 | // This test exists because of a regression that occurred. Because Buffer |
| 2280 | // instances are allocated with the same underlying allocator as TypedArrays, |
| 2281 | // but Buffer's can optional be non-zero filled, there was a regression that |
| 2282 | // occurred when a Buffer allocated failed, the internal flag specifying |
| 2283 | // whether or not to zero-fill was not being reset, causing TypedArrays to |
| 2284 | // allocate incorrectly. |
| 2285 | const zeroArray = new Uint32Array(10).fill(0); |
| 2286 | const sizes = [1e10, 0, 0.1, -1, 'a', undefined, null, NaN]; |
| 2287 | const allocators = [ |
| 2288 | Buffer, |
| 2289 | SlowBuffer, |
| 2290 | Buffer.alloc, |
| 2291 | Buffer.allocUnsafe, |
| 2292 | Buffer.allocUnsafeSlow, |
| 2293 | ]; |
| 2294 | for (const allocator of allocators) { |
| 2295 | for (const size of sizes) { |
| 2296 | try { |
| 2297 | // Some of these allocations are known to fail. If they do, |
| 2298 | // Uint32Array should still produce a zeroed out result. |
| 2299 | allocator(size); |
| 2300 | } catch { |
| 2301 | deepStrictEqual(zeroArray, new Uint32Array(10)); |
| 2302 | } |
| 2303 | } |
| 2304 | } |
| 2305 | }, |
| 2306 | }; |
| 2307 | |
| 2308 | export const fakes = { |
| 2309 | test(ctrl, env, ctx) { |
| 2310 | function FakeBuffer() {} |
| 2311 | Object.setPrototypeOf(FakeBuffer, Buffer); |
| 2312 | Object.setPrototypeOf(FakeBuffer.prototype, Buffer.prototype); |
| 2313 | |
| 2314 | const fb = new FakeBuffer(); |
| 2315 | |
| 2316 | throws(function () { |
| 2317 | Buffer.from(fb); |
| 2318 | }, TypeError); |
| 2319 | |
| 2320 | throws(function () { |
| 2321 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions |
| 2322 | +Buffer.prototype; |
| 2323 | }, TypeError); |
| 2324 | |
| 2325 | throws(function () { |
| 2326 | Buffer.compare(fb, Buffer.alloc(0)); |
| 2327 | }, TypeError); |
| 2328 | |
| 2329 | throws(function () { |
| 2330 | fb.write('foo'); |
| 2331 | }, TypeError); |
| 2332 | |
| 2333 | throws(function () { |
| 2334 | Buffer.concat([fb, fb]); |
| 2335 | }, TypeError); |
| 2336 | |
| 2337 | throws(function () { |
| 2338 | fb.toString(); |
| 2339 | }, TypeError); |
| 2340 | |
| 2341 | throws(function () { |
| 2342 | fb.equals(Buffer.alloc(0)); |
| 2343 | }, TypeError); |
| 2344 | |
| 2345 | throws(function () { |
| 2346 | fb.indexOf(5); |
| 2347 | }, TypeError); |
| 2348 | |
| 2349 | throws(function () { |
| 2350 | fb.readFloatLE(0); |
| 2351 | }, TypeError); |
| 2352 | |
| 2353 | throws(function () { |
| 2354 | fb.writeFloatLE(0); |
| 2355 | }, TypeError); |
| 2356 | |
| 2357 | throws(function () { |
| 2358 | fb.fill(0); |
| 2359 | }, TypeError); |
| 2360 | }, |
| 2361 | }; |
| 2362 | |
| 2363 | export const fill = { |
| 2364 | test(ctrl, env, ctx) { |
| 2365 | const SIZE = 28; |
| 2366 | const buf1 = Buffer.allocUnsafe(SIZE); |
| 2367 | const buf2 = Buffer.allocUnsafe(SIZE); |
| 2368 | |
| 2369 | // Default encoding |
| 2370 | testBufs('abc'); |
| 2371 | testBufs('\u0222aa'); |
| 2372 | testBufs('a\u0234b\u0235c\u0236'); |
| 2373 | testBufs('abc', 4); |
| 2374 | testBufs('abc', 5); |
| 2375 | testBufs('abc', SIZE); |
| 2376 | testBufs('\u0222aa', 2); |
| 2377 | testBufs('\u0222aa', 8); |
| 2378 | testBufs('a\u0234b\u0235c\u0236', 4); |
| 2379 | testBufs('a\u0234b\u0235c\u0236', 12); |
| 2380 | testBufs('abc', 4, 1); |
| 2381 | testBufs('abc', 5, 1); |
| 2382 | testBufs('\u0222aa', 8, 1); |
| 2383 | testBufs('a\u0234b\u0235c\u0236', 4, 1); |
| 2384 | testBufs('a\u0234b\u0235c\u0236', 12, 1); |
| 2385 | |
| 2386 | // UTF8 |
| 2387 | testBufs('abc', 'utf8'); |
| 2388 | testBufs('\u0222aa', 'utf8'); |
| 2389 | testBufs('a\u0234b\u0235c\u0236', 'utf8'); |
| 2390 | testBufs('abc', 4, 'utf8'); |
| 2391 | testBufs('abc', 5, 'utf8'); |
| 2392 | testBufs('abc', SIZE, 'utf8'); |
| 2393 | testBufs('\u0222aa', 2, 'utf8'); |
| 2394 | testBufs('\u0222aa', 8, 'utf8'); |
| 2395 | testBufs('a\u0234b\u0235c\u0236', 4, 'utf8'); |
| 2396 | testBufs('a\u0234b\u0235c\u0236', 12, 'utf8'); |
| 2397 | testBufs('abc', 4, 1, 'utf8'); |
| 2398 | testBufs('abc', 5, 1, 'utf8'); |
| 2399 | testBufs('\u0222aa', 8, 1, 'utf8'); |
| 2400 | testBufs('a\u0234b\u0235c\u0236', 4, 1, 'utf8'); |
| 2401 | testBufs('a\u0234b\u0235c\u0236', 12, 1, 'utf8'); |
| 2402 | strictEqual(Buffer.allocUnsafe(1).fill(0).fill('\u0222')[0], 0xc8); |
| 2403 | |
| 2404 | // BINARY |
| 2405 | testBufs('abc', 'binary'); |
| 2406 | testBufs('\u0222aa', 'binary'); |
| 2407 | testBufs('a\u0234b\u0235c\u0236', 'binary'); |
| 2408 | testBufs('abc', 4, 'binary'); |
| 2409 | testBufs('abc', 5, 'binary'); |
| 2410 | testBufs('abc', SIZE, 'binary'); |
| 2411 | testBufs('\u0222aa', 2, 'binary'); |
| 2412 | testBufs('\u0222aa', 8, 'binary'); |
| 2413 | testBufs('a\u0234b\u0235c\u0236', 4, 'binary'); |
| 2414 | testBufs('a\u0234b\u0235c\u0236', 12, 'binary'); |
| 2415 | testBufs('abc', 4, 1, 'binary'); |
| 2416 | testBufs('abc', 5, 1, 'binary'); |
| 2417 | testBufs('\u0222aa', 8, 1, 'binary'); |
| 2418 | testBufs('a\u0234b\u0235c\u0236', 4, 1, 'binary'); |
| 2419 | testBufs('a\u0234b\u0235c\u0236', 12, 1, 'binary'); |
| 2420 | |
| 2421 | // LATIN1 |
| 2422 | testBufs('abc', 'latin1'); |
| 2423 | testBufs('\u0222aa', 'latin1'); |
| 2424 | testBufs('a\u0234b\u0235c\u0236', 'latin1'); |
| 2425 | testBufs('abc', 4, 'latin1'); |
| 2426 | testBufs('abc', 5, 'latin1'); |
| 2427 | testBufs('abc', SIZE, 'latin1'); |
| 2428 | testBufs('\u0222aa', 2, 'latin1'); |
| 2429 | testBufs('\u0222aa', 8, 'latin1'); |
| 2430 | testBufs('a\u0234b\u0235c\u0236', 4, 'latin1'); |
| 2431 | testBufs('a\u0234b\u0235c\u0236', 12, 'latin1'); |
| 2432 | testBufs('abc', 4, 1, 'latin1'); |
| 2433 | testBufs('abc', 5, 1, 'latin1'); |
| 2434 | testBufs('\u0222aa', 8, 1, 'latin1'); |
| 2435 | testBufs('a\u0234b\u0235c\u0236', 4, 1, 'latin1'); |
| 2436 | testBufs('a\u0234b\u0235c\u0236', 12, 1, 'latin1'); |
| 2437 | |
| 2438 | // UCS2 |
| 2439 | testBufs('abc', 'ucs2'); |
| 2440 | testBufs('\u0222aa', 'ucs2'); |
| 2441 | testBufs('a\u0234b\u0235c\u0236', 'ucs2'); |
| 2442 | testBufs('abc', 4, 'ucs2'); |
| 2443 | testBufs('abc', SIZE, 'ucs2'); |
| 2444 | testBufs('\u0222aa', 2, 'ucs2'); |
| 2445 | testBufs('\u0222aa', 8, 'ucs2'); |
| 2446 | testBufs('a\u0234b\u0235c\u0236', 4, 'ucs2'); |
| 2447 | testBufs('a\u0234b\u0235c\u0236', 12, 'ucs2'); |
| 2448 | testBufs('abc', 4, 1, 'ucs2'); |
| 2449 | testBufs('abc', 5, 1, 'ucs2'); |
| 2450 | testBufs('\u0222aa', 8, 1, 'ucs2'); |
| 2451 | testBufs('a\u0234b\u0235c\u0236', 4, 1, 'ucs2'); |
| 2452 | testBufs('a\u0234b\u0235c\u0236', 12, 1, 'ucs2'); |
| 2453 | strictEqual(Buffer.allocUnsafe(1).fill('\u0222', 'ucs2')[0], 0x22); |
| 2454 | |
| 2455 | // HEX |
| 2456 | testBufs('616263', 'hex'); |
| 2457 | testBufs('c8a26161', 'hex'); |
| 2458 | testBufs('61c8b462c8b563c8b6', 'hex'); |
| 2459 | testBufs('616263', 4, 'hex'); |
| 2460 | testBufs('616263', 5, 'hex'); |
| 2461 | testBufs('616263', SIZE, 'hex'); |
| 2462 | testBufs('c8a26161', 2, 'hex'); |
| 2463 | testBufs('c8a26161', 8, 'hex'); |
| 2464 | testBufs('61c8b462c8b563c8b6', 4, 'hex'); |
| 2465 | testBufs('61c8b462c8b563c8b6', 12, 'hex'); |
| 2466 | testBufs('616263', 4, 1, 'hex'); |
| 2467 | testBufs('616263', 5, 1, 'hex'); |
| 2468 | testBufs('c8a26161', 8, 1, 'hex'); |
| 2469 | testBufs('61c8b462c8b563c8b6', 4, 1, 'hex'); |
| 2470 | testBufs('61c8b462c8b563c8b6', 12, 1, 'hex'); |
| 2471 | |
| 2472 | throws( |
| 2473 | () => { |
| 2474 | const buf = Buffer.allocUnsafe(SIZE); |
| 2475 | |
| 2476 | buf.fill('yKJh', 'hex'); |
| 2477 | }, |
| 2478 | { |
| 2479 | name: 'TypeError', |
| 2480 | } |
| 2481 | ); |
| 2482 | |
| 2483 | throws( |
| 2484 | () => { |
| 2485 | const buf = Buffer.allocUnsafe(SIZE); |
| 2486 | |
| 2487 | buf.fill('\u0222', 'hex'); |
| 2488 | }, |
| 2489 | { |
| 2490 | name: 'TypeError', |
| 2491 | } |
| 2492 | ); |
| 2493 | |
| 2494 | // BASE64 |
| 2495 | testBufs('YWJj', 'base64'); |
| 2496 | testBufs('yKJhYQ==', 'base64'); |
| 2497 | testBufs('Yci0Ysi1Y8i2', 'base64'); |
| 2498 | testBufs('YWJj', 4, 'base64'); |
| 2499 | testBufs('YWJj', SIZE, 'base64'); |
| 2500 | testBufs('yKJhYQ==', 2, 'base64'); |
| 2501 | testBufs('yKJhYQ==', 8, 'base64'); |
| 2502 | testBufs('Yci0Ysi1Y8i2', 4, 'base64'); |
| 2503 | testBufs('Yci0Ysi1Y8i2', 12, 'base64'); |
| 2504 | testBufs('YWJj', 4, 1, 'base64'); |
| 2505 | testBufs('YWJj', 5, 1, 'base64'); |
| 2506 | testBufs('yKJhYQ==', 8, 1, 'base64'); |
| 2507 | testBufs('Yci0Ysi1Y8i2', 4, 1, 'base64'); |
| 2508 | testBufs('Yci0Ysi1Y8i2', 12, 1, 'base64'); |
| 2509 | |
| 2510 | // BASE64URL |
| 2511 | testBufs('YWJj', 'base64url'); |
| 2512 | testBufs('yKJhYQ', 'base64url'); |
| 2513 | testBufs('Yci0Ysi1Y8i2', 'base64url'); |
| 2514 | testBufs('YWJj', 4, 'base64url'); |
| 2515 | testBufs('YWJj', SIZE, 'base64url'); |
| 2516 | testBufs('yKJhYQ', 2, 'base64url'); |
| 2517 | testBufs('yKJhYQ', 8, 'base64url'); |
| 2518 | testBufs('Yci0Ysi1Y8i2', 4, 'base64url'); |
| 2519 | testBufs('Yci0Ysi1Y8i2', 12, 'base64url'); |
| 2520 | testBufs('YWJj', 4, 1, 'base64url'); |
| 2521 | testBufs('YWJj', 5, 1, 'base64url'); |
| 2522 | testBufs('yKJhYQ', 8, 1, 'base64url'); |
| 2523 | testBufs('Yci0Ysi1Y8i2', 4, 1, 'base64url'); |
| 2524 | testBufs('Yci0Ysi1Y8i2', 12, 1, 'base64url'); |
| 2525 | |
| 2526 | function deepStrictEqualValues(buf, arr) { |
| 2527 | for (const [index, value] of buf.entries()) { |
| 2528 | deepStrictEqual(value, arr[index]); |
| 2529 | } |
| 2530 | } |
| 2531 | |
| 2532 | const buf2Fill = Buffer.allocUnsafe(1).fill(2); |
| 2533 | deepStrictEqualValues(genBuffer(4, [buf2Fill]), [2, 2, 2, 2]); |
| 2534 | deepStrictEqualValues(genBuffer(4, [buf2Fill, 1]), [0, 2, 2, 2]); |
| 2535 | deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 3]), [0, 2, 2, 0]); |
| 2536 | deepStrictEqualValues(genBuffer(4, [buf2Fill, 1, 1]), [0, 0, 0, 0]); |
| 2537 | const hexBufFill = Buffer.allocUnsafe(2).fill(0).fill('0102', 'hex'); |
| 2538 | deepStrictEqualValues(genBuffer(4, [hexBufFill]), [1, 2, 1, 2]); |
| 2539 | deepStrictEqualValues(genBuffer(4, [hexBufFill, 1]), [0, 1, 2, 1]); |
| 2540 | deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 3]), [0, 1, 2, 0]); |
| 2541 | deepStrictEqualValues(genBuffer(4, [hexBufFill, 1, 1]), [0, 0, 0, 0]); |
| 2542 | |
| 2543 | // Check exceptions |
| 2544 | [ |
| 2545 | [0, -1], |
| 2546 | [0, 0, buf1.length + 1], |
| 2547 | ['', -1], |
| 2548 | ['', 0, buf1.length + 1], |
| 2549 | ['', 1, -1], |
| 2550 | ].forEach((args) => { |
| 2551 | throws(() => buf1.fill(...args), { name: 'RangeError' }); |
| 2552 | }); |
| 2553 | |
| 2554 | throws(() => buf1.fill('a', 0, buf1.length, 'node rocks!'), { |
| 2555 | code: 'ERR_UNKNOWN_ENCODING', |
| 2556 | name: 'TypeError', |
| 2557 | message: 'Unknown encoding: node rocks!', |
| 2558 | }); |
| 2559 | |
| 2560 | [ |
| 2561 | ['a', 0, 0, NaN], |
| 2562 | ['a', 0, 0, false], |
| 2563 | ].forEach((args) => { |
| 2564 | throws(() => buf1.fill(...args), { |
| 2565 | name: 'TypeError', |
| 2566 | }); |
| 2567 | }); |
| 2568 | |
| 2569 | throws(() => buf1.fill('a', 0, 0, 'foo'), { |
| 2570 | code: 'ERR_UNKNOWN_ENCODING', |
| 2571 | name: 'TypeError', |
| 2572 | message: 'Unknown encoding: foo', |
| 2573 | }); |
| 2574 | |
| 2575 | function genBuffer(size, args) { |
| 2576 | const b = Buffer.allocUnsafe(size); |
| 2577 | return b.fill(0).fill.apply(b, args); |
| 2578 | } |
| 2579 | |
| 2580 | function bufReset() { |
| 2581 | buf1.fill(0); |
| 2582 | buf2.fill(0); |
| 2583 | } |
| 2584 | |
| 2585 | // This is mostly accurate. Except write() won't write partial bytes to the |
| 2586 | // string while fill() blindly copies bytes into memory. To account for that an |
| 2587 | // error will be thrown if not all the data can be written, and the SIZE has |
| 2588 | // been massaged to work with the input characters. |
| 2589 | function writeToFill(string, offset, end, encoding) { |
| 2590 | if (typeof offset === 'string') { |
| 2591 | encoding = offset; |
| 2592 | offset = 0; |
| 2593 | end = buf2.length; |
| 2594 | } else if (typeof end === 'string') { |
| 2595 | encoding = end; |
| 2596 | end = buf2.length; |
| 2597 | } else if (end === undefined) { |
| 2598 | end = buf2.length; |
| 2599 | } |
| 2600 | |
| 2601 | // Should never be reached. |
| 2602 | // eslint-disable-next-line no-undef |
| 2603 | if (offset < 0 || end > buf2.length) throw new ERR_OUT_OF_RANGE(); |
| 2604 | |
| 2605 | if (end <= offset) return buf2; |
| 2606 | |
| 2607 | offset >>>= 0; |
| 2608 | end >>>= 0; |
| 2609 | ok(offset <= buf2.length); |
| 2610 | |
| 2611 | // Convert "end" to "length" (which write understands). |
| 2612 | const length = end - offset < 0 ? 0 : end - offset; |
| 2613 | |
| 2614 | let wasZero = false; |
| 2615 | do { |
| 2616 | const written = buf2.write(string, offset, length, encoding); |
| 2617 | offset += written; |
| 2618 | // Safety check in case write falls into infinite loop. |
| 2619 | if (written === 0) { |
| 2620 | if (wasZero) throw new Error('Could not write all data to Buffer'); |
| 2621 | else wasZero = true; |
| 2622 | } |
| 2623 | } while (offset < buf2.length); |
| 2624 | |
| 2625 | return buf2; |
| 2626 | } |
| 2627 | |
| 2628 | function testBufs(string, offset, length, encoding) { |
| 2629 | bufReset(); |
| 2630 | buf1.fill.apply(buf1, arguments); |
| 2631 | // Swap bytes on BE archs for ucs2 encoding. |
| 2632 | deepStrictEqual( |
| 2633 | buf1.fill.apply(buf1, arguments), |
| 2634 | writeToFill.apply(null, arguments) |
| 2635 | ); |
| 2636 | } |
| 2637 | |
| 2638 | // Make sure these throw. |
| 2639 | throws(() => Buffer.allocUnsafe(8).fill('a', -1), { |
| 2640 | code: 'ERR_OUT_OF_RANGE', |
| 2641 | }); |
| 2642 | throws(() => Buffer.allocUnsafe(8).fill('a', 0, 9), { |
| 2643 | code: 'ERR_OUT_OF_RANGE', |
| 2644 | }); |
| 2645 | |
| 2646 | // // Make sure this doesn't hang indefinitely. |
| 2647 | Buffer.allocUnsafe(8).fill(''); |
| 2648 | Buffer.alloc(8, ''); |
| 2649 | |
| 2650 | { |
| 2651 | const buf = Buffer.alloc(64, 10); |
| 2652 | for (let i = 0; i < buf.length; i++) strictEqual(buf[i], 10); |
| 2653 | |
| 2654 | buf.fill(11, 0, buf.length >> 1); |
| 2655 | for (let i = 0; i < buf.length >> 1; i++) strictEqual(buf[i], 11); |
| 2656 | for (let i = (buf.length >> 1) + 1; i < buf.length; i++) |
| 2657 | strictEqual(buf[i], 10); |
| 2658 | |
| 2659 | buf.fill('h'); |
| 2660 | for (let i = 0; i < buf.length; i++) |
| 2661 | strictEqual(buf[i], 'h'.charCodeAt(0)); |
| 2662 | |
| 2663 | buf.fill(0); |
| 2664 | for (let i = 0; i < buf.length; i++) strictEqual(buf[i], 0); |
| 2665 | |
| 2666 | buf.fill(null); |
| 2667 | for (let i = 0; i < buf.length; i++) strictEqual(buf[i], 0); |
| 2668 | |
| 2669 | buf.fill(1, 16, 32); |
| 2670 | for (let i = 0; i < 16; i++) strictEqual(buf[i], 0); |
| 2671 | for (let i = 16; i < 32; i++) strictEqual(buf[i], 1); |
| 2672 | for (let i = 32; i < buf.length; i++) strictEqual(buf[i], 0); |
| 2673 | } |
| 2674 | |
| 2675 | { |
| 2676 | const buf = Buffer.alloc(10, 'abc'); |
| 2677 | strictEqual(buf.toString(), 'abcabcabca'); |
| 2678 | buf.fill('է'); |
| 2679 | strictEqual(buf.toString(), 'էէէէէ'); |
| 2680 | } |
| 2681 | |
| 2682 | // Make sure "end" is properly checked, even if it's magically mangled using |
| 2683 | // Symbol.toPrimitive. |
| 2684 | { |
| 2685 | throws( |
| 2686 | () => { |
| 2687 | const end = { |
| 2688 | [Symbol.toPrimitive]() { |
| 2689 | return 1; |
| 2690 | }, |
| 2691 | }; |
| 2692 | Buffer.alloc(1).fill(Buffer.alloc(1), 0, end); |
| 2693 | }, |
| 2694 | { |
| 2695 | code: 'ERR_INVALID_ARG_TYPE', |
| 2696 | message: |
| 2697 | 'The "end" argument must be of type number. Received an ' + |
| 2698 | 'instance of Object', |
| 2699 | } |
| 2700 | ); |
| 2701 | } |
| 2702 | |
| 2703 | // Test that bypassing 'length' won't cause an abort. |
| 2704 | // Node.js throws an error in this case because it's often the case that the |
| 2705 | // Buffer might contain uninitialized memory and we need to prevent overreads. |
| 2706 | // However, our implementation is backed entirely by ArrayBuffer/Uint8Array |
| 2707 | // and always has initialized memory, so if the user does something funky |
| 2708 | // like this, they'll get back undefineds. |
| 2709 | { |
| 2710 | const buf = Buffer.from('w00t'); |
| 2711 | Object.defineProperty(buf, 'length', { |
| 2712 | value: 1337, |
| 2713 | enumerable: true, |
| 2714 | }); |
| 2715 | buf.fill(''); |
| 2716 | } |
| 2717 | |
| 2718 | deepStrictEqual( |
| 2719 | Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), |
| 2720 | Buffer.from('61006200610062006100620061006200', 'hex') |
| 2721 | ); |
| 2722 | |
| 2723 | deepStrictEqual( |
| 2724 | Buffer.allocUnsafeSlow(15).fill('ab', 'utf16le'), |
| 2725 | Buffer.from('610062006100620061006200610062', 'hex') |
| 2726 | ); |
| 2727 | |
| 2728 | deepStrictEqual( |
| 2729 | Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), |
| 2730 | Buffer.from('61006200610062006100620061006200', 'hex') |
| 2731 | ); |
| 2732 | deepStrictEqual( |
| 2733 | Buffer.allocUnsafeSlow(16).fill('a', 'utf16le'), |
| 2734 | Buffer.from('61006100610061006100610061006100', 'hex') |
| 2735 | ); |
| 2736 | |
| 2737 | strictEqual( |
| 2738 | Buffer.allocUnsafeSlow(16).fill('a', 'utf16le').toString('utf16le'), |
| 2739 | 'a'.repeat(8) |
| 2740 | ); |
| 2741 | strictEqual( |
| 2742 | Buffer.allocUnsafeSlow(16).fill('a', 'latin1').toString('latin1'), |
| 2743 | 'a'.repeat(16) |
| 2744 | ); |
| 2745 | strictEqual( |
| 2746 | Buffer.allocUnsafeSlow(16).fill('a', 'utf8').toString('utf8'), |
| 2747 | 'a'.repeat(16) |
| 2748 | ); |
| 2749 | |
| 2750 | strictEqual( |
| 2751 | Buffer.allocUnsafeSlow(16).fill('Љ', 'utf16le').toString('utf16le'), |
| 2752 | 'Љ'.repeat(8) |
| 2753 | ); |
| 2754 | strictEqual( |
| 2755 | Buffer.allocUnsafeSlow(16).fill('Љ', 'latin1').toString('latin1'), |
| 2756 | '\t'.repeat(16) |
| 2757 | ); |
| 2758 | strictEqual( |
| 2759 | Buffer.allocUnsafeSlow(16).fill('Љ', 'utf8').toString('utf8'), |
| 2760 | 'Љ'.repeat(8) |
| 2761 | ); |
| 2762 | |
| 2763 | throws( |
| 2764 | () => { |
| 2765 | const buf = Buffer.from('a'.repeat(1000)); |
| 2766 | |
| 2767 | buf.fill('This is not correctly encoded', 'hex'); |
| 2768 | }, |
| 2769 | { |
| 2770 | name: 'TypeError', |
| 2771 | } |
| 2772 | ); |
| 2773 | |
| 2774 | { |
| 2775 | const bufEmptyString = Buffer.alloc(5, ''); |
| 2776 | strictEqual(bufEmptyString.toString(), '\x00\x00\x00\x00\x00'); |
| 2777 | |
| 2778 | const bufEmptyArray = Buffer.alloc(5, []); |
| 2779 | strictEqual(bufEmptyArray.toString(), '\x00\x00\x00\x00\x00'); |
| 2780 | |
| 2781 | const bufEmptyBuffer = Buffer.alloc(5, Buffer.alloc(5)); |
| 2782 | strictEqual(bufEmptyBuffer.toString(), '\x00\x00\x00\x00\x00'); |
| 2783 | |
| 2784 | const bufZero = Buffer.alloc(5, 0); |
| 2785 | strictEqual(bufZero.toString(), '\x00\x00\x00\x00\x00'); |
| 2786 | } |
| 2787 | }, |
| 2788 | }; |
| 2789 | |
| 2790 | export const includes = { |
| 2791 | test(ctrl, env, ctx) { |
| 2792 | const b = Buffer.from('abcdef'); |
| 2793 | const buf_a = Buffer.from('a'); |
| 2794 | const buf_bc = Buffer.from('bc'); |
| 2795 | const buf_f = Buffer.from('f'); |
| 2796 | const buf_z = Buffer.from('z'); |
| 2797 | const buf_empty = Buffer.from(''); |
| 2798 | |
| 2799 | ok(b.includes('a')); |
| 2800 | ok(!b.includes('a', 1)); |
| 2801 | ok(!b.includes('a', -1)); |
| 2802 | ok(!b.includes('a', -4)); |
| 2803 | ok(b.includes('a', -b.length)); |
| 2804 | ok(b.includes('a', NaN)); |
| 2805 | ok(b.includes('a', -Infinity)); |
| 2806 | ok(!b.includes('a', Infinity)); |
| 2807 | ok(b.includes('bc')); |
| 2808 | ok(!b.includes('bc', 2)); |
| 2809 | ok(!b.includes('bc', -1)); |
| 2810 | ok(!b.includes('bc', -3)); |
| 2811 | ok(b.includes('bc', -5)); |
| 2812 | ok(b.includes('bc', NaN)); |
| 2813 | ok(b.includes('bc', -Infinity)); |
| 2814 | ok(!b.includes('bc', Infinity)); |
| 2815 | ok(b.includes('f'), b.length - 1); |
| 2816 | ok(!b.includes('z')); |
| 2817 | ok(b.includes('')); |
| 2818 | ok(b.includes('', 1)); |
| 2819 | ok(b.includes('', b.length + 1)); |
| 2820 | ok(b.includes('', Infinity)); |
| 2821 | ok(b.includes(buf_a)); |
| 2822 | ok(!b.includes(buf_a, 1)); |
| 2823 | ok(!b.includes(buf_a, -1)); |
| 2824 | ok(!b.includes(buf_a, -4)); |
| 2825 | ok(b.includes(buf_a, -b.length)); |
| 2826 | ok(b.includes(buf_a, NaN)); |
| 2827 | ok(b.includes(buf_a, -Infinity)); |
| 2828 | ok(!b.includes(buf_a, Infinity)); |
| 2829 | ok(b.includes(buf_bc)); |
| 2830 | ok(!b.includes(buf_bc, 2)); |
| 2831 | ok(!b.includes(buf_bc, -1)); |
| 2832 | ok(!b.includes(buf_bc, -3)); |
| 2833 | ok(b.includes(buf_bc, -5)); |
| 2834 | ok(b.includes(buf_bc, NaN)); |
| 2835 | ok(b.includes(buf_bc, -Infinity)); |
| 2836 | ok(!b.includes(buf_bc, Infinity)); |
| 2837 | ok(b.includes(buf_f), b.length - 1); |
| 2838 | ok(!b.includes(buf_z)); |
| 2839 | ok(b.includes(buf_empty)); |
| 2840 | ok(b.includes(buf_empty, 1)); |
| 2841 | ok(b.includes(buf_empty, b.length + 1)); |
| 2842 | ok(b.includes(buf_empty, Infinity)); |
| 2843 | ok(b.includes(0x61)); |
| 2844 | ok(!b.includes(0x61, 1)); |
| 2845 | ok(!b.includes(0x61, -1)); |
| 2846 | ok(!b.includes(0x61, -4)); |
| 2847 | ok(b.includes(0x61, -b.length)); |
| 2848 | ok(b.includes(0x61, NaN)); |
| 2849 | ok(b.includes(0x61, -Infinity)); |
| 2850 | ok(!b.includes(0x61, Infinity)); |
| 2851 | ok(!b.includes(0x0)); |
| 2852 | |
| 2853 | // test offsets |
| 2854 | ok(b.includes('d', 2)); |
| 2855 | ok(b.includes('f', 5)); |
| 2856 | ok(b.includes('f', -1)); |
| 2857 | ok(!b.includes('f', 6)); |
| 2858 | |
| 2859 | ok(b.includes(Buffer.from('d'), 2)); |
| 2860 | ok(b.includes(Buffer.from('f'), 5)); |
| 2861 | ok(b.includes(Buffer.from('f'), -1)); |
| 2862 | ok(!b.includes(Buffer.from('f'), 6)); |
| 2863 | |
| 2864 | ok(!Buffer.from('ff').includes(Buffer.from('f'), 1, 'ucs2')); |
| 2865 | |
| 2866 | // test hex encoding |
| 2867 | strictEqual( |
| 2868 | Buffer.from(b.toString('hex'), 'hex').includes('64', 0, 'hex'), |
| 2869 | true |
| 2870 | ); |
| 2871 | strictEqual( |
| 2872 | Buffer.from(b.toString('hex'), 'hex').includes( |
| 2873 | Buffer.from('64', 'hex'), |
| 2874 | 0, |
| 2875 | 'hex' |
| 2876 | ), |
| 2877 | true |
| 2878 | ); |
| 2879 | |
| 2880 | // Test base64 encoding |
| 2881 | strictEqual( |
| 2882 | Buffer.from(b.toString('base64'), 'base64').includes('ZA==', 0, 'base64'), |
| 2883 | true |
| 2884 | ); |
| 2885 | strictEqual( |
| 2886 | Buffer.from(b.toString('base64'), 'base64').includes( |
| 2887 | Buffer.from('ZA==', 'base64'), |
| 2888 | 0, |
| 2889 | 'base64' |
| 2890 | ), |
| 2891 | true |
| 2892 | ); |
| 2893 | |
| 2894 | // test ascii encoding |
| 2895 | strictEqual( |
| 2896 | Buffer.from(b.toString('ascii'), 'ascii').includes('d', 0, 'ascii'), |
| 2897 | true |
| 2898 | ); |
| 2899 | strictEqual( |
| 2900 | Buffer.from(b.toString('ascii'), 'ascii').includes( |
| 2901 | Buffer.from('d', 'ascii'), |
| 2902 | 0, |
| 2903 | 'ascii' |
| 2904 | ), |
| 2905 | true |
| 2906 | ); |
| 2907 | |
| 2908 | // Test latin1 encoding |
| 2909 | strictEqual( |
| 2910 | Buffer.from(b.toString('latin1'), 'latin1').includes('d', 0, 'latin1'), |
| 2911 | true |
| 2912 | ); |
| 2913 | strictEqual( |
| 2914 | Buffer.from(b.toString('latin1'), 'latin1').includes( |
| 2915 | Buffer.from('d', 'latin1'), |
| 2916 | 0, |
| 2917 | 'latin1' |
| 2918 | ), |
| 2919 | true |
| 2920 | ); |
| 2921 | |
| 2922 | // Test binary encoding |
| 2923 | strictEqual( |
| 2924 | Buffer.from(b.toString('binary'), 'binary').includes('d', 0, 'binary'), |
| 2925 | true |
| 2926 | ); |
| 2927 | strictEqual( |
| 2928 | Buffer.from(b.toString('binary'), 'binary').includes( |
| 2929 | Buffer.from('d', 'binary'), |
| 2930 | 0, |
| 2931 | 'binary' |
| 2932 | ), |
| 2933 | true |
| 2934 | ); |
| 2935 | |
| 2936 | // test ucs2 encoding |
| 2937 | let twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); |
| 2938 | |
| 2939 | ok(twoByteString.includes('\u0395', 4, 'ucs2')); |
| 2940 | ok(twoByteString.includes('\u03a3', -4, 'ucs2')); |
| 2941 | ok(twoByteString.includes('\u03a3', -6, 'ucs2')); |
| 2942 | ok(twoByteString.includes(Buffer.from('\u03a3', 'ucs2'), -6, 'ucs2')); |
| 2943 | ok(!twoByteString.includes('\u03a3', -2, 'ucs2')); |
| 2944 | |
| 2945 | const mixedByteStringUcs2 = Buffer.from( |
| 2946 | '\u039a\u0391abc\u03a3\u03a3\u0395', |
| 2947 | 'ucs2' |
| 2948 | ); |
| 2949 | ok(mixedByteStringUcs2.includes('bc', 0, 'ucs2')); |
| 2950 | ok(mixedByteStringUcs2.includes('\u03a3', 0, 'ucs2')); |
| 2951 | ok(!mixedByteStringUcs2.includes('\u0396', 0, 'ucs2')); |
| 2952 | |
| 2953 | ok(mixedByteStringUcs2.includes(Buffer.from('bc', 'ucs2'), 0, 'ucs2')); |
| 2954 | ok(mixedByteStringUcs2.includes(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2')); |
| 2955 | ok(!mixedByteStringUcs2.includes(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2')); |
| 2956 | |
| 2957 | twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); |
| 2958 | |
| 2959 | // Test single char pattern |
| 2960 | ok(twoByteString.includes('\u039a', 0, 'ucs2')); |
| 2961 | ok(twoByteString.includes('\u0391', 0, 'ucs2'), 'Alpha'); |
| 2962 | ok(twoByteString.includes('\u03a3', 0, 'ucs2'), 'First Sigma'); |
| 2963 | ok(twoByteString.includes('\u03a3', 6, 'ucs2'), 'Second Sigma'); |
| 2964 | ok(twoByteString.includes('\u0395', 0, 'ucs2'), 'Epsilon'); |
| 2965 | ok(!twoByteString.includes('\u0392', 0, 'ucs2'), 'Not beta'); |
| 2966 | |
| 2967 | // Test multi-char pattern |
| 2968 | ok(twoByteString.includes('\u039a\u0391', 0, 'ucs2'), 'Lambda Alpha'); |
| 2969 | ok(twoByteString.includes('\u0391\u03a3', 0, 'ucs2'), 'Alpha Sigma'); |
| 2970 | ok(twoByteString.includes('\u03a3\u03a3', 0, 'ucs2'), 'Sigma Sigma'); |
| 2971 | ok(twoByteString.includes('\u03a3\u0395', 0, 'ucs2'), 'Sigma Epsilon'); |
| 2972 | |
| 2973 | const mixedByteStringUtf8 = Buffer.from( |
| 2974 | '\u039a\u0391abc\u03a3\u03a3\u0395' |
| 2975 | ); |
| 2976 | ok(mixedByteStringUtf8.includes('bc')); |
| 2977 | ok(mixedByteStringUtf8.includes('bc', 5)); |
| 2978 | ok(mixedByteStringUtf8.includes('bc', -8)); |
| 2979 | ok(mixedByteStringUtf8.includes('\u03a3')); |
| 2980 | ok(!mixedByteStringUtf8.includes('\u0396')); |
| 2981 | |
| 2982 | // Test complex string includes algorithms. Only trigger for long strings. |
| 2983 | // Long string that isn't a simple repeat of a shorter string. |
| 2984 | let longString = 'A'; |
| 2985 | for (let i = 66; i < 76; i++) { |
| 2986 | // from 'B' to 'K' |
| 2987 | longString = longString + String.fromCharCode(i) + longString; |
| 2988 | } |
| 2989 | |
| 2990 | const longBufferString = Buffer.from(longString); |
| 2991 | |
| 2992 | // Pattern of 15 chars, repeated every 16 chars in long |
| 2993 | let pattern = 'ABACABADABACABA'; |
| 2994 | for (let i = 0; i < longBufferString.length - pattern.length; i += 7) { |
| 2995 | const includes = longBufferString.includes(pattern, i); |
| 2996 | ok(includes, `Long ABACABA...-string at index ${i}`); |
| 2997 | } |
| 2998 | ok(longBufferString.includes('AJABACA'), 'Long AJABACA, First J'); |
| 2999 | ok(longBufferString.includes('AJABACA', 511), 'Long AJABACA, Second J'); |
| 3000 | |
| 3001 | pattern = 'JABACABADABACABA'; |
| 3002 | ok(longBufferString.includes(pattern), 'Long JABACABA..., First J'); |
| 3003 | ok(longBufferString.includes(pattern, 512), 'Long JABACABA..., Second J'); |
| 3004 | |
| 3005 | // Search for a non-ASCII string in a pure ASCII string. |
| 3006 | const asciiString = Buffer.from( |
| 3007 | 'arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf' |
| 3008 | ); |
| 3009 | ok(!asciiString.includes('\x2061')); |
| 3010 | ok(asciiString.includes('leb', 0)); |
| 3011 | |
| 3012 | // Search in string containing many non-ASCII chars. |
| 3013 | const allCodePoints = []; |
| 3014 | for (let i = 0; i < 65534; i++) allCodePoints[i] = i; |
| 3015 | const allCharsString = |
| 3016 | String.fromCharCode.apply(String, allCodePoints) + |
| 3017 | String.fromCharCode(65534, 65535); |
| 3018 | const allCharsBufferUtf8 = Buffer.from(allCharsString); |
| 3019 | const allCharsBufferUcs2 = Buffer.from(allCharsString, 'ucs2'); |
| 3020 | |
| 3021 | // Search for string long enough to trigger complex search with ASCII pattern |
| 3022 | // and UC16 subject. |
| 3023 | ok(!allCharsBufferUtf8.includes('notfound')); |
| 3024 | ok(!allCharsBufferUcs2.includes('notfound')); |
| 3025 | |
| 3026 | // Find substrings in Utf8. |
| 3027 | let lengths = [1, 3, 15]; // Single char, simple and complex. |
| 3028 | let indices = [0x5, 0x60, 0x400, 0x680, 0x7ee, 0xff02, 0x16610, 0x2f77b]; |
| 3029 | for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) { |
| 3030 | for (let i = 0; i < indices.length; i++) { |
| 3031 | const index = indices[i]; |
| 3032 | let length = lengths[lengthIndex]; |
| 3033 | |
| 3034 | if (index + length > 0x7f) { |
| 3035 | length = 2 * length; |
| 3036 | } |
| 3037 | |
| 3038 | if (index + length > 0x7ff) { |
| 3039 | length = 3 * length; |
| 3040 | } |
| 3041 | |
| 3042 | if (index + length > 0xffff) { |
| 3043 | length = 4 * length; |
| 3044 | } |
| 3045 | |
| 3046 | const patternBufferUtf8 = allCharsBufferUtf8.slice( |
| 3047 | index, |
| 3048 | index + length |
| 3049 | ); |
| 3050 | ok(index, allCharsBufferUtf8.includes(patternBufferUtf8)); |
| 3051 | |
| 3052 | const patternStringUtf8 = patternBufferUtf8.toString(); |
| 3053 | ok(index, allCharsBufferUtf8.includes(patternStringUtf8)); |
| 3054 | } |
| 3055 | } |
| 3056 | |
| 3057 | // Find substrings in Usc2. |
| 3058 | lengths = [2, 4, 16]; // Single char, simple and complex. |
| 3059 | indices = [0x5, 0x65, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0]; |
| 3060 | for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) { |
| 3061 | for (let i = 0; i < indices.length; i++) { |
| 3062 | const index = indices[i] * 2; |
| 3063 | const length = lengths[lengthIndex]; |
| 3064 | |
| 3065 | const patternBufferUcs2 = allCharsBufferUcs2.slice( |
| 3066 | index, |
| 3067 | index + length |
| 3068 | ); |
| 3069 | ok(allCharsBufferUcs2.includes(patternBufferUcs2, 0, 'ucs2')); |
| 3070 | |
| 3071 | const patternStringUcs2 = patternBufferUcs2.toString('ucs2'); |
| 3072 | ok(allCharsBufferUcs2.includes(patternStringUcs2, 0, 'ucs2')); |
| 3073 | } |
| 3074 | } |
| 3075 | |
| 3076 | [() => {}, {}, []].forEach((val) => { |
| 3077 | throws(() => b.includes(val), { |
| 3078 | name: 'TypeError', |
| 3079 | }); |
| 3080 | }); |
| 3081 | |
| 3082 | // Test truncation of Number arguments to uint8 |
| 3083 | { |
| 3084 | const buf = Buffer.from('this is a test'); |
| 3085 | ok(buf.includes(0x6973)); |
| 3086 | ok(buf.includes(0x697320)); |
| 3087 | ok(buf.includes(0x69732069)); |
| 3088 | ok(buf.includes(0x697374657374)); |
| 3089 | ok(buf.includes(0x69737374)); |
| 3090 | ok(buf.includes(0x69737465)); |
| 3091 | ok(buf.includes(0x69737465)); |
| 3092 | ok(buf.includes(-140)); |
| 3093 | ok(buf.includes(-152)); |
| 3094 | ok(!buf.includes(0xff)); |
| 3095 | ok(!buf.includes(0xffff)); |
| 3096 | } |
| 3097 | }, |
| 3098 | }; |
| 3099 | |
| 3100 | export const indexof = { |
| 3101 | test(ctrl, env, ctx) { |
| 3102 | const b = Buffer.from('abcdef'); |
| 3103 | const buf_a = Buffer.from('a'); |
| 3104 | const buf_bc = Buffer.from('bc'); |
| 3105 | const buf_f = Buffer.from('f'); |
| 3106 | const buf_z = Buffer.from('z'); |
| 3107 | const buf_empty = Buffer.from(''); |
| 3108 | |
| 3109 | const s = 'abcdef'; |
| 3110 | |
| 3111 | strictEqual(b.indexOf('a'), 0); |
| 3112 | strictEqual(b.indexOf('a', 1), -1); |
| 3113 | strictEqual(b.indexOf('a', -1), -1); |
| 3114 | strictEqual(b.indexOf('a', -4), -1); |
| 3115 | strictEqual(b.indexOf('a', -b.length), 0); |
| 3116 | strictEqual(b.indexOf('a', NaN), 0); |
| 3117 | strictEqual(b.indexOf('a', -Infinity), 0); |
| 3118 | strictEqual(b.indexOf('a', Infinity), -1); |
| 3119 | strictEqual(b.indexOf('bc'), 1); |
| 3120 | strictEqual(b.indexOf('bc', 2), -1); |
| 3121 | strictEqual(b.indexOf('bc', -1), -1); |
| 3122 | strictEqual(b.indexOf('bc', -3), -1); |
| 3123 | strictEqual(b.indexOf('bc', -5), 1); |
| 3124 | strictEqual(b.indexOf('bc', NaN), 1); |
| 3125 | strictEqual(b.indexOf('bc', -Infinity), 1); |
| 3126 | strictEqual(b.indexOf('bc', Infinity), -1); |
| 3127 | strictEqual(b.indexOf('f'), b.length - 1); |
| 3128 | strictEqual(b.indexOf('z'), -1); |
| 3129 | strictEqual(b.indexOf(''), 0); |
| 3130 | strictEqual(b.indexOf('', 1), 1); |
| 3131 | strictEqual(b.indexOf('', b.length + 1), b.length); |
| 3132 | strictEqual(b.indexOf('', Infinity), b.length); |
| 3133 | strictEqual(b.indexOf(buf_a), 0); |
| 3134 | strictEqual(b.indexOf(buf_a, 1), -1); |
| 3135 | strictEqual(b.indexOf(buf_a, -1), -1); |
| 3136 | strictEqual(b.indexOf(buf_a, -4), -1); |
| 3137 | strictEqual(b.indexOf(buf_a, -b.length), 0); |
| 3138 | strictEqual(b.indexOf(buf_a, NaN), 0); |
| 3139 | strictEqual(b.indexOf(buf_a, -Infinity), 0); |
| 3140 | strictEqual(b.indexOf(buf_a, Infinity), -1); |
| 3141 | strictEqual(b.indexOf(buf_bc), 1); |
| 3142 | strictEqual(b.indexOf(buf_bc, 2), -1); |
| 3143 | strictEqual(b.indexOf(buf_bc, -1), -1); |
| 3144 | strictEqual(b.indexOf(buf_bc, -3), -1); |
| 3145 | strictEqual(b.indexOf(buf_bc, -5), 1); |
| 3146 | strictEqual(b.indexOf(buf_bc, NaN), 1); |
| 3147 | strictEqual(b.indexOf(buf_bc, -Infinity), 1); |
| 3148 | strictEqual(b.indexOf(buf_bc, Infinity), -1); |
| 3149 | strictEqual(b.indexOf(buf_f), b.length - 1); |
| 3150 | strictEqual(b.indexOf(buf_z), -1); |
| 3151 | strictEqual(b.indexOf(buf_empty), 0); |
| 3152 | strictEqual(b.indexOf(buf_empty, 1), 1); |
| 3153 | strictEqual(b.indexOf(buf_empty, b.length + 1), b.length); |
| 3154 | strictEqual(b.indexOf(buf_empty, Infinity), b.length); |
| 3155 | strictEqual(b.indexOf(0x61), 0); |
| 3156 | strictEqual(b.indexOf(0x61, 1), -1); |
| 3157 | strictEqual(b.indexOf(0x61, -1), -1); |
| 3158 | strictEqual(b.indexOf(0x61, -4), -1); |
| 3159 | strictEqual(b.indexOf(0x61, -b.length), 0); |
| 3160 | strictEqual(b.indexOf(0x61, NaN), 0); |
| 3161 | strictEqual(b.indexOf(0x61, -Infinity), 0); |
| 3162 | strictEqual(b.indexOf(0x61, Infinity), -1); |
| 3163 | strictEqual(b.indexOf(0x0), -1); |
| 3164 | |
| 3165 | // test offsets |
| 3166 | strictEqual(b.indexOf('d', 2), 3); |
| 3167 | strictEqual(b.indexOf('f', 5), 5); |
| 3168 | strictEqual(b.indexOf('f', -1), 5); |
| 3169 | strictEqual(b.indexOf('f', 6), -1); |
| 3170 | |
| 3171 | strictEqual(b.indexOf(Buffer.from('d'), 2), 3); |
| 3172 | strictEqual(b.indexOf(Buffer.from('f'), 5), 5); |
| 3173 | strictEqual(b.indexOf(Buffer.from('f'), -1), 5); |
| 3174 | strictEqual(b.indexOf(Buffer.from('f'), 6), -1); |
| 3175 | |
| 3176 | strictEqual(Buffer.from('ff').indexOf(Buffer.from('f'), 1, 'ucs2'), -1); |
| 3177 | |
| 3178 | // Test invalid and uppercase encoding |
| 3179 | strictEqual(b.indexOf('b', 'utf8'), 1); |
| 3180 | strictEqual(b.indexOf('b', 'UTF8'), 1); |
| 3181 | strictEqual(b.indexOf('62', 'HEX'), 1); |
| 3182 | |
| 3183 | throws(() => b.indexOf('bad', 'enc'), /Unknown encoding: enc/); |
| 3184 | |
| 3185 | // test hex encoding |
| 3186 | strictEqual( |
| 3187 | Buffer.from(b.toString('hex'), 'hex').indexOf('64', 0, 'hex'), |
| 3188 | 3 |
| 3189 | ); |
| 3190 | strictEqual( |
| 3191 | Buffer.from(b.toString('hex'), 'hex').indexOf( |
| 3192 | Buffer.from('64', 'hex'), |
| 3193 | 0, |
| 3194 | 'hex' |
| 3195 | ), |
| 3196 | 3 |
| 3197 | ); |
| 3198 | |
| 3199 | // Test base64 encoding |
| 3200 | strictEqual( |
| 3201 | Buffer.from(b.toString('base64'), 'base64').indexOf('ZA==', 0, 'base64'), |
| 3202 | 3 |
| 3203 | ); |
| 3204 | strictEqual( |
| 3205 | Buffer.from(b.toString('base64'), 'base64').indexOf( |
| 3206 | Buffer.from('ZA==', 'base64'), |
| 3207 | 0, |
| 3208 | 'base64' |
| 3209 | ), |
| 3210 | 3 |
| 3211 | ); |
| 3212 | |
| 3213 | // Test base64url encoding |
| 3214 | strictEqual( |
| 3215 | Buffer.from(b.toString('base64url'), 'base64url').indexOf( |
| 3216 | 'ZA==', |
| 3217 | 0, |
| 3218 | 'base64url' |
| 3219 | ), |
| 3220 | 3 |
| 3221 | ); |
| 3222 | |
| 3223 | // test ascii encoding |
| 3224 | strictEqual( |
| 3225 | Buffer.from(b.toString('ascii'), 'ascii').indexOf('d', 0, 'ascii'), |
| 3226 | 3 |
| 3227 | ); |
| 3228 | strictEqual( |
| 3229 | Buffer.from(b.toString('ascii'), 'ascii').indexOf( |
| 3230 | Buffer.from('d', 'ascii'), |
| 3231 | 0, |
| 3232 | 'ascii' |
| 3233 | ), |
| 3234 | 3 |
| 3235 | ); |
| 3236 | |
| 3237 | // Test latin1 encoding |
| 3238 | strictEqual( |
| 3239 | Buffer.from(b.toString('latin1'), 'latin1').indexOf('d', 0, 'latin1'), |
| 3240 | 3 |
| 3241 | ); |
| 3242 | strictEqual( |
| 3243 | Buffer.from(b.toString('latin1'), 'latin1').indexOf( |
| 3244 | Buffer.from('d', 'latin1'), |
| 3245 | 0, |
| 3246 | 'latin1' |
| 3247 | ), |
| 3248 | 3 |
| 3249 | ); |
| 3250 | strictEqual( |
| 3251 | Buffer.from('aa\u00e8aa', 'latin1').indexOf('\u00e8', 'latin1'), |
| 3252 | 2 |
| 3253 | ); |
| 3254 | strictEqual(Buffer.from('\u00e8', 'latin1').indexOf('\u00e8', 'latin1'), 0); |
| 3255 | strictEqual( |
| 3256 | Buffer.from('\u00e8', 'latin1').indexOf( |
| 3257 | Buffer.from('\u00e8', 'latin1'), |
| 3258 | 'latin1' |
| 3259 | ), |
| 3260 | 0 |
| 3261 | ); |
| 3262 | |
| 3263 | // Test binary encoding |
| 3264 | strictEqual( |
| 3265 | Buffer.from(b.toString('binary'), 'binary').indexOf('d', 0, 'binary'), |
| 3266 | 3 |
| 3267 | ); |
| 3268 | strictEqual( |
| 3269 | Buffer.from(b.toString('binary'), 'binary').indexOf( |
| 3270 | Buffer.from('d', 'binary'), |
| 3271 | 0, |
| 3272 | 'binary' |
| 3273 | ), |
| 3274 | 3 |
| 3275 | ); |
| 3276 | strictEqual( |
| 3277 | Buffer.from('aa\u00e8aa', 'binary').indexOf('\u00e8', 'binary'), |
| 3278 | 2 |
| 3279 | ); |
| 3280 | strictEqual(Buffer.from('\u00e8', 'binary').indexOf('\u00e8', 'binary'), 0); |
| 3281 | strictEqual( |
| 3282 | Buffer.from('\u00e8', 'binary').indexOf( |
| 3283 | Buffer.from('\u00e8', 'binary'), |
| 3284 | 'binary' |
| 3285 | ), |
| 3286 | 0 |
| 3287 | ); |
| 3288 | |
| 3289 | // Test optional offset with passed encoding |
| 3290 | strictEqual(Buffer.from('aaaa0').indexOf('30', 'hex'), 4); |
| 3291 | strictEqual(Buffer.from('aaaa00a').indexOf('3030', 'hex'), 4); |
| 3292 | |
| 3293 | { |
| 3294 | // Test usc2 and utf16le encoding |
| 3295 | ['ucs2', 'utf16le'].forEach((encoding) => { |
| 3296 | const twoByteString = Buffer.from( |
| 3297 | '\u039a\u0391\u03a3\u03a3\u0395', |
| 3298 | encoding |
| 3299 | ); |
| 3300 | |
| 3301 | strictEqual(twoByteString.indexOf('\u0395', 4, encoding), 8); |
| 3302 | strictEqual(twoByteString.indexOf('\u03a3', -4, encoding), 6); |
| 3303 | strictEqual(twoByteString.indexOf('\u03a3', -6, encoding), 4); |
| 3304 | strictEqual( |
| 3305 | twoByteString.indexOf(Buffer.from('\u03a3', encoding), -6, encoding), |
| 3306 | 4 |
| 3307 | ); |
| 3308 | strictEqual(-1, twoByteString.indexOf('\u03a3', -2, encoding)); |
| 3309 | }); |
| 3310 | } |
| 3311 | |
| 3312 | const mixedByteStringUcs2 = Buffer.from( |
| 3313 | '\u039a\u0391abc\u03a3\u03a3\u0395', |
| 3314 | 'ucs2' |
| 3315 | ); |
| 3316 | strictEqual(mixedByteStringUcs2.indexOf('bc', 0, 'ucs2'), 6); |
| 3317 | strictEqual(mixedByteStringUcs2.indexOf('\u03a3', 0, 'ucs2'), 10); |
| 3318 | strictEqual(-1, mixedByteStringUcs2.indexOf('\u0396', 0, 'ucs2')); |
| 3319 | |
| 3320 | strictEqual( |
| 3321 | mixedByteStringUcs2.indexOf(Buffer.from('bc', 'ucs2'), 0, 'ucs2'), |
| 3322 | 6 |
| 3323 | ); |
| 3324 | strictEqual( |
| 3325 | mixedByteStringUcs2.indexOf(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2'), |
| 3326 | 10 |
| 3327 | ); |
| 3328 | strictEqual( |
| 3329 | -1, |
| 3330 | mixedByteStringUcs2.indexOf(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2') |
| 3331 | ); |
| 3332 | |
| 3333 | { |
| 3334 | const twoByteString = Buffer.from( |
| 3335 | '\u039a\u0391\u03a3\u03a3\u0395', |
| 3336 | 'ucs2' |
| 3337 | ); |
| 3338 | |
| 3339 | // Test single char pattern |
| 3340 | strictEqual(twoByteString.indexOf('\u039a', 0, 'ucs2'), 0); |
| 3341 | let index = twoByteString.indexOf('\u0391', 0, 'ucs2'); |
| 3342 | strictEqual(index, 2, `Alpha - at index ${index}`); |
| 3343 | index = twoByteString.indexOf('\u03a3', 0, 'ucs2'); |
| 3344 | strictEqual(index, 4, `First Sigma - at index ${index}`); |
| 3345 | index = twoByteString.indexOf('\u03a3', 6, 'ucs2'); |
| 3346 | strictEqual(index, 6, `Second Sigma - at index ${index}`); |
| 3347 | index = twoByteString.indexOf('\u0395', 0, 'ucs2'); |
| 3348 | strictEqual(index, 8, `Epsilon - at index ${index}`); |
| 3349 | index = twoByteString.indexOf('\u0392', 0, 'ucs2'); |
| 3350 | strictEqual(-1, index, `Not beta - at index ${index}`); |
| 3351 | |
| 3352 | // Test multi-char pattern |
| 3353 | index = twoByteString.indexOf('\u039a\u0391', 0, 'ucs2'); |
| 3354 | strictEqual(index, 0, `Lambda Alpha - at index ${index}`); |
| 3355 | index = twoByteString.indexOf('\u0391\u03a3', 0, 'ucs2'); |
| 3356 | strictEqual(index, 2, `Alpha Sigma - at index ${index}`); |
| 3357 | index = twoByteString.indexOf('\u03a3\u03a3', 0, 'ucs2'); |
| 3358 | strictEqual(index, 4, `Sigma Sigma - at index ${index}`); |
| 3359 | index = twoByteString.indexOf('\u03a3\u0395', 0, 'ucs2'); |
| 3360 | strictEqual(index, 6, `Sigma Epsilon - at index ${index}`); |
| 3361 | } |
| 3362 | |
| 3363 | const mixedByteStringUtf8 = Buffer.from( |
| 3364 | '\u039a\u0391abc\u03a3\u03a3\u0395' |
| 3365 | ); |
| 3366 | strictEqual(mixedByteStringUtf8.indexOf('bc'), 5); |
| 3367 | strictEqual(mixedByteStringUtf8.indexOf('bc', 5), 5); |
| 3368 | strictEqual(mixedByteStringUtf8.indexOf('bc', -8), 5); |
| 3369 | strictEqual(mixedByteStringUtf8.indexOf('\u03a3'), 7); |
| 3370 | strictEqual(mixedByteStringUtf8.indexOf('\u0396'), -1); |
| 3371 | |
| 3372 | // Test complex string indexOf algorithms. Only trigger for long strings. |
| 3373 | // Long string that isn't a simple repeat of a shorter string. |
| 3374 | let longString = 'A'; |
| 3375 | for (let i = 66; i < 76; i++) { |
| 3376 | // from 'B' to 'K' |
| 3377 | longString = longString + String.fromCharCode(i) + longString; |
| 3378 | } |
| 3379 | |
| 3380 | const longBufferString = Buffer.from(longString); |
| 3381 | |
| 3382 | // Pattern of 15 chars, repeated every 16 chars in long |
| 3383 | let pattern = 'ABACABADABACABA'; |
| 3384 | for (let i = 0; i < longBufferString.length - pattern.length; i += 7) { |
| 3385 | const index = longBufferString.indexOf(pattern, i); |
| 3386 | strictEqual( |
| 3387 | (i + 15) & ~0xf, |
| 3388 | index, |
| 3389 | `Long ABACABA...-string at index ${i}` |
| 3390 | ); |
| 3391 | } |
| 3392 | |
| 3393 | let index = longBufferString.indexOf('AJABACA'); |
| 3394 | strictEqual(index, 510, `Long AJABACA, First J - at index ${index}`); |
| 3395 | index = longBufferString.indexOf('AJABACA', 511); |
| 3396 | strictEqual(index, 1534, `Long AJABACA, Second J - at index ${index}`); |
| 3397 | |
| 3398 | pattern = 'JABACABADABACABA'; |
| 3399 | index = longBufferString.indexOf(pattern); |
| 3400 | strictEqual(index, 511, `Long JABACABA..., First J - at index ${index}`); |
| 3401 | index = longBufferString.indexOf(pattern, 512); |
| 3402 | strictEqual(index, 1535, `Long JABACABA..., Second J - at index ${index}`); |
| 3403 | |
| 3404 | // Search for a non-ASCII string in a pure ASCII string. |
| 3405 | const asciiString = Buffer.from( |
| 3406 | 'arglebargleglopglyfarglebargleglopglyfarglebargleglopglyf' |
| 3407 | ); |
| 3408 | strictEqual(-1, asciiString.indexOf('\x2061')); |
| 3409 | strictEqual(asciiString.indexOf('leb', 0), 3); |
| 3410 | |
| 3411 | // Search in string containing many non-ASCII chars. |
| 3412 | const allCodePoints = []; |
| 3413 | for (let i = 0; i < 65534; i++) allCodePoints[i] = i; |
| 3414 | const allCharsString = |
| 3415 | String.fromCharCode.apply(String, allCodePoints) + |
| 3416 | String.fromCharCode(65534, 65535); |
| 3417 | const allCharsBufferUtf8 = Buffer.from(allCharsString); |
| 3418 | const allCharsBufferUcs2 = Buffer.from(allCharsString, 'ucs2'); |
| 3419 | |
| 3420 | // Search for string long enough to trigger complex search with ASCII pattern |
| 3421 | // and UC16 subject. |
| 3422 | strictEqual(-1, allCharsBufferUtf8.indexOf('notfound')); |
| 3423 | strictEqual(-1, allCharsBufferUcs2.indexOf('notfound')); |
| 3424 | |
| 3425 | // Needle is longer than haystack, but only because it's encoded as UTF-16 |
| 3426 | strictEqual(Buffer.from('aaaa').indexOf('a'.repeat(4), 'ucs2'), -1); |
| 3427 | |
| 3428 | strictEqual(Buffer.from('aaaa').indexOf('a'.repeat(4), 'utf8'), 0); |
| 3429 | strictEqual(Buffer.from('aaaa').indexOf('你好', 'ucs2'), -1); |
| 3430 | |
| 3431 | // Haystack has odd length, but the needle is UCS2. |
| 3432 | strictEqual(Buffer.from('aaaaa').indexOf('b', 'ucs2'), -1); |
| 3433 | |
| 3434 | { |
| 3435 | // Find substrings in Utf8. |
| 3436 | const lengths = [1, 3, 15]; // Single char, simple and complex. |
| 3437 | const indices = [ |
| 3438 | 0x5, 0x60, 0x400, 0x680, 0x7ee, 0xff02, 0x16610, 0x2f77b, |
| 3439 | ]; |
| 3440 | for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) { |
| 3441 | for (let i = 0; i < indices.length; i++) { |
| 3442 | const index = indices[i]; |
| 3443 | let length = lengths[lengthIndex]; |
| 3444 | |
| 3445 | if (index + length > 0x7f) { |
| 3446 | length = 2 * length; |
| 3447 | } |
| 3448 | |
| 3449 | if (index + length > 0x7ff) { |
| 3450 | length = 3 * length; |
| 3451 | } |
| 3452 | |
| 3453 | if (index + length > 0xffff) { |
| 3454 | length = 4 * length; |
| 3455 | } |
| 3456 | |
| 3457 | const patternBufferUtf8 = allCharsBufferUtf8.slice( |
| 3458 | index, |
| 3459 | index + length |
| 3460 | ); |
| 3461 | strictEqual(index, allCharsBufferUtf8.indexOf(patternBufferUtf8)); |
| 3462 | |
| 3463 | const patternStringUtf8 = patternBufferUtf8.toString(); |
| 3464 | strictEqual(index, allCharsBufferUtf8.indexOf(patternStringUtf8)); |
| 3465 | } |
| 3466 | } |
| 3467 | } |
| 3468 | |
| 3469 | { |
| 3470 | // Find substrings in Usc2. |
| 3471 | const lengths = [2, 4, 16]; // Single char, simple and complex. |
| 3472 | const indices = [0x5, 0x65, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0]; |
| 3473 | for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) { |
| 3474 | for (let i = 0; i < indices.length; i++) { |
| 3475 | const index = indices[i] * 2; |
| 3476 | const length = lengths[lengthIndex]; |
| 3477 | |
| 3478 | const patternBufferUcs2 = allCharsBufferUcs2.slice( |
| 3479 | index, |
| 3480 | index + length |
| 3481 | ); |
| 3482 | strictEqual( |
| 3483 | index, |
| 3484 | allCharsBufferUcs2.indexOf(patternBufferUcs2, 0, 'ucs2') |
| 3485 | ); |
| 3486 | |
| 3487 | const patternStringUcs2 = patternBufferUcs2.toString('ucs2'); |
| 3488 | strictEqual( |
| 3489 | index, |
| 3490 | allCharsBufferUcs2.indexOf(patternStringUcs2, 0, 'ucs2') |
| 3491 | ); |
| 3492 | } |
| 3493 | } |
| 3494 | } |
| 3495 | |
| 3496 | [() => {}, {}, []].forEach((val) => { |
| 3497 | throws(() => b.indexOf(val), { |
| 3498 | name: 'TypeError', |
| 3499 | }); |
| 3500 | }); |
| 3501 | |
| 3502 | // Test weird offset arguments. |
| 3503 | // The following offsets coerce to NaN or 0, searching the whole Buffer |
| 3504 | strictEqual(b.indexOf('b', undefined), 1); |
| 3505 | strictEqual(b.indexOf('b', {}), 1); |
| 3506 | strictEqual(b.indexOf('b', 0), 1); |
| 3507 | strictEqual(b.indexOf('b', null), 1); |
| 3508 | strictEqual(b.indexOf('b', []), 1); |
| 3509 | |
| 3510 | // The following offset coerces to 2, in other words +[2] === 2 |
| 3511 | strictEqual(b.indexOf('b', [2]), -1); |
| 3512 | |
| 3513 | // Behavior should match String.indexOf() |
| 3514 | strictEqual(b.indexOf('b', undefined), s.indexOf('b', undefined)); |
| 3515 | strictEqual(b.indexOf('b', {}), s.indexOf('b', {})); |
| 3516 | strictEqual(b.indexOf('b', 0), s.indexOf('b', 0)); |
| 3517 | strictEqual(b.indexOf('b', null), s.indexOf('b', null)); |
| 3518 | strictEqual(b.indexOf('b', []), s.indexOf('b', [])); |
| 3519 | strictEqual(b.indexOf('b', [2]), s.indexOf('b', [2])); |
| 3520 | |
| 3521 | // All code for handling encodings is shared between Buffer.indexOf and |
| 3522 | // Buffer.lastIndexOf, so only testing the separate lastIndexOf semantics. |
| 3523 | |
| 3524 | // Test lastIndexOf basic functionality; Buffer b contains 'abcdef'. |
| 3525 | // lastIndexOf string: |
| 3526 | strictEqual(b.lastIndexOf('a'), 0); |
| 3527 | strictEqual(b.lastIndexOf('a', 1), 0); |
| 3528 | strictEqual(b.lastIndexOf('b', 1), 1); |
| 3529 | strictEqual(b.lastIndexOf('c', 1), -1); |
| 3530 | strictEqual(b.lastIndexOf('a', -1), 0); |
| 3531 | strictEqual(b.lastIndexOf('a', -4), 0); |
| 3532 | strictEqual(b.lastIndexOf('a', -b.length), 0); |
| 3533 | strictEqual(b.lastIndexOf('a', -b.length - 1), -1); |
| 3534 | strictEqual(b.lastIndexOf('a', NaN), 0); |
| 3535 | strictEqual(b.lastIndexOf('a', -Infinity), -1); |
| 3536 | strictEqual(b.lastIndexOf('a', Infinity), 0); |
| 3537 | // lastIndexOf Buffer: |
| 3538 | strictEqual(b.lastIndexOf(buf_a), 0); |
| 3539 | strictEqual(b.lastIndexOf(buf_a, 1), 0); |
| 3540 | strictEqual(b.lastIndexOf(buf_a, -1), 0); |
| 3541 | strictEqual(b.lastIndexOf(buf_a, -4), 0); |
| 3542 | strictEqual(b.lastIndexOf(buf_a, -b.length), 0); |
| 3543 | strictEqual(b.lastIndexOf(buf_a, -b.length - 1), -1); |
| 3544 | strictEqual(b.lastIndexOf(buf_a, NaN), 0); |
| 3545 | strictEqual(b.lastIndexOf(buf_a, -Infinity), -1); |
| 3546 | strictEqual(b.lastIndexOf(buf_a, Infinity), 0); |
| 3547 | strictEqual(b.lastIndexOf(buf_bc), 1); |
| 3548 | strictEqual(b.lastIndexOf(buf_bc, 2), 1); |
| 3549 | strictEqual(b.lastIndexOf(buf_bc, -1), 1); |
| 3550 | strictEqual(b.lastIndexOf(buf_bc, -3), 1); |
| 3551 | strictEqual(b.lastIndexOf(buf_bc, -5), 1); |
| 3552 | strictEqual(b.lastIndexOf(buf_bc, -6), -1); |
| 3553 | strictEqual(b.lastIndexOf(buf_bc, NaN), 1); |
| 3554 | strictEqual(b.lastIndexOf(buf_bc, -Infinity), -1); |
| 3555 | strictEqual(b.lastIndexOf(buf_bc, Infinity), 1); |
| 3556 | strictEqual(b.lastIndexOf(buf_f), b.length - 1); |
| 3557 | strictEqual(b.lastIndexOf(buf_z), -1); |
| 3558 | strictEqual(b.lastIndexOf(buf_empty), b.length); |
| 3559 | strictEqual(b.lastIndexOf(buf_empty, 1), 1); |
| 3560 | strictEqual(b.lastIndexOf(buf_empty, b.length + 1), b.length); |
| 3561 | strictEqual(b.lastIndexOf(buf_empty, Infinity), b.length); |
| 3562 | // lastIndexOf number: |
| 3563 | strictEqual(b.lastIndexOf(0x61), 0); |
| 3564 | strictEqual(b.lastIndexOf(0x61, 1), 0); |
| 3565 | strictEqual(b.lastIndexOf(0x61, -1), 0); |
| 3566 | strictEqual(b.lastIndexOf(0x61, -4), 0); |
| 3567 | strictEqual(b.lastIndexOf(0x61, -b.length), 0); |
| 3568 | strictEqual(b.lastIndexOf(0x61, -b.length - 1), -1); |
| 3569 | strictEqual(b.lastIndexOf(0x61, NaN), 0); |
| 3570 | strictEqual(b.lastIndexOf(0x61, -Infinity), -1); |
| 3571 | strictEqual(b.lastIndexOf(0x61, Infinity), 0); |
| 3572 | strictEqual(b.lastIndexOf(0x0), -1); |
| 3573 | |
| 3574 | // Test weird offset arguments. |
| 3575 | // The following offsets coerce to NaN, searching the whole Buffer |
| 3576 | strictEqual(b.lastIndexOf('b', undefined), 1); |
| 3577 | strictEqual(b.lastIndexOf('b', {}), 1); |
| 3578 | |
| 3579 | // The following offsets coerce to 0 |
| 3580 | strictEqual(b.lastIndexOf('b', 0), -1); |
| 3581 | strictEqual(b.lastIndexOf('b', null), -1); |
| 3582 | strictEqual(b.lastIndexOf('b', []), -1); |
| 3583 | |
| 3584 | // The following offset coerces to 2, in other words +[2] === 2 |
| 3585 | strictEqual(b.lastIndexOf('b', [2]), 1); |
| 3586 | |
| 3587 | // Behavior should match String.lastIndexOf() |
| 3588 | strictEqual(b.lastIndexOf('b', undefined), s.lastIndexOf('b', undefined)); |
| 3589 | strictEqual(b.lastIndexOf('b', {}), s.lastIndexOf('b', {})); |
| 3590 | strictEqual(b.lastIndexOf('b', 0), s.lastIndexOf('b', 0)); |
| 3591 | strictEqual(b.lastIndexOf('b', null), s.lastIndexOf('b', null)); |
| 3592 | strictEqual(b.lastIndexOf('b', []), s.lastIndexOf('b', [])); |
| 3593 | strictEqual(b.lastIndexOf('b', [2]), s.lastIndexOf('b', [2])); |
| 3594 | |
| 3595 | // Test needles longer than the haystack. |
| 3596 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'ucs2'), -1); |
| 3597 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'utf8'), -1); |
| 3598 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'latin1'), -1); |
| 3599 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 'binary'), -1); |
| 3600 | strictEqual(b.lastIndexOf(Buffer.from('aaaaaaaaaaaaaaa')), -1); |
| 3601 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 2, 'ucs2'), -1); |
| 3602 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 3, 'utf8'), -1); |
| 3603 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 5, 'latin1'), -1); |
| 3604 | strictEqual(b.lastIndexOf('aaaaaaaaaaaaaaa', 5, 'binary'), -1); |
| 3605 | strictEqual(b.lastIndexOf(Buffer.from('aaaaaaaaaaaaaaa'), 7), -1); |
| 3606 | |
| 3607 | // 你好 expands to a total of 6 bytes using UTF-8 and 4 bytes using UTF-16 |
| 3608 | strictEqual(buf_bc.lastIndexOf('你好', 'ucs2'), -1); |
| 3609 | strictEqual(buf_bc.lastIndexOf('你好', 'utf8'), -1); |
| 3610 | strictEqual(buf_bc.lastIndexOf('你好', 'latin1'), -1); |
| 3611 | strictEqual(buf_bc.lastIndexOf('你好', 'binary'), -1); |
| 3612 | strictEqual(buf_bc.lastIndexOf(Buffer.from('你好')), -1); |
| 3613 | strictEqual(buf_bc.lastIndexOf('你好', 2, 'ucs2'), -1); |
| 3614 | strictEqual(buf_bc.lastIndexOf('你好', 3, 'utf8'), -1); |
| 3615 | strictEqual(buf_bc.lastIndexOf('你好', 5, 'latin1'), -1); |
| 3616 | strictEqual(buf_bc.lastIndexOf('你好', 5, 'binary'), -1); |
| 3617 | strictEqual(buf_bc.lastIndexOf(Buffer.from('你好'), 7), -1); |
| 3618 | |
| 3619 | // Test lastIndexOf on a longer buffer: |
| 3620 | const bufferString = Buffer.from('a man a plan a canal panama'); |
| 3621 | strictEqual(bufferString.lastIndexOf('canal'), 15); |
| 3622 | strictEqual(bufferString.lastIndexOf('panama'), 21); |
| 3623 | strictEqual(bufferString.lastIndexOf('a man a plan a canal panama'), 0); |
| 3624 | strictEqual(-1, bufferString.lastIndexOf('a man a plan a canal mexico')); |
| 3625 | strictEqual( |
| 3626 | -1, |
| 3627 | bufferString.lastIndexOf('a man a plan a canal mexico city') |
| 3628 | ); |
| 3629 | strictEqual(-1, bufferString.lastIndexOf(Buffer.from('a'.repeat(1000)))); |
| 3630 | strictEqual(bufferString.lastIndexOf('a man a plan', 4), 0); |
| 3631 | strictEqual(bufferString.lastIndexOf('a '), 13); |
| 3632 | strictEqual(bufferString.lastIndexOf('a ', 13), 13); |
| 3633 | strictEqual(bufferString.lastIndexOf('a ', 12), 6); |
| 3634 | strictEqual(bufferString.lastIndexOf('a ', 5), 0); |
| 3635 | strictEqual(bufferString.lastIndexOf('a ', -1), 13); |
| 3636 | strictEqual(bufferString.lastIndexOf('a ', -27), 0); |
| 3637 | strictEqual(-1, bufferString.lastIndexOf('a ', -28)); |
| 3638 | |
| 3639 | // Test lastIndexOf for the case that the first character can be found, |
| 3640 | // but in a part of the buffer that does not make search to search |
| 3641 | // due do length constraints. |
| 3642 | const abInUCS2 = Buffer.from('ab', 'ucs2'); |
| 3643 | strictEqual(-1, Buffer.from('µaaaa¶bbbb', 'latin1').lastIndexOf('µ')); |
| 3644 | strictEqual(-1, Buffer.from('µaaaa¶bbbb', 'binary').lastIndexOf('µ')); |
| 3645 | strictEqual(-1, Buffer.from('bc').lastIndexOf('ab')); |
| 3646 | strictEqual(-1, Buffer.from('abc').lastIndexOf('qa')); |
| 3647 | strictEqual(-1, Buffer.from('abcdef').lastIndexOf('qabc')); |
| 3648 | strictEqual(-1, Buffer.from('bc').lastIndexOf(Buffer.from('ab'))); |
| 3649 | strictEqual(-1, Buffer.from('bc', 'ucs2').lastIndexOf('ab', 'ucs2')); |
| 3650 | strictEqual(-1, Buffer.from('bc', 'ucs2').lastIndexOf(abInUCS2)); |
| 3651 | |
| 3652 | strictEqual(Buffer.from('abc').lastIndexOf('ab'), 0); |
| 3653 | strictEqual(Buffer.from('abc').lastIndexOf('ab', 1), 0); |
| 3654 | strictEqual(Buffer.from('abc').lastIndexOf('ab', 2), 0); |
| 3655 | strictEqual(Buffer.from('abc').lastIndexOf('ab', 3), 0); |
| 3656 | |
| 3657 | // The above tests test the LINEAR and SINGLE-CHAR strategies. |
| 3658 | // Now, we test the BOYER-MOORE-HORSPOOL strategy. |
| 3659 | // Test lastIndexOf on a long buffer w multiple matches: |
| 3660 | // pattern = 'JABACABADABACABA'; |
| 3661 | strictEqual(longBufferString.lastIndexOf(pattern), 1535); |
| 3662 | strictEqual(longBufferString.lastIndexOf(pattern, 1535), 1535); |
| 3663 | strictEqual(longBufferString.lastIndexOf(pattern, 1534), 511); |
| 3664 | |
| 3665 | // Generate a really long Thue-Morse sequence of 'yolo' and 'swag', |
| 3666 | // "yolo swag swag yolo swag yolo yolo swag" ..., goes on for about 5MB. |
| 3667 | // This is hard to search because it all looks similar, but never repeats. |
| 3668 | |
| 3669 | // countBits returns the number of bits in the binary representation of n. |
| 3670 | function countBits(n) { |
| 3671 | let count; |
| 3672 | for (count = 0; n > 0; count++) { |
| 3673 | n = n & (n - 1); // remove top bit |
| 3674 | } |
| 3675 | return count; |
| 3676 | } |
| 3677 | const parts = []; |
| 3678 | for (let i = 0; i < 1000000; i++) { |
| 3679 | parts.push(countBits(i) % 2 === 0 ? 'yolo' : 'swag'); |
| 3680 | } |
| 3681 | const reallyLong = Buffer.from(parts.join(' ')); |
| 3682 | strictEqual(reallyLong.slice(0, 19).toString(), 'yolo swag swag yolo'); |
| 3683 | |
| 3684 | // Expensive reverse searches. Stress test lastIndexOf: |
| 3685 | pattern = reallyLong.slice(0, 100000); // First 1/50th of the pattern. |
| 3686 | strictEqual(reallyLong.lastIndexOf(pattern), 4751360); |
| 3687 | strictEqual(reallyLong.lastIndexOf(pattern, 4000000), 3932160); |
| 3688 | strictEqual(reallyLong.lastIndexOf(pattern, 3000000), 2949120); |
| 3689 | pattern = reallyLong.slice(100000, 200000); // Second 1/50th. |
| 3690 | strictEqual(reallyLong.lastIndexOf(pattern), 4728480); |
| 3691 | pattern = reallyLong.slice(0, 1000000); // First 1/5th. |
| 3692 | strictEqual(reallyLong.lastIndexOf(pattern), 3932160); |
| 3693 | pattern = reallyLong.slice(0, 2000000); // first 2/5ths. |
| 3694 | strictEqual(reallyLong.lastIndexOf(pattern), 0); |
| 3695 | |
| 3696 | // Test truncation of Number arguments to uint8 |
| 3697 | { |
| 3698 | const buf = Buffer.from('this is a test'); |
| 3699 | strictEqual(buf.indexOf(0x6973), 3); |
| 3700 | strictEqual(buf.indexOf(0x697320), 4); |
| 3701 | strictEqual(buf.indexOf(0x69732069), 2); |
| 3702 | strictEqual(buf.indexOf(0x697374657374), 0); |
| 3703 | strictEqual(buf.indexOf(0x69737374), 0); |
| 3704 | strictEqual(buf.indexOf(0x69737465), 11); |
| 3705 | strictEqual(buf.indexOf(0x69737465), 11); |
| 3706 | strictEqual(buf.indexOf(-140), 0); |
| 3707 | strictEqual(buf.indexOf(-152), 1); |
| 3708 | strictEqual(buf.indexOf(0xff), -1); |
| 3709 | strictEqual(buf.indexOf(0xffff), -1); |
| 3710 | } |
| 3711 | |
| 3712 | // Test that Uint8Array arguments are okay. |
| 3713 | { |
| 3714 | const needle = new Uint8Array([0x66, 0x6f, 0x6f]); |
| 3715 | const haystack = Buffer.from('a foo b foo'); |
| 3716 | strictEqual(haystack.indexOf(needle), 2); |
| 3717 | strictEqual(haystack.lastIndexOf(needle), haystack.length - 3); |
| 3718 | } |
| 3719 | }, |
| 3720 | }; |
| 3721 | |
| 3722 | export const inheritance = { |
| 3723 | test(ctrl, env, ctx) { |
| 3724 | function T(n) { |
| 3725 | const ui8 = new Uint8Array(n); |
| 3726 | Object.setPrototypeOf(ui8, T.prototype); |
| 3727 | return ui8; |
| 3728 | } |
| 3729 | Object.setPrototypeOf(T.prototype, Buffer.prototype); |
| 3730 | Object.setPrototypeOf(T, Buffer); |
| 3731 | |
| 3732 | T.prototype.sum = function sum() { |
| 3733 | let cntr = 0; |
| 3734 | for (let i = 0; i < this.length; i++) cntr += this[i]; |
| 3735 | return cntr; |
| 3736 | }; |
| 3737 | |
| 3738 | const vals = [new T(4), T(4)]; |
| 3739 | |
| 3740 | vals.forEach(function (t) { |
| 3741 | strictEqual(t.constructor, T); |
| 3742 | strictEqual(Object.getPrototypeOf(t), T.prototype); |
| 3743 | strictEqual( |
| 3744 | Object.getPrototypeOf(Object.getPrototypeOf(t)), |
| 3745 | Buffer.prototype |
| 3746 | ); |
| 3747 | |
| 3748 | t.fill(5); |
| 3749 | let cntr = 0; |
| 3750 | for (let i = 0; i < t.length; i++) cntr += t[i]; |
| 3751 | strictEqual(cntr, t.length * 5); |
| 3752 | |
| 3753 | // Check this does not throw |
| 3754 | t.toString(); |
| 3755 | }); |
| 3756 | }, |
| 3757 | }; |
| 3758 | |
| 3759 | export const iterator = { |
| 3760 | test(ctrl, env, ctx) { |
| 3761 | const buffer = Buffer.from([1, 2, 3, 4, 5]); |
| 3762 | let arr; |
| 3763 | let b; |
| 3764 | |
| 3765 | // Buffers should be iterable |
| 3766 | |
| 3767 | arr = []; |
| 3768 | |
| 3769 | for (b of buffer) arr.push(b); |
| 3770 | |
| 3771 | deepStrictEqual(arr, [1, 2, 3, 4, 5]); |
| 3772 | |
| 3773 | // Buffer iterators should be iterable |
| 3774 | |
| 3775 | arr = []; |
| 3776 | |
| 3777 | for (b of buffer[Symbol.iterator]()) arr.push(b); |
| 3778 | |
| 3779 | deepStrictEqual(arr, [1, 2, 3, 4, 5]); |
| 3780 | |
| 3781 | // buffer#values() should return iterator for values |
| 3782 | |
| 3783 | arr = []; |
| 3784 | |
| 3785 | for (b of buffer.values()) arr.push(b); |
| 3786 | |
| 3787 | deepStrictEqual(arr, [1, 2, 3, 4, 5]); |
| 3788 | |
| 3789 | // buffer#keys() should return iterator for keys |
| 3790 | |
| 3791 | arr = []; |
| 3792 | |
| 3793 | for (b of buffer.keys()) arr.push(b); |
| 3794 | |
| 3795 | deepStrictEqual(arr, [0, 1, 2, 3, 4]); |
| 3796 | |
| 3797 | // buffer#entries() should return iterator for entries |
| 3798 | |
| 3799 | arr = []; |
| 3800 | |
| 3801 | for (b of buffer.entries()) arr.push(b); |
| 3802 | |
| 3803 | deepStrictEqual(arr, [ |
| 3804 | [0, 1], |
| 3805 | [1, 2], |
| 3806 | [2, 3], |
| 3807 | [3, 4], |
| 3808 | [4, 5], |
| 3809 | ]); |
| 3810 | }, |
| 3811 | }; |
| 3812 | |
| 3813 | export const negativeAlloc = { |
| 3814 | test(ctrl, env, ctx) { |
| 3815 | const msg = { |
| 3816 | name: 'RangeError', |
| 3817 | }; |
| 3818 | |
| 3819 | // Test that negative Buffer length inputs throw errors. |
| 3820 | |
| 3821 | throws(() => Buffer(-100), msg); |
| 3822 | throws(() => Buffer(-1), msg); |
| 3823 | throws(() => Buffer(NaN), msg); |
| 3824 | |
| 3825 | throws(() => Buffer.alloc(-100), msg); |
| 3826 | throws(() => Buffer.alloc(-1), msg); |
| 3827 | throws(() => Buffer.alloc(NaN), msg); |
| 3828 | |
| 3829 | throws(() => Buffer.allocUnsafe(-100), msg); |
| 3830 | throws(() => Buffer.allocUnsafe(-1), msg); |
| 3831 | throws(() => Buffer.allocUnsafe(NaN), msg); |
| 3832 | |
| 3833 | throws(() => Buffer.allocUnsafeSlow(-100), msg); |
| 3834 | throws(() => Buffer.allocUnsafeSlow(-1), msg); |
| 3835 | throws(() => Buffer.allocUnsafeSlow(NaN), msg); |
| 3836 | |
| 3837 | throws(() => SlowBuffer(-100), msg); |
| 3838 | throws(() => SlowBuffer(-1), msg); |
| 3839 | throws(() => SlowBuffer(NaN), msg); |
| 3840 | }, |
| 3841 | }; |
| 3842 | |
| 3843 | export const overMaxLength = { |
| 3844 | test(ctrl, env, ctx) { |
| 3845 | const bufferMaxSizeMsg = { |
| 3846 | name: 'RangeError', |
| 3847 | }; |
| 3848 | |
| 3849 | throws(() => Buffer((-1 >>> 0) + 2), bufferMaxSizeMsg); |
| 3850 | throws(() => SlowBuffer((-1 >>> 0) + 2), bufferMaxSizeMsg); |
| 3851 | throws(() => Buffer.alloc((-1 >>> 0) + 2), bufferMaxSizeMsg); |
| 3852 | throws(() => Buffer.allocUnsafe((-1 >>> 0) + 2), bufferMaxSizeMsg); |
| 3853 | throws(() => Buffer.allocUnsafeSlow((-1 >>> 0) + 2), bufferMaxSizeMsg); |
| 3854 | |
| 3855 | throws(() => Buffer(kMaxLength + 1), bufferMaxSizeMsg); |
| 3856 | throws(() => SlowBuffer(kMaxLength + 1), bufferMaxSizeMsg); |
| 3857 | throws(() => Buffer.alloc(kMaxLength + 1), bufferMaxSizeMsg); |
| 3858 | throws(() => Buffer.allocUnsafe(kMaxLength + 1), bufferMaxSizeMsg); |
| 3859 | throws(() => Buffer.allocUnsafeSlow(kMaxLength + 1), bufferMaxSizeMsg); |
| 3860 | |
| 3861 | // issue GH-4331 |
| 3862 | throws(() => Buffer.allocUnsafe(0x100000001), bufferMaxSizeMsg); |
| 3863 | throws(() => Buffer.allocUnsafe(0xfffffffff), bufferMaxSizeMsg); |
| 3864 | }, |
| 3865 | }; |
| 3866 | |
| 3867 | export const read = { |
| 3868 | test(ctrl, env, ctx) { |
| 3869 | // Testing basic buffer read functions |
| 3870 | const buf = Buffer.from([ |
| 3871 | 0xa4, 0xfd, 0x48, 0xea, 0xcf, 0xff, 0xd9, 0x01, 0xde, |
| 3872 | ]); |
| 3873 | |
| 3874 | function read(buff, funx, args, expected) { |
| 3875 | strictEqual(buff[funx](...args), expected); |
| 3876 | throws(() => buff[funx](-1, args[1]), { code: 'ERR_OUT_OF_RANGE' }); |
| 3877 | } |
| 3878 | |
| 3879 | // Testing basic functionality of readDoubleBE() and readDoubleLE() |
| 3880 | read(buf, 'readDoubleBE', [1], -3.1827727774563287e295); |
| 3881 | read(buf, 'readDoubleLE', [1], -6.966010051009108e144); |
| 3882 | |
| 3883 | // Testing basic functionality of readFloatBE() and readFloatLE() |
| 3884 | read(buf, 'readFloatBE', [1], -1.6691549692541768e37); |
| 3885 | read(buf, 'readFloatLE', [1], -7861303808); |
| 3886 | |
| 3887 | // Testing basic functionality of readInt8() |
| 3888 | read(buf, 'readInt8', [1], -3); |
| 3889 | |
| 3890 | // Testing basic functionality of readInt16BE() and readInt16LE() |
| 3891 | read(buf, 'readInt16BE', [1], -696); |
| 3892 | read(buf, 'readInt16LE', [1], 0x48fd); |
| 3893 | |
| 3894 | // Testing basic functionality of readInt32BE() and readInt32LE() |
| 3895 | read(buf, 'readInt32BE', [1], -45552945); |
| 3896 | read(buf, 'readInt32LE', [1], -806729475); |
| 3897 | |
| 3898 | // Testing basic functionality of readIntBE() and readIntLE() |
| 3899 | read(buf, 'readIntBE', [1, 1], -3); |
| 3900 | read(buf, 'readIntLE', [2, 1], 0x48); |
| 3901 | |
| 3902 | // Testing basic functionality of readUInt8() |
| 3903 | read(buf, 'readUInt8', [1], 0xfd); |
| 3904 | |
| 3905 | // Testing basic functionality of readUInt16BE() and readUInt16LE() |
| 3906 | read(buf, 'readUInt16BE', [2], 0x48ea); |
| 3907 | read(buf, 'readUInt16LE', [2], 0xea48); |
| 3908 | |
| 3909 | // Testing basic functionality of readUInt32BE() and readUInt32LE() |
| 3910 | read(buf, 'readUInt32BE', [1], 0xfd48eacf); |
| 3911 | read(buf, 'readUInt32LE', [1], 0xcfea48fd); |
| 3912 | |
| 3913 | // Testing basic functionality of readUIntBE() and readUIntLE() |
| 3914 | read(buf, 'readUIntBE', [2, 2], 0x48ea); |
| 3915 | read(buf, 'readUIntLE', [2, 2], 0xea48); |
| 3916 | |
| 3917 | // Error name and message |
| 3918 | const OOR_ERROR = { |
| 3919 | name: 'RangeError', |
| 3920 | }; |
| 3921 | |
| 3922 | const OOB_ERROR = { |
| 3923 | name: 'RangeError', |
| 3924 | message: 'Attempt to access memory outside buffer bounds', |
| 3925 | }; |
| 3926 | |
| 3927 | // Attempt to overflow buffers, similar to previous bug in array buffers |
| 3928 | throws(() => Buffer.allocUnsafe(8).readFloatBE(0xffffffff), OOR_ERROR); |
| 3929 | |
| 3930 | throws(() => Buffer.allocUnsafe(8).readFloatLE(0xffffffff), OOR_ERROR); |
| 3931 | |
| 3932 | // Ensure negative values can't get past offset |
| 3933 | throws(() => Buffer.allocUnsafe(8).readFloatBE(-1), OOR_ERROR); |
| 3934 | throws(() => Buffer.allocUnsafe(8).readFloatLE(-1), OOR_ERROR); |
| 3935 | |
| 3936 | // Offset checks |
| 3937 | { |
| 3938 | const buf = Buffer.allocUnsafe(0); |
| 3939 | |
| 3940 | throws(() => buf.readUInt8(0), OOB_ERROR); |
| 3941 | throws(() => buf.readInt8(0), OOB_ERROR); |
| 3942 | } |
| 3943 | |
| 3944 | [16, 32].forEach((bit) => { |
| 3945 | const buf = Buffer.allocUnsafe(bit / 8 - 1); |
| 3946 | [`Int${bit}B`, `Int${bit}L`, `UInt${bit}B`, `UInt${bit}L`].forEach( |
| 3947 | (fn) => { |
| 3948 | throws(() => buf[`read${fn}E`](0), OOB_ERROR); |
| 3949 | } |
| 3950 | ); |
| 3951 | }); |
| 3952 | |
| 3953 | [16, 32].forEach((bits) => { |
| 3954 | const buf = Buffer.from([0xff, 0xff, 0xff, 0xff]); |
| 3955 | ['LE', 'BE'].forEach((endian) => { |
| 3956 | strictEqual( |
| 3957 | buf[`readUInt${bits}${endian}`](0), |
| 3958 | 0xffffffff >>> (32 - bits) |
| 3959 | ); |
| 3960 | |
| 3961 | strictEqual( |
| 3962 | buf[`readInt${bits}${endian}`](0), |
| 3963 | 0xffffffff >> (32 - bits) |
| 3964 | ); |
| 3965 | }); |
| 3966 | }); |
| 3967 | }, |
| 3968 | }; |
| 3969 | |
| 3970 | export const readDouble = { |
| 3971 | test(ctrl, env, ctx) { |
| 3972 | // Test (64 bit) double |
| 3973 | const buffer = Buffer.allocUnsafe(8); |
| 3974 | |
| 3975 | buffer[0] = 0x55; |
| 3976 | buffer[1] = 0x55; |
| 3977 | buffer[2] = 0x55; |
| 3978 | buffer[3] = 0x55; |
| 3979 | buffer[4] = 0x55; |
| 3980 | buffer[5] = 0x55; |
| 3981 | buffer[6] = 0xd5; |
| 3982 | buffer[7] = 0x3f; |
| 3983 | strictEqual(buffer.readDoubleBE(0), 1.1945305291680097e103); |
| 3984 | strictEqual(buffer.readDoubleLE(0), 0.3333333333333333); |
| 3985 | |
| 3986 | buffer[0] = 1; |
| 3987 | buffer[1] = 0; |
| 3988 | buffer[2] = 0; |
| 3989 | buffer[3] = 0; |
| 3990 | buffer[4] = 0; |
| 3991 | buffer[5] = 0; |
| 3992 | buffer[6] = 0xf0; |
| 3993 | buffer[7] = 0x3f; |
| 3994 | strictEqual(buffer.readDoubleBE(0), 7.291122019655968e-304); |
| 3995 | strictEqual(buffer.readDoubleLE(0), 1.0000000000000002); |
| 3996 | |
| 3997 | buffer[0] = 2; |
| 3998 | strictEqual(buffer.readDoubleBE(0), 4.778309726801735e-299); |
| 3999 | strictEqual(buffer.readDoubleLE(0), 1.0000000000000004); |
| 4000 | |
| 4001 | buffer[0] = 1; |
| 4002 | buffer[6] = 0; |
| 4003 | buffer[7] = 0; |
| 4004 | // eslint-disable-next-line no-loss-of-precision |
| 4005 | strictEqual(buffer.readDoubleBE(0), 7.291122019556398e-304); |
| 4006 | strictEqual(buffer.readDoubleLE(0), 5e-324); |
| 4007 | |
| 4008 | buffer[0] = 0xff; |
| 4009 | buffer[1] = 0xff; |
| 4010 | buffer[2] = 0xff; |
| 4011 | buffer[3] = 0xff; |
| 4012 | buffer[4] = 0xff; |
| 4013 | buffer[5] = 0xff; |
| 4014 | buffer[6] = 0x0f; |
| 4015 | buffer[7] = 0x00; |
| 4016 | ok(Number.isNaN(buffer.readDoubleBE(0))); |
| 4017 | strictEqual(buffer.readDoubleLE(0), 2.225073858507201e-308); |
| 4018 | |
| 4019 | buffer[6] = 0xef; |
| 4020 | buffer[7] = 0x7f; |
| 4021 | ok(Number.isNaN(buffer.readDoubleBE(0))); |
| 4022 | strictEqual(buffer.readDoubleLE(0), 1.7976931348623157e308); |
| 4023 | |
| 4024 | buffer[0] = 0; |
| 4025 | buffer[1] = 0; |
| 4026 | buffer[2] = 0; |
| 4027 | buffer[3] = 0; |
| 4028 | buffer[4] = 0; |
| 4029 | buffer[5] = 0; |
| 4030 | buffer[6] = 0xf0; |
| 4031 | buffer[7] = 0x3f; |
| 4032 | strictEqual(buffer.readDoubleBE(0), 3.03865e-319); |
| 4033 | strictEqual(buffer.readDoubleLE(0), 1); |
| 4034 | |
| 4035 | buffer[6] = 0; |
| 4036 | buffer[7] = 0x40; |
| 4037 | strictEqual(buffer.readDoubleBE(0), 3.16e-322); |
| 4038 | strictEqual(buffer.readDoubleLE(0), 2); |
| 4039 | |
| 4040 | buffer[7] = 0xc0; |
| 4041 | strictEqual(buffer.readDoubleBE(0), 9.5e-322); |
| 4042 | strictEqual(buffer.readDoubleLE(0), -2); |
| 4043 | |
| 4044 | buffer[6] = 0x10; |
| 4045 | buffer[7] = 0; |
| 4046 | strictEqual(buffer.readDoubleBE(0), 2.0237e-320); |
| 4047 | strictEqual(buffer.readDoubleLE(0), 2.2250738585072014e-308); |
| 4048 | |
| 4049 | buffer[6] = 0; |
| 4050 | strictEqual(buffer.readDoubleBE(0), 0); |
| 4051 | strictEqual(buffer.readDoubleLE(0), 0); |
| 4052 | ok(1 / buffer.readDoubleLE(0) >= 0); |
| 4053 | |
| 4054 | buffer[7] = 0x80; |
| 4055 | strictEqual(buffer.readDoubleBE(0), 6.3e-322); |
| 4056 | strictEqual(buffer.readDoubleLE(0), -0); |
| 4057 | ok(1 / buffer.readDoubleLE(0) < 0); |
| 4058 | |
| 4059 | buffer[6] = 0xf0; |
| 4060 | buffer[7] = 0x7f; |
| 4061 | strictEqual(buffer.readDoubleBE(0), 3.0418e-319); |
| 4062 | strictEqual(buffer.readDoubleLE(0), Infinity); |
| 4063 | |
| 4064 | buffer[7] = 0xff; |
| 4065 | strictEqual(buffer.readDoubleBE(0), 3.04814e-319); |
| 4066 | strictEqual(buffer.readDoubleLE(0), -Infinity); |
| 4067 | |
| 4068 | ['readDoubleLE', 'readDoubleBE'].forEach((fn) => { |
| 4069 | // Verify that default offset works fine. |
| 4070 | buffer[fn](undefined); |
| 4071 | buffer[fn](); |
| 4072 | |
| 4073 | ['', '0', null, {}, [], () => {}, true, false].forEach((off) => { |
| 4074 | throws(() => buffer[fn](off), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 4075 | }); |
| 4076 | |
| 4077 | [Infinity, -1, 1].forEach((offset) => { |
| 4078 | throws(() => buffer[fn](offset), { |
| 4079 | code: 'ERR_OUT_OF_RANGE', |
| 4080 | name: 'RangeError', |
| 4081 | }); |
| 4082 | }); |
| 4083 | |
| 4084 | throws(() => Buffer.alloc(1)[fn](1), { |
| 4085 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 4086 | name: 'RangeError', |
| 4087 | message: 'Attempt to access memory outside buffer bounds', |
| 4088 | }); |
| 4089 | |
| 4090 | [NaN, 1.01].forEach((offset) => { |
| 4091 | throws(() => buffer[fn](offset), { |
| 4092 | code: 'ERR_OUT_OF_RANGE', |
| 4093 | name: 'RangeError', |
| 4094 | message: |
| 4095 | 'The value of "offset" is out of range. ' + |
| 4096 | `It must be an integer. Received ${offset}`, |
| 4097 | }); |
| 4098 | }); |
| 4099 | }); |
| 4100 | }, |
| 4101 | }; |
| 4102 | |
| 4103 | export const readFloat = { |
| 4104 | test(ctrl, env, ctx) { |
| 4105 | // Test 32 bit float |
| 4106 | const buffer = Buffer.alloc(4); |
| 4107 | |
| 4108 | buffer[0] = 0; |
| 4109 | buffer[1] = 0; |
| 4110 | buffer[2] = 0x80; |
| 4111 | buffer[3] = 0x3f; |
| 4112 | strictEqual(buffer.readFloatBE(0), 4.600602988224807e-41); |
| 4113 | strictEqual(buffer.readFloatLE(0), 1); |
| 4114 | |
| 4115 | buffer[0] = 0; |
| 4116 | buffer[1] = 0; |
| 4117 | buffer[2] = 0; |
| 4118 | buffer[3] = 0xc0; |
| 4119 | strictEqual(buffer.readFloatBE(0), 2.6904930515036488e-43); |
| 4120 | strictEqual(buffer.readFloatLE(0), -2); |
| 4121 | |
| 4122 | buffer[0] = 0xff; |
| 4123 | buffer[1] = 0xff; |
| 4124 | buffer[2] = 0x7f; |
| 4125 | buffer[3] = 0x7f; |
| 4126 | ok(Number.isNaN(buffer.readFloatBE(0))); |
| 4127 | strictEqual(buffer.readFloatLE(0), 3.4028234663852886e38); |
| 4128 | |
| 4129 | buffer[0] = 0xab; |
| 4130 | buffer[1] = 0xaa; |
| 4131 | buffer[2] = 0xaa; |
| 4132 | buffer[3] = 0x3e; |
| 4133 | strictEqual(buffer.readFloatBE(0), -1.2126478207002966e-12); |
| 4134 | strictEqual(buffer.readFloatLE(0), 0.3333333432674408); |
| 4135 | |
| 4136 | buffer[0] = 0; |
| 4137 | buffer[1] = 0; |
| 4138 | buffer[2] = 0; |
| 4139 | buffer[3] = 0; |
| 4140 | strictEqual(buffer.readFloatBE(0), 0); |
| 4141 | strictEqual(buffer.readFloatLE(0), 0); |
| 4142 | ok(1 / buffer.readFloatLE(0) >= 0); |
| 4143 | |
| 4144 | buffer[3] = 0x80; |
| 4145 | strictEqual(buffer.readFloatBE(0), 1.793662034335766e-43); |
| 4146 | strictEqual(buffer.readFloatLE(0), -0); |
| 4147 | ok(1 / buffer.readFloatLE(0) < 0); |
| 4148 | |
| 4149 | buffer[0] = 0; |
| 4150 | buffer[1] = 0; |
| 4151 | buffer[2] = 0x80; |
| 4152 | buffer[3] = 0x7f; |
| 4153 | strictEqual(buffer.readFloatBE(0), 4.609571298396486e-41); |
| 4154 | strictEqual(buffer.readFloatLE(0), Infinity); |
| 4155 | |
| 4156 | buffer[0] = 0; |
| 4157 | buffer[1] = 0; |
| 4158 | buffer[2] = 0x80; |
| 4159 | buffer[3] = 0xff; |
| 4160 | strictEqual(buffer.readFloatBE(0), 4.627507918739843e-41); |
| 4161 | strictEqual(buffer.readFloatLE(0), -Infinity); |
| 4162 | |
| 4163 | ['readFloatLE', 'readFloatBE'].forEach((fn) => { |
| 4164 | // Verify that default offset works fine. |
| 4165 | buffer[fn](undefined); |
| 4166 | buffer[fn](); |
| 4167 | |
| 4168 | ['', '0', null, {}, [], () => {}, true, false].forEach((off) => { |
| 4169 | throws(() => buffer[fn](off), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 4170 | }); |
| 4171 | |
| 4172 | [Infinity, -1, 1].forEach((offset) => { |
| 4173 | throws(() => buffer[fn](offset), { |
| 4174 | code: 'ERR_OUT_OF_RANGE', |
| 4175 | name: 'RangeError', |
| 4176 | }); |
| 4177 | }); |
| 4178 | |
| 4179 | throws(() => Buffer.alloc(1)[fn](1), { |
| 4180 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 4181 | name: 'RangeError', |
| 4182 | message: 'Attempt to access memory outside buffer bounds', |
| 4183 | }); |
| 4184 | |
| 4185 | [NaN, 1.01].forEach((offset) => { |
| 4186 | throws(() => buffer[fn](offset), { |
| 4187 | code: 'ERR_OUT_OF_RANGE', |
| 4188 | name: 'RangeError', |
| 4189 | message: |
| 4190 | 'The value of "offset" is out of range. ' + |
| 4191 | `It must be an integer. Received ${offset}`, |
| 4192 | }); |
| 4193 | }); |
| 4194 | }); |
| 4195 | }, |
| 4196 | }; |
| 4197 | |
| 4198 | export const readInt = { |
| 4199 | test(ctrl, env, ctx) { |
| 4200 | // Test OOB |
| 4201 | { |
| 4202 | const buffer = Buffer.alloc(4); |
| 4203 | |
| 4204 | ['Int8', 'Int16BE', 'Int16LE', 'Int32BE', 'Int32LE'].forEach((fn) => { |
| 4205 | // Verify that default offset works fine. |
| 4206 | buffer[`read${fn}`](undefined); |
| 4207 | buffer[`read${fn}`](); |
| 4208 | |
| 4209 | ['', '0', null, {}, [], () => {}, true, false].forEach((o) => { |
| 4210 | throws(() => buffer[`read${fn}`](o), { |
| 4211 | code: 'ERR_INVALID_ARG_TYPE', |
| 4212 | name: 'TypeError', |
| 4213 | }); |
| 4214 | }); |
| 4215 | |
| 4216 | [Infinity, -1, -4294967295].forEach((offset) => { |
| 4217 | throws(() => buffer[`read${fn}`](offset), { |
| 4218 | code: 'ERR_OUT_OF_RANGE', |
| 4219 | name: 'RangeError', |
| 4220 | }); |
| 4221 | }); |
| 4222 | |
| 4223 | [NaN, 1.01].forEach((offset) => { |
| 4224 | throws(() => buffer[`read${fn}`](offset), { |
| 4225 | code: 'ERR_OUT_OF_RANGE', |
| 4226 | name: 'RangeError', |
| 4227 | }); |
| 4228 | }); |
| 4229 | }); |
| 4230 | } |
| 4231 | |
| 4232 | // Test 8 bit signed integers |
| 4233 | { |
| 4234 | const data = Buffer.from([0x23, 0xab, 0x7c, 0xef]); |
| 4235 | |
| 4236 | strictEqual(data.readInt8(0), 0x23); |
| 4237 | |
| 4238 | data[0] = 0xff; |
| 4239 | strictEqual(data.readInt8(0), -1); |
| 4240 | |
| 4241 | data[0] = 0x87; |
| 4242 | strictEqual(data.readInt8(0), -121); |
| 4243 | strictEqual(data.readInt8(1), -85); |
| 4244 | strictEqual(data.readInt8(2), 124); |
| 4245 | strictEqual(data.readInt8(3), -17); |
| 4246 | } |
| 4247 | |
| 4248 | // Test 16 bit integers |
| 4249 | { |
| 4250 | const buffer = Buffer.from([0x16, 0x79, 0x65, 0x6e, 0x69, 0x78]); |
| 4251 | |
| 4252 | strictEqual(buffer.readInt16BE(0), 0x1679); |
| 4253 | strictEqual(buffer.readInt16LE(0), 0x7916); |
| 4254 | |
| 4255 | buffer[0] = 0xff; |
| 4256 | buffer[1] = 0x80; |
| 4257 | strictEqual(buffer.readInt16BE(0), -128); |
| 4258 | strictEqual(buffer.readInt16LE(0), -32513); |
| 4259 | |
| 4260 | buffer[0] = 0x77; |
| 4261 | buffer[1] = 0x65; |
| 4262 | strictEqual(buffer.readInt16BE(0), 0x7765); |
| 4263 | strictEqual(buffer.readInt16BE(1), 0x6565); |
| 4264 | strictEqual(buffer.readInt16BE(2), 0x656e); |
| 4265 | strictEqual(buffer.readInt16BE(3), 0x6e69); |
| 4266 | strictEqual(buffer.readInt16BE(4), 0x6978); |
| 4267 | strictEqual(buffer.readInt16LE(0), 0x6577); |
| 4268 | strictEqual(buffer.readInt16LE(1), 0x6565); |
| 4269 | strictEqual(buffer.readInt16LE(2), 0x6e65); |
| 4270 | strictEqual(buffer.readInt16LE(3), 0x696e); |
| 4271 | strictEqual(buffer.readInt16LE(4), 0x7869); |
| 4272 | } |
| 4273 | |
| 4274 | // Test 32 bit integers |
| 4275 | { |
| 4276 | const buffer = Buffer.from([0x43, 0x53, 0x16, 0x79, 0x36, 0x17]); |
| 4277 | |
| 4278 | strictEqual(buffer.readInt32BE(0), 0x43531679); |
| 4279 | strictEqual(buffer.readInt32LE(0), 0x79165343); |
| 4280 | |
| 4281 | buffer[0] = 0xff; |
| 4282 | buffer[1] = 0xfe; |
| 4283 | buffer[2] = 0xef; |
| 4284 | buffer[3] = 0xfa; |
| 4285 | strictEqual(buffer.readInt32BE(0), -69638); |
| 4286 | strictEqual(buffer.readInt32LE(0), -84934913); |
| 4287 | |
| 4288 | buffer[0] = 0x42; |
| 4289 | buffer[1] = 0xc3; |
| 4290 | buffer[2] = 0x95; |
| 4291 | buffer[3] = 0xa9; |
| 4292 | strictEqual(buffer.readInt32BE(0), 0x42c395a9); |
| 4293 | strictEqual(buffer.readInt32BE(1), -1013601994); |
| 4294 | strictEqual(buffer.readInt32BE(2), -1784072681); |
| 4295 | strictEqual(buffer.readInt32LE(0), -1449802942); |
| 4296 | strictEqual(buffer.readInt32LE(1), 917083587); |
| 4297 | strictEqual(buffer.readInt32LE(2), 389458325); |
| 4298 | } |
| 4299 | |
| 4300 | // Test Int |
| 4301 | { |
| 4302 | const buffer = Buffer.from([ |
| 4303 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 4304 | ]); |
| 4305 | |
| 4306 | strictEqual(buffer.readIntLE(0, 1), 0x01); |
| 4307 | strictEqual(buffer.readIntBE(0, 1), 0x01); |
| 4308 | strictEqual(buffer.readIntLE(0, 3), 0x030201); |
| 4309 | strictEqual(buffer.readIntBE(0, 3), 0x010203); |
| 4310 | strictEqual(buffer.readIntLE(0, 5), 0x0504030201); |
| 4311 | strictEqual(buffer.readIntBE(0, 5), 0x0102030405); |
| 4312 | strictEqual(buffer.readIntLE(0, 6), 0x060504030201); |
| 4313 | strictEqual(buffer.readIntBE(0, 6), 0x010203040506); |
| 4314 | strictEqual(buffer.readIntLE(1, 6), 0x070605040302); |
| 4315 | strictEqual(buffer.readIntBE(1, 6), 0x020304050607); |
| 4316 | strictEqual(buffer.readIntLE(2, 6), 0x080706050403); |
| 4317 | strictEqual(buffer.readIntBE(2, 6), 0x030405060708); |
| 4318 | |
| 4319 | // Check byteLength. |
| 4320 | ['readIntBE', 'readIntLE'].forEach((fn) => { |
| 4321 | ['', '0', null, {}, [], () => {}, true, false, undefined].forEach( |
| 4322 | (len) => { |
| 4323 | throws(() => buffer[fn](0, len), { name: 'RangeError' }); |
| 4324 | } |
| 4325 | ); |
| 4326 | |
| 4327 | [Infinity, -1].forEach((byteLength) => { |
| 4328 | throws(() => buffer[fn](0, byteLength), { |
| 4329 | name: 'RangeError', |
| 4330 | }); |
| 4331 | }); |
| 4332 | |
| 4333 | [NaN, 1.01].forEach((byteLength) => { |
| 4334 | throws(() => buffer[fn](0, byteLength), { |
| 4335 | name: 'RangeError', |
| 4336 | }); |
| 4337 | }); |
| 4338 | }); |
| 4339 | |
| 4340 | // Test 1 to 6 bytes. |
| 4341 | for (let i = 1; i <= 6; i++) { |
| 4342 | ['readIntBE', 'readIntLE'].forEach((fn) => { |
| 4343 | ['', '0', null, {}, [], () => {}, true, false, undefined].forEach( |
| 4344 | (o) => { |
| 4345 | throws(() => buffer[fn](o, i), { |
| 4346 | name: 'TypeError', |
| 4347 | }); |
| 4348 | } |
| 4349 | ); |
| 4350 | |
| 4351 | [Infinity, -1, -4294967295].forEach((offset) => { |
| 4352 | throws(() => buffer[fn](offset, i), { |
| 4353 | name: 'RangeError', |
| 4354 | }); |
| 4355 | }); |
| 4356 | |
| 4357 | [NaN, 1.01].forEach((offset) => { |
| 4358 | throws(() => buffer[fn](offset, i), { |
| 4359 | name: 'RangeError', |
| 4360 | }); |
| 4361 | }); |
| 4362 | }); |
| 4363 | } |
| 4364 | } |
| 4365 | }, |
| 4366 | }; |
| 4367 | |
| 4368 | export const readUint = { |
| 4369 | test(ctrl, env, ctx) { |
| 4370 | // Test OOB |
| 4371 | { |
| 4372 | const buffer = Buffer.alloc(4); |
| 4373 | |
| 4374 | ['UInt8', 'UInt16BE', 'UInt16LE', 'UInt32BE', 'UInt32LE'].forEach( |
| 4375 | (fn) => { |
| 4376 | // Verify that default offset works fine. |
| 4377 | buffer[`read${fn}`](undefined); |
| 4378 | buffer[`read${fn}`](); |
| 4379 | |
| 4380 | ['', '0', null, {}, [], () => {}, true, false].forEach((o) => { |
| 4381 | throws(() => buffer[`read${fn}`](o), { |
| 4382 | code: 'ERR_INVALID_ARG_TYPE', |
| 4383 | name: 'TypeError', |
| 4384 | }); |
| 4385 | }); |
| 4386 | |
| 4387 | [Infinity, -1, -4294967295].forEach((offset) => { |
| 4388 | throws(() => buffer[`read${fn}`](offset), { |
| 4389 | code: 'ERR_OUT_OF_RANGE', |
| 4390 | name: 'RangeError', |
| 4391 | }); |
| 4392 | }); |
| 4393 | |
| 4394 | [NaN, 1.01].forEach((offset) => { |
| 4395 | throws(() => buffer[`read${fn}`](offset), { |
| 4396 | code: 'ERR_OUT_OF_RANGE', |
| 4397 | name: 'RangeError', |
| 4398 | }); |
| 4399 | }); |
| 4400 | } |
| 4401 | ); |
| 4402 | } |
| 4403 | |
| 4404 | // Test 8 bit unsigned integers |
| 4405 | { |
| 4406 | const data = Buffer.from([0xff, 0x2a, 0x2a, 0x2a]); |
| 4407 | strictEqual(data.readUInt8(0), 255); |
| 4408 | strictEqual(data.readUInt8(1), 42); |
| 4409 | strictEqual(data.readUInt8(2), 42); |
| 4410 | strictEqual(data.readUInt8(3), 42); |
| 4411 | } |
| 4412 | |
| 4413 | // Test 16 bit unsigned integers |
| 4414 | { |
| 4415 | const data = Buffer.from([0x00, 0x2a, 0x42, 0x3f]); |
| 4416 | strictEqual(data.readUInt16BE(0), 0x2a); |
| 4417 | strictEqual(data.readUInt16BE(1), 0x2a42); |
| 4418 | strictEqual(data.readUInt16BE(2), 0x423f); |
| 4419 | strictEqual(data.readUInt16LE(0), 0x2a00); |
| 4420 | strictEqual(data.readUInt16LE(1), 0x422a); |
| 4421 | strictEqual(data.readUInt16LE(2), 0x3f42); |
| 4422 | |
| 4423 | data[0] = 0xfe; |
| 4424 | data[1] = 0xfe; |
| 4425 | strictEqual(data.readUInt16BE(0), 0xfefe); |
| 4426 | strictEqual(data.readUInt16LE(0), 0xfefe); |
| 4427 | } |
| 4428 | |
| 4429 | // Test 32 bit unsigned integers |
| 4430 | { |
| 4431 | const data = Buffer.from([0x32, 0x65, 0x42, 0x56, 0x23, 0xff]); |
| 4432 | strictEqual(data.readUInt32BE(0), 0x32654256); |
| 4433 | strictEqual(data.readUInt32BE(1), 0x65425623); |
| 4434 | strictEqual(data.readUInt32BE(2), 0x425623ff); |
| 4435 | strictEqual(data.readUInt32LE(0), 0x56426532); |
| 4436 | strictEqual(data.readUInt32LE(1), 0x23564265); |
| 4437 | strictEqual(data.readUInt32LE(2), 0xff235642); |
| 4438 | } |
| 4439 | |
| 4440 | // Test UInt |
| 4441 | { |
| 4442 | const buffer = Buffer.from([ |
| 4443 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 4444 | ]); |
| 4445 | |
| 4446 | strictEqual(buffer.readUIntLE(0, 1), 0x01); |
| 4447 | strictEqual(buffer.readUIntBE(0, 1), 0x01); |
| 4448 | strictEqual(buffer.readUIntLE(0, 3), 0x030201); |
| 4449 | strictEqual(buffer.readUIntBE(0, 3), 0x010203); |
| 4450 | strictEqual(buffer.readUIntLE(0, 5), 0x0504030201); |
| 4451 | strictEqual(buffer.readUIntBE(0, 5), 0x0102030405); |
| 4452 | strictEqual(buffer.readUIntLE(0, 6), 0x060504030201); |
| 4453 | strictEqual(buffer.readUIntBE(0, 6), 0x010203040506); |
| 4454 | strictEqual(buffer.readUIntLE(1, 6), 0x070605040302); |
| 4455 | strictEqual(buffer.readUIntBE(1, 6), 0x020304050607); |
| 4456 | strictEqual(buffer.readUIntLE(2, 6), 0x080706050403); |
| 4457 | strictEqual(buffer.readUIntBE(2, 6), 0x030405060708); |
| 4458 | |
| 4459 | // Check byteLength. |
| 4460 | ['readUIntBE', 'readUIntLE'].forEach((fn) => { |
| 4461 | ['', '0', null, {}, [], () => {}, true, false, undefined].forEach( |
| 4462 | (len) => { |
| 4463 | throws(() => buffer[fn](0, len), { name: 'RangeError' }); |
| 4464 | } |
| 4465 | ); |
| 4466 | |
| 4467 | [Infinity, -1].forEach((byteLength) => { |
| 4468 | throws(() => buffer[fn](0, byteLength), { |
| 4469 | name: 'RangeError', |
| 4470 | }); |
| 4471 | }); |
| 4472 | |
| 4473 | [NaN, 1.01].forEach((byteLength) => { |
| 4474 | throws(() => buffer[fn](0, byteLength), { |
| 4475 | name: 'RangeError', |
| 4476 | }); |
| 4477 | }); |
| 4478 | }); |
| 4479 | |
| 4480 | // Test 1 to 6 bytes. |
| 4481 | for (let i = 1; i <= 6; i++) { |
| 4482 | ['readUIntBE', 'readUIntLE'].forEach((fn) => { |
| 4483 | ['', '0', null, {}, [], () => {}, true, false, undefined].forEach( |
| 4484 | (o) => { |
| 4485 | throws(() => buffer[fn](o, i), { |
| 4486 | name: 'TypeError', |
| 4487 | }); |
| 4488 | } |
| 4489 | ); |
| 4490 | |
| 4491 | [Infinity, -1, -4294967295].forEach((offset) => { |
| 4492 | throws(() => buffer[fn](offset, i), { |
| 4493 | name: 'RangeError', |
| 4494 | }); |
| 4495 | }); |
| 4496 | |
| 4497 | [NaN, 1.01].forEach((offset) => { |
| 4498 | throws(() => buffer[fn](offset, i), { |
| 4499 | name: 'RangeError', |
| 4500 | }); |
| 4501 | }); |
| 4502 | }); |
| 4503 | } |
| 4504 | } |
| 4505 | }, |
| 4506 | }; |
| 4507 | |
| 4508 | export const sharedArrayBuffer = { |
| 4509 | test(ctrl, env, ctx) { |
| 4510 | const sab = new SharedArrayBuffer(24); |
| 4511 | const arr1 = new Uint16Array(sab); |
| 4512 | const arr2 = new Uint16Array(12); |
| 4513 | arr2[0] = 5000; |
| 4514 | arr1[0] = 5000; |
| 4515 | arr1[1] = 4000; |
| 4516 | arr2[1] = 4000; |
| 4517 | |
| 4518 | const arr_buf = Buffer.from(arr1.buffer); |
| 4519 | const ar_buf = Buffer.from(arr2.buffer); |
| 4520 | |
| 4521 | deepStrictEqual(arr_buf, ar_buf); |
| 4522 | |
| 4523 | arr1[1] = 6000; |
| 4524 | arr2[1] = 6000; |
| 4525 | |
| 4526 | deepStrictEqual(arr_buf, ar_buf); |
| 4527 | |
| 4528 | // Checks for calling Buffer.byteLength on a SharedArrayBuffer. |
| 4529 | strictEqual(Buffer.byteLength(sab), sab.byteLength); |
| 4530 | |
| 4531 | Buffer.from({ buffer: sab }); // Should not throw. |
| 4532 | }, |
| 4533 | }; |
| 4534 | |
| 4535 | export const slice = { |
| 4536 | test(ctrl, env, ctx) { |
| 4537 | strictEqual(Buffer.from('hello', 'utf8').slice(0, 0).length, 0); |
| 4538 | strictEqual(Buffer('hello', 'utf8').slice(0, 0).length, 0); |
| 4539 | |
| 4540 | const buf = Buffer.from('0123456789', 'utf8'); |
| 4541 | const expectedSameBufs = [ |
| 4542 | [buf.slice(-10, 10), Buffer.from('0123456789', 'utf8')], |
| 4543 | [buf.slice(-20, 10), Buffer.from('0123456789', 'utf8')], |
| 4544 | [buf.slice(-20, -10), Buffer.from('', 'utf8')], |
| 4545 | [buf.slice(), Buffer.from('0123456789', 'utf8')], |
| 4546 | [buf.slice(0), Buffer.from('0123456789', 'utf8')], |
| 4547 | [buf.slice(0, 0), Buffer.from('', 'utf8')], |
| 4548 | [buf.slice(undefined), Buffer.from('0123456789', 'utf8')], |
| 4549 | [buf.slice('foobar'), Buffer.from('0123456789', 'utf8')], |
| 4550 | [buf.slice(undefined, undefined), Buffer.from('0123456789', 'utf8')], |
| 4551 | [buf.slice(2), Buffer.from('23456789', 'utf8')], |
| 4552 | [buf.slice(5), Buffer.from('56789', 'utf8')], |
| 4553 | [buf.slice(10), Buffer.from('', 'utf8')], |
| 4554 | [buf.slice(5, 8), Buffer.from('567', 'utf8')], |
| 4555 | [buf.slice(8, -1), Buffer.from('8', 'utf8')], |
| 4556 | [buf.slice(-10), Buffer.from('0123456789', 'utf8')], |
| 4557 | [buf.slice(0, -9), Buffer.from('0', 'utf8')], |
| 4558 | [buf.slice(0, -10), Buffer.from('', 'utf8')], |
| 4559 | [buf.slice(0, -1), Buffer.from('012345678', 'utf8')], |
| 4560 | [buf.slice(2, -2), Buffer.from('234567', 'utf8')], |
| 4561 | [buf.slice(0, 65536), Buffer.from('0123456789', 'utf8')], |
| 4562 | [buf.slice(65536, 0), Buffer.from('', 'utf8')], |
| 4563 | [buf.slice(-5, -8), Buffer.from('', 'utf8')], |
| 4564 | [buf.slice(-5, -3), Buffer.from('56', 'utf8')], |
| 4565 | [buf.slice(-10, 10), Buffer.from('0123456789', 'utf8')], |
| 4566 | [buf.slice('0', '1'), Buffer.from('0', 'utf8')], |
| 4567 | [buf.slice('-5', '10'), Buffer.from('56789', 'utf8')], |
| 4568 | [buf.slice('-10', '10'), Buffer.from('0123456789', 'utf8')], |
| 4569 | [buf.slice('-10', '-5'), Buffer.from('01234', 'utf8')], |
| 4570 | [buf.slice('-10', '-0'), Buffer.from('', 'utf8')], |
| 4571 | [buf.slice('111'), Buffer.from('', 'utf8')], |
| 4572 | [buf.slice('0', '-111'), Buffer.from('', 'utf8')], |
| 4573 | ]; |
| 4574 | |
| 4575 | for (let i = 0, s = buf.toString(); i < buf.length; ++i) { |
| 4576 | expectedSameBufs.push( |
| 4577 | [buf.slice(i), Buffer.from(s.slice(i))], |
| 4578 | [buf.slice(0, i), Buffer.from(s.slice(0, i))], |
| 4579 | [buf.slice(-i), Buffer.from(s.slice(-i))], |
| 4580 | [buf.slice(0, -i), Buffer.from(s.slice(0, -i))] |
| 4581 | ); |
| 4582 | } |
| 4583 | |
| 4584 | expectedSameBufs.forEach(([buf1, buf2]) => { |
| 4585 | strictEqual(Buffer.compare(buf1, buf2), 0); |
| 4586 | }); |
| 4587 | |
| 4588 | const utf16Buf = Buffer.from('0123456789', 'utf16le'); |
| 4589 | deepStrictEqual(utf16Buf.slice(0, 6), Buffer.from('012', 'utf16le')); |
| 4590 | // Try to slice a zero length Buffer. |
| 4591 | // See https://github.com/joyent/node/issues/5881 |
| 4592 | strictEqual(Buffer.alloc(0).slice(0, 1).length, 0); |
| 4593 | |
| 4594 | { |
| 4595 | // Single argument slice |
| 4596 | strictEqual( |
| 4597 | Buffer.from('abcde', 'utf8').slice(1).toString('utf8'), |
| 4598 | 'bcde' |
| 4599 | ); |
| 4600 | } |
| 4601 | |
| 4602 | // slice(0,0).length === 0 |
| 4603 | strictEqual(Buffer.from('hello', 'utf8').slice(0, 0).length, 0); |
| 4604 | |
| 4605 | { |
| 4606 | // Regression tests for https://github.com/nodejs/node/issues/9096 |
| 4607 | const buf = Buffer.from('abcd', 'utf8'); |
| 4608 | strictEqual(buf.slice(buf.length / 3).toString('utf8'), 'bcd'); |
| 4609 | strictEqual(buf.slice(buf.length / 3, buf.length).toString(), 'bcd'); |
| 4610 | } |
| 4611 | |
| 4612 | { |
| 4613 | const buf = Buffer.from('abcdefg', 'utf8'); |
| 4614 | strictEqual( |
| 4615 | buf.slice(-(-1 >>> 0) - 1).toString('utf8'), |
| 4616 | buf.toString('utf8') |
| 4617 | ); |
| 4618 | } |
| 4619 | |
| 4620 | { |
| 4621 | const buf = Buffer.from('abc', 'utf8'); |
| 4622 | strictEqual(buf.slice(-0.5).toString('utf8'), buf.toString('utf8')); |
| 4623 | } |
| 4624 | |
| 4625 | { |
| 4626 | const buf = Buffer.from([ |
| 4627 | 1, 29, 0, 0, 1, 143, 216, 162, 92, 254, 248, 63, 0, 0, 0, 18, 184, 6, 0, |
| 4628 | 175, 29, 0, 8, 11, 1, 0, 0, |
| 4629 | ]); |
| 4630 | const chunk1 = Buffer.from([ |
| 4631 | 1, 29, 0, 0, 1, 143, 216, 162, 92, 254, 248, 63, 0, |
| 4632 | ]); |
| 4633 | const chunk2 = Buffer.from([ |
| 4634 | 0, 0, 18, 184, 6, 0, 175, 29, 0, 8, 11, 1, 0, 0, |
| 4635 | ]); |
| 4636 | const middle = buf.length / 2; |
| 4637 | |
| 4638 | deepStrictEqual(buf.slice(0, middle), chunk1); |
| 4639 | deepStrictEqual(buf.slice(middle), chunk2); |
| 4640 | } |
| 4641 | }, |
| 4642 | }; |
| 4643 | |
| 4644 | export const swap = { |
| 4645 | test(ctrl, env, ctx) { |
| 4646 | // Test buffers small enough to use the JS implementation |
| 4647 | { |
| 4648 | const buf = Buffer.from([ |
| 4649 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, |
| 4650 | 0x0d, 0x0e, 0x0f, 0x10, |
| 4651 | ]); |
| 4652 | |
| 4653 | strictEqual(buf, buf.swap16()); |
| 4654 | deepStrictEqual( |
| 4655 | buf, |
| 4656 | Buffer.from([ |
| 4657 | 0x02, 0x01, 0x04, 0x03, 0x06, 0x05, 0x08, 0x07, 0x0a, 0x09, 0x0c, |
| 4658 | 0x0b, 0x0e, 0x0d, 0x10, 0x0f, |
| 4659 | ]) |
| 4660 | ); |
| 4661 | buf.swap16(); // restore |
| 4662 | |
| 4663 | strictEqual(buf, buf.swap32()); |
| 4664 | deepStrictEqual( |
| 4665 | buf, |
| 4666 | Buffer.from([ |
| 4667 | 0x04, 0x03, 0x02, 0x01, 0x08, 0x07, 0x06, 0x05, 0x0c, 0x0b, 0x0a, |
| 4668 | 0x09, 0x10, 0x0f, 0x0e, 0x0d, |
| 4669 | ]) |
| 4670 | ); |
| 4671 | buf.swap32(); // restore |
| 4672 | |
| 4673 | strictEqual(buf, buf.swap64()); |
| 4674 | deepStrictEqual( |
| 4675 | buf, |
| 4676 | Buffer.from([ |
| 4677 | 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x10, 0x0f, 0x0e, |
| 4678 | 0x0d, 0x0c, 0x0b, 0x0a, 0x09, |
| 4679 | ]) |
| 4680 | ); |
| 4681 | } |
| 4682 | |
| 4683 | // Operates in-place |
| 4684 | { |
| 4685 | const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7]); |
| 4686 | buf.slice(1, 5).swap32(); |
| 4687 | deepStrictEqual(buf, Buffer.from([0x1, 0x5, 0x4, 0x3, 0x2, 0x6, 0x7])); |
| 4688 | buf.slice(1, 5).swap16(); |
| 4689 | deepStrictEqual(buf, Buffer.from([0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7])); |
| 4690 | |
| 4691 | // Length assertions |
| 4692 | const re16 = /Buffer size must be a multiple of 16-bits/; |
| 4693 | const re32 = /Buffer size must be a multiple of 32-bits/; |
| 4694 | const re64 = /Buffer size must be a multiple of 64-bits/; |
| 4695 | |
| 4696 | throws(() => Buffer.from(buf).swap16(), re16); |
| 4697 | throws(() => Buffer.alloc(1025).swap16(), re16); |
| 4698 | throws(() => Buffer.from(buf).swap32(), re32); |
| 4699 | throws(() => buf.slice(1, 3).swap32(), re32); |
| 4700 | throws(() => Buffer.alloc(1025).swap32(), re32); |
| 4701 | throws(() => buf.slice(1, 3).swap64(), re64); |
| 4702 | throws(() => Buffer.alloc(1025).swap64(), re64); |
| 4703 | } |
| 4704 | |
| 4705 | { |
| 4706 | const buf = Buffer.from([ |
| 4707 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, |
| 4708 | 0x0d, 0x0e, 0x0f, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 4709 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 4710 | ]); |
| 4711 | |
| 4712 | buf.slice(2, 18).swap64(); |
| 4713 | |
| 4714 | deepStrictEqual( |
| 4715 | buf, |
| 4716 | Buffer.from([ |
| 4717 | 0x01, 0x02, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, |
| 4718 | 0x01, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x03, 0x04, 0x05, 0x06, |
| 4719 | 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 4720 | ]) |
| 4721 | ); |
| 4722 | } |
| 4723 | |
| 4724 | // Force use of native code (Buffer size above threshold limit for js impl) |
| 4725 | { |
| 4726 | const bufData = new Uint32Array(256).fill(0x04030201); |
| 4727 | const buf = Buffer.from(bufData.buffer, bufData.byteOffset); |
| 4728 | const otherBufData = new Uint32Array(256).fill(0x03040102); |
| 4729 | const otherBuf = Buffer.from( |
| 4730 | otherBufData.buffer, |
| 4731 | otherBufData.byteOffset |
| 4732 | ); |
| 4733 | buf.swap16(); |
| 4734 | deepStrictEqual(buf, otherBuf); |
| 4735 | } |
| 4736 | |
| 4737 | { |
| 4738 | const bufData = new Uint32Array(256).fill(0x04030201); |
| 4739 | const buf = Buffer.from(bufData.buffer); |
| 4740 | const otherBufData = new Uint32Array(256).fill(0x01020304); |
| 4741 | const otherBuf = Buffer.from( |
| 4742 | otherBufData.buffer, |
| 4743 | otherBufData.byteOffset |
| 4744 | ); |
| 4745 | buf.swap32(); |
| 4746 | deepStrictEqual(buf, otherBuf); |
| 4747 | } |
| 4748 | |
| 4749 | { |
| 4750 | const bufData = new Uint8Array(256 * 8); |
| 4751 | const otherBufData = new Uint8Array(256 * 8); |
| 4752 | for (let i = 0; i < bufData.length; i++) { |
| 4753 | bufData[i] = i % 8; |
| 4754 | otherBufData[otherBufData.length - i - 1] = i % 8; |
| 4755 | } |
| 4756 | const buf = Buffer.from(bufData.buffer, bufData.byteOffset); |
| 4757 | const otherBuf = Buffer.from( |
| 4758 | otherBufData.buffer, |
| 4759 | otherBufData.byteOffset |
| 4760 | ); |
| 4761 | buf.swap64(); |
| 4762 | deepStrictEqual(buf, otherBuf); |
| 4763 | } |
| 4764 | |
| 4765 | // Test native code with buffers that are not memory-aligned |
| 4766 | { |
| 4767 | const bufData = new Uint8Array(256 * 8); |
| 4768 | const otherBufData = new Uint8Array(256 * 8 - 2); |
| 4769 | for (let i = 0; i < bufData.length; i++) { |
| 4770 | bufData[i] = i % 2; |
| 4771 | } |
| 4772 | for (let i = 1; i < otherBufData.length; i++) { |
| 4773 | otherBufData[otherBufData.length - i] = (i + 1) % 2; |
| 4774 | } |
| 4775 | const buf = Buffer.from(bufData.buffer, bufData.byteOffset); |
| 4776 | // 0|1 0|1 0|1... |
| 4777 | const otherBuf = Buffer.from( |
| 4778 | otherBufData.buffer, |
| 4779 | otherBufData.byteOffset |
| 4780 | ); |
| 4781 | // 0|0 1|0 1|0... |
| 4782 | |
| 4783 | buf.slice(1, buf.length - 1).swap16(); |
| 4784 | deepStrictEqual(buf.slice(0, otherBuf.length), otherBuf); |
| 4785 | } |
| 4786 | |
| 4787 | { |
| 4788 | const bufData = new Uint8Array(256 * 8); |
| 4789 | const otherBufData = new Uint8Array(256 * 8 - 4); |
| 4790 | for (let i = 0; i < bufData.length; i++) { |
| 4791 | bufData[i] = i % 4; |
| 4792 | } |
| 4793 | for (let i = 1; i < otherBufData.length; i++) { |
| 4794 | otherBufData[otherBufData.length - i] = (i + 1) % 4; |
| 4795 | } |
| 4796 | const buf = Buffer.from(bufData.buffer, bufData.byteOffset); |
| 4797 | // 0|1 2 3 0|1 2 3... |
| 4798 | const otherBuf = Buffer.from( |
| 4799 | otherBufData.buffer, |
| 4800 | otherBufData.byteOffset |
| 4801 | ); |
| 4802 | // 0|0 3 2 1|0 3 2... |
| 4803 | |
| 4804 | buf.slice(1, buf.length - 3).swap32(); |
| 4805 | deepStrictEqual(buf.slice(0, otherBuf.length), otherBuf); |
| 4806 | } |
| 4807 | |
| 4808 | { |
| 4809 | const bufData = new Uint8Array(256 * 8); |
| 4810 | const otherBufData = new Uint8Array(256 * 8 - 8); |
| 4811 | for (let i = 0; i < bufData.length; i++) { |
| 4812 | bufData[i] = i % 8; |
| 4813 | } |
| 4814 | for (let i = 1; i < otherBufData.length; i++) { |
| 4815 | otherBufData[otherBufData.length - i] = (i + 1) % 8; |
| 4816 | } |
| 4817 | const buf = Buffer.from(bufData.buffer, bufData.byteOffset); |
| 4818 | // 0|1 2 3 4 5 6 7 0|1 2 3 4... |
| 4819 | const otherBuf = Buffer.from( |
| 4820 | otherBufData.buffer, |
| 4821 | otherBufData.byteOffset |
| 4822 | ); |
| 4823 | // 0|0 7 6 5 4 3 2 1|0 7 6 5... |
| 4824 | |
| 4825 | buf.slice(1, buf.length - 7).swap64(); |
| 4826 | deepStrictEqual(buf.slice(0, otherBuf.length), otherBuf); |
| 4827 | } |
| 4828 | }, |
| 4829 | }; |
| 4830 | |
| 4831 | export const json = { |
| 4832 | test(ctrl, env, ctx) { |
| 4833 | { |
| 4834 | strictEqual( |
| 4835 | JSON.stringify(Buffer.alloc(0)), |
| 4836 | '{"type":"Buffer","data":[]}' |
| 4837 | ); |
| 4838 | strictEqual( |
| 4839 | JSON.stringify(Buffer.from([1, 2, 3, 4])), |
| 4840 | '{"type":"Buffer","data":[1,2,3,4]}' |
| 4841 | ); |
| 4842 | } |
| 4843 | |
| 4844 | // issue GH-7849 |
| 4845 | { |
| 4846 | const buf = Buffer.from('test'); |
| 4847 | const json = JSON.stringify(buf); |
| 4848 | const obj = JSON.parse(json); |
| 4849 | const copy = Buffer.from(obj); |
| 4850 | |
| 4851 | deepStrictEqual(buf, copy); |
| 4852 | } |
| 4853 | |
| 4854 | // GH-5110 |
| 4855 | { |
| 4856 | const buffer = Buffer.from('test'); |
| 4857 | const string = JSON.stringify(buffer); |
| 4858 | |
| 4859 | strictEqual(string, '{"type":"Buffer","data":[116,101,115,116]}'); |
| 4860 | |
| 4861 | function receiver(key, value) { |
| 4862 | return value && value.type === 'Buffer' |
| 4863 | ? Buffer.from(value.data) |
| 4864 | : value; |
| 4865 | } |
| 4866 | |
| 4867 | deepStrictEqual(buffer, JSON.parse(string, receiver)); |
| 4868 | } |
| 4869 | }, |
| 4870 | }; |
| 4871 | |
| 4872 | export const writeUint8 = { |
| 4873 | test(ctrl, env, ctx) { |
| 4874 | { |
| 4875 | // OOB |
| 4876 | const data = Buffer.alloc(8); |
| 4877 | ['UInt8', 'UInt16BE', 'UInt16LE', 'UInt32BE', 'UInt32LE'].forEach( |
| 4878 | (fn) => { |
| 4879 | // Verify that default offset works fine. |
| 4880 | data[`write${fn}`](23, undefined); |
| 4881 | data[`write${fn}`](23); |
| 4882 | |
| 4883 | ['', '0', null, {}, [], () => {}, true, false].forEach((o) => { |
| 4884 | throws(() => data[`write${fn}`](23, o), { name: 'TypeError' }); |
| 4885 | }); |
| 4886 | |
| 4887 | [NaN, Infinity, -1, 1.01].forEach((o) => { |
| 4888 | throws(() => data[`write${fn}`](23, o), { name: 'RangeError' }); |
| 4889 | }); |
| 4890 | } |
| 4891 | ); |
| 4892 | } |
| 4893 | |
| 4894 | { |
| 4895 | // Test 8 bit |
| 4896 | const data = Buffer.alloc(4); |
| 4897 | |
| 4898 | data.writeUInt8(23, 0); |
| 4899 | data.writeUInt8(23, 1); |
| 4900 | data.writeUInt8(23, 2); |
| 4901 | data.writeUInt8(23, 3); |
| 4902 | ok(data.equals(new Uint8Array([23, 23, 23, 23]))); |
| 4903 | |
| 4904 | data.writeUInt8(23, 0); |
| 4905 | data.writeUInt8(23, 1); |
| 4906 | data.writeUInt8(23, 2); |
| 4907 | data.writeUInt8(23, 3); |
| 4908 | ok(data.equals(new Uint8Array([23, 23, 23, 23]))); |
| 4909 | |
| 4910 | data.writeUInt8(255, 0); |
| 4911 | strictEqual(data[0], 255); |
| 4912 | |
| 4913 | data.writeUInt8(255, 0); |
| 4914 | strictEqual(data[0], 255); |
| 4915 | } |
| 4916 | |
| 4917 | // Test 16 bit |
| 4918 | { |
| 4919 | let value = 0x2343; |
| 4920 | const data = Buffer.alloc(4); |
| 4921 | |
| 4922 | data.writeUInt16BE(value, 0); |
| 4923 | ok(data.equals(new Uint8Array([0x23, 0x43, 0, 0]))); |
| 4924 | |
| 4925 | data.writeUInt16BE(value, 1); |
| 4926 | ok(data.equals(new Uint8Array([0x23, 0x23, 0x43, 0]))); |
| 4927 | |
| 4928 | data.writeUInt16BE(value, 2); |
| 4929 | ok(data.equals(new Uint8Array([0x23, 0x23, 0x23, 0x43]))); |
| 4930 | |
| 4931 | data.writeUInt16LE(value, 0); |
| 4932 | ok(data.equals(new Uint8Array([0x43, 0x23, 0x23, 0x43]))); |
| 4933 | |
| 4934 | data.writeUInt16LE(value, 1); |
| 4935 | ok(data.equals(new Uint8Array([0x43, 0x43, 0x23, 0x43]))); |
| 4936 | |
| 4937 | data.writeUInt16LE(value, 2); |
| 4938 | ok(data.equals(new Uint8Array([0x43, 0x43, 0x43, 0x23]))); |
| 4939 | |
| 4940 | value = 0xff80; |
| 4941 | data.writeUInt16LE(value, 0); |
| 4942 | ok(data.equals(new Uint8Array([0x80, 0xff, 0x43, 0x23]))); |
| 4943 | |
| 4944 | data.writeUInt16BE(value, 0); |
| 4945 | ok(data.equals(new Uint8Array([0xff, 0x80, 0x43, 0x23]))); |
| 4946 | |
| 4947 | value = 0xfffff; |
| 4948 | ['writeUInt16BE', 'writeUInt16LE'].forEach((fn) => { |
| 4949 | throws(() => data[fn](value, 0), { |
| 4950 | name: 'RangeError', |
| 4951 | }); |
| 4952 | }); |
| 4953 | } |
| 4954 | |
| 4955 | // Test 32 bit |
| 4956 | { |
| 4957 | const data = Buffer.alloc(6); |
| 4958 | const value = 0xe7f90a6d; |
| 4959 | |
| 4960 | data.writeUInt32BE(value, 0); |
| 4961 | ok(data.equals(new Uint8Array([0xe7, 0xf9, 0x0a, 0x6d, 0, 0]))); |
| 4962 | |
| 4963 | data.writeUInt32BE(value, 1); |
| 4964 | ok(data.equals(new Uint8Array([0xe7, 0xe7, 0xf9, 0x0a, 0x6d, 0]))); |
| 4965 | |
| 4966 | data.writeUInt32BE(value, 2); |
| 4967 | ok(data.equals(new Uint8Array([0xe7, 0xe7, 0xe7, 0xf9, 0x0a, 0x6d]))); |
| 4968 | |
| 4969 | data.writeUInt32LE(value, 0); |
| 4970 | ok(data.equals(new Uint8Array([0x6d, 0x0a, 0xf9, 0xe7, 0x0a, 0x6d]))); |
| 4971 | |
| 4972 | data.writeUInt32LE(value, 1); |
| 4973 | ok(data.equals(new Uint8Array([0x6d, 0x6d, 0x0a, 0xf9, 0xe7, 0x6d]))); |
| 4974 | |
| 4975 | data.writeUInt32LE(value, 2); |
| 4976 | ok(data.equals(new Uint8Array([0x6d, 0x6d, 0x6d, 0x0a, 0xf9, 0xe7]))); |
| 4977 | } |
| 4978 | |
| 4979 | // Test 48 bit |
| 4980 | { |
| 4981 | const value = 0x1234567890ab; |
| 4982 | const data = Buffer.allocUnsafe(6); |
| 4983 | data.writeUIntBE(value, 0, 6); |
| 4984 | ok(data.equals(new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]))); |
| 4985 | |
| 4986 | data.writeUIntLE(value, 0, 6); |
| 4987 | ok(data.equals(new Uint8Array([0xab, 0x90, 0x78, 0x56, 0x34, 0x12]))); |
| 4988 | } |
| 4989 | |
| 4990 | // Test UInt |
| 4991 | { |
| 4992 | const data = Buffer.alloc(8); |
| 4993 | let val = 0x100; |
| 4994 | |
| 4995 | // Check byteLength. |
| 4996 | ['writeUIntBE', 'writeUIntLE'].forEach((fn) => { |
| 4997 | ['', '0', null, {}, [], () => {}, true, false, undefined].forEach( |
| 4998 | (bl) => { |
| 4999 | throws(() => data[fn](23, 0, bl), { name: 'RangeError' }); |
| 5000 | } |
| 5001 | ); |
| 5002 | |
| 5003 | [Infinity, -1].forEach((byteLength) => { |
| 5004 | throws(() => data[fn](23, 0, byteLength), { |
| 5005 | name: 'RangeError', |
| 5006 | }); |
| 5007 | }); |
| 5008 | |
| 5009 | [NaN, 1.01].forEach((byteLength) => { |
| 5010 | throws(() => data[fn](42, 0, byteLength), { |
| 5011 | name: 'RangeError', |
| 5012 | }); |
| 5013 | }); |
| 5014 | }); |
| 5015 | |
| 5016 | // Test 1 to 6 bytes. |
| 5017 | for (let i = 1; i <= 6; i++) { |
| 5018 | const _range = i < 5 ? `= ${val - 1}` : ` 2 ** ${i * 8}`; |
| 5019 | const _received = |
| 5020 | i > 4 ? String(val).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1_') : val; |
| 5021 | ['writeUIntBE', 'writeUIntLE'].forEach((fn) => { |
| 5022 | throws( |
| 5023 | () => { |
| 5024 | data[fn](val, 0, i); |
| 5025 | }, |
| 5026 | { |
| 5027 | name: 'RangeError', |
| 5028 | } |
| 5029 | ); |
| 5030 | |
| 5031 | ['', '0', null, {}, [], () => {}, true, false].forEach((o) => { |
| 5032 | throws(() => data[fn](23, o, i), { |
| 5033 | name: 'TypeError', |
| 5034 | }); |
| 5035 | }); |
| 5036 | |
| 5037 | [Infinity, -1, -4294967295].forEach((offset) => { |
| 5038 | throws(() => data[fn](val - 1, offset, i), { |
| 5039 | name: 'RangeError', |
| 5040 | }); |
| 5041 | }); |
| 5042 | |
| 5043 | [NaN, 1.01].forEach((offset) => { |
| 5044 | throws(() => data[fn](val - 1, offset, i), { |
| 5045 | name: 'RangeError', |
| 5046 | }); |
| 5047 | }); |
| 5048 | }); |
| 5049 | |
| 5050 | val *= 0x100; |
| 5051 | } |
| 5052 | } |
| 5053 | |
| 5054 | for (const fn of [ |
| 5055 | 'UInt8', |
| 5056 | 'UInt16LE', |
| 5057 | 'UInt16BE', |
| 5058 | 'UInt32LE', |
| 5059 | 'UInt32BE', |
| 5060 | 'UIntLE', |
| 5061 | 'UIntBE', |
| 5062 | 'BigUInt64LE', |
| 5063 | 'BigUInt64BE', |
| 5064 | ]) { |
| 5065 | const p = Buffer.prototype; |
| 5066 | const lowerFn = fn.replace(/UInt/, 'Uint'); |
| 5067 | strictEqual(p[`write${fn}`], p[`write${lowerFn}`]); |
| 5068 | strictEqual(p[`read${fn}`], p[`read${lowerFn}`]); |
| 5069 | } |
| 5070 | }, |
| 5071 | }; |
| 5072 | |
| 5073 | export const writeInt = { |
| 5074 | test(ctrl, env, ctx) { |
| 5075 | const errorOutOfBounds = { |
| 5076 | name: 'RangeError', |
| 5077 | }; |
| 5078 | |
| 5079 | // Test 8 bit |
| 5080 | { |
| 5081 | const buffer = Buffer.alloc(2); |
| 5082 | |
| 5083 | buffer.writeInt8(0x23, 0); |
| 5084 | buffer.writeInt8(-5, 1); |
| 5085 | ok(buffer.equals(new Uint8Array([0x23, 0xfb]))); |
| 5086 | |
| 5087 | /* Make sure we handle min/max correctly */ |
| 5088 | buffer.writeInt8(0x7f, 0); |
| 5089 | buffer.writeInt8(-0x80, 1); |
| 5090 | ok(buffer.equals(new Uint8Array([0x7f, 0x80]))); |
| 5091 | |
| 5092 | throws(() => { |
| 5093 | buffer.writeInt8(0x7f + 1, 0); |
| 5094 | }, errorOutOfBounds); |
| 5095 | throws(() => { |
| 5096 | buffer.writeInt8(-0x80 - 1, 0); |
| 5097 | }, errorOutOfBounds); |
| 5098 | |
| 5099 | // Verify that default offset works fine. |
| 5100 | buffer.writeInt8(23, undefined); |
| 5101 | buffer.writeInt8(23); |
| 5102 | |
| 5103 | ['', '0', null, {}, [], () => {}, true, false].forEach((off) => { |
| 5104 | throws(() => buffer.writeInt8(23, off), { name: 'TypeError' }); |
| 5105 | }); |
| 5106 | |
| 5107 | [NaN, Infinity, -1, 1.01].forEach((off) => { |
| 5108 | throws(() => buffer.writeInt8(23, off), { name: 'RangeError' }); |
| 5109 | }); |
| 5110 | } |
| 5111 | |
| 5112 | // Test 16 bit |
| 5113 | { |
| 5114 | const buffer = Buffer.alloc(4); |
| 5115 | |
| 5116 | buffer.writeInt16BE(0x0023, 0); |
| 5117 | buffer.writeInt16LE(0x0023, 2); |
| 5118 | ok(buffer.equals(new Uint8Array([0x00, 0x23, 0x23, 0x00]))); |
| 5119 | |
| 5120 | buffer.writeInt16BE(-5, 0); |
| 5121 | buffer.writeInt16LE(-5, 2); |
| 5122 | ok(buffer.equals(new Uint8Array([0xff, 0xfb, 0xfb, 0xff]))); |
| 5123 | |
| 5124 | buffer.writeInt16BE(-1679, 0); |
| 5125 | buffer.writeInt16LE(-1679, 2); |
| 5126 | ok(buffer.equals(new Uint8Array([0xf9, 0x71, 0x71, 0xf9]))); |
| 5127 | |
| 5128 | /* Make sure we handle min/max correctly */ |
| 5129 | buffer.writeInt16BE(0x7fff, 0); |
| 5130 | buffer.writeInt16BE(-0x8000, 2); |
| 5131 | ok(buffer.equals(new Uint8Array([0x7f, 0xff, 0x80, 0x00]))); |
| 5132 | |
| 5133 | buffer.writeInt16LE(0x7fff, 0); |
| 5134 | buffer.writeInt16LE(-0x8000, 2); |
| 5135 | ok(buffer.equals(new Uint8Array([0xff, 0x7f, 0x00, 0x80]))); |
| 5136 | |
| 5137 | ['writeInt16BE', 'writeInt16LE'].forEach((fn) => { |
| 5138 | // Verify that default offset works fine. |
| 5139 | buffer[fn](23, undefined); |
| 5140 | buffer[fn](23); |
| 5141 | |
| 5142 | throws(() => { |
| 5143 | buffer[fn](0x7fff + 1, 0); |
| 5144 | }, errorOutOfBounds); |
| 5145 | throws(() => { |
| 5146 | buffer[fn](-0x8000 - 1, 0); |
| 5147 | }, errorOutOfBounds); |
| 5148 | |
| 5149 | ['', '0', null, {}, [], () => {}, true, false].forEach((off) => { |
| 5150 | throws(() => buffer[fn](23, off), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 5151 | }); |
| 5152 | |
| 5153 | [NaN, Infinity, -1, 1.01].forEach((off) => { |
| 5154 | throws(() => buffer[fn](23, off), { code: 'ERR_OUT_OF_RANGE' }); |
| 5155 | }); |
| 5156 | }); |
| 5157 | } |
| 5158 | |
| 5159 | // Test 32 bit |
| 5160 | { |
| 5161 | const buffer = Buffer.alloc(8); |
| 5162 | |
| 5163 | buffer.writeInt32BE(0x23, 0); |
| 5164 | buffer.writeInt32LE(0x23, 4); |
| 5165 | ok( |
| 5166 | buffer.equals( |
| 5167 | new Uint8Array([0x00, 0x00, 0x00, 0x23, 0x23, 0x00, 0x00, 0x00]) |
| 5168 | ) |
| 5169 | ); |
| 5170 | |
| 5171 | buffer.writeInt32BE(-5, 0); |
| 5172 | buffer.writeInt32LE(-5, 4); |
| 5173 | ok( |
| 5174 | buffer.equals( |
| 5175 | new Uint8Array([0xff, 0xff, 0xff, 0xfb, 0xfb, 0xff, 0xff, 0xff]) |
| 5176 | ) |
| 5177 | ); |
| 5178 | |
| 5179 | buffer.writeInt32BE(-805306713, 0); |
| 5180 | buffer.writeInt32LE(-805306713, 4); |
| 5181 | ok( |
| 5182 | buffer.equals( |
| 5183 | new Uint8Array([0xcf, 0xff, 0xfe, 0xa7, 0xa7, 0xfe, 0xff, 0xcf]) |
| 5184 | ) |
| 5185 | ); |
| 5186 | |
| 5187 | /* Make sure we handle min/max correctly */ |
| 5188 | buffer.writeInt32BE(0x7fffffff, 0); |
| 5189 | buffer.writeInt32BE(-0x80000000, 4); |
| 5190 | ok( |
| 5191 | buffer.equals( |
| 5192 | new Uint8Array([0x7f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00]) |
| 5193 | ) |
| 5194 | ); |
| 5195 | |
| 5196 | buffer.writeInt32LE(0x7fffffff, 0); |
| 5197 | buffer.writeInt32LE(-0x80000000, 4); |
| 5198 | ok( |
| 5199 | buffer.equals( |
| 5200 | new Uint8Array([0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x80]) |
| 5201 | ) |
| 5202 | ); |
| 5203 | |
| 5204 | ['writeInt32BE', 'writeInt32LE'].forEach((fn) => { |
| 5205 | // Verify that default offset works fine. |
| 5206 | buffer[fn](23, undefined); |
| 5207 | buffer[fn](23); |
| 5208 | |
| 5209 | throws(() => { |
| 5210 | buffer[fn](0x7fffffff + 1, 0); |
| 5211 | }, errorOutOfBounds); |
| 5212 | throws(() => { |
| 5213 | buffer[fn](-0x80000000 - 1, 0); |
| 5214 | }, errorOutOfBounds); |
| 5215 | |
| 5216 | ['', '0', null, {}, [], () => {}, true, false].forEach((off) => { |
| 5217 | throws(() => buffer[fn](23, off), { code: 'ERR_INVALID_ARG_TYPE' }); |
| 5218 | }); |
| 5219 | |
| 5220 | [NaN, Infinity, -1, 1.01].forEach((off) => { |
| 5221 | throws(() => buffer[fn](23, off), { code: 'ERR_OUT_OF_RANGE' }); |
| 5222 | }); |
| 5223 | }); |
| 5224 | } |
| 5225 | |
| 5226 | // Test 48 bit |
| 5227 | { |
| 5228 | const value = 0x1234567890ab; |
| 5229 | const buffer = Buffer.allocUnsafe(6); |
| 5230 | buffer.writeIntBE(value, 0, 6); |
| 5231 | ok(buffer.equals(new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]))); |
| 5232 | |
| 5233 | buffer.writeIntLE(value, 0, 6); |
| 5234 | ok(buffer.equals(new Uint8Array([0xab, 0x90, 0x78, 0x56, 0x34, 0x12]))); |
| 5235 | } |
| 5236 | |
| 5237 | // Test Int |
| 5238 | { |
| 5239 | const data = Buffer.alloc(8); |
| 5240 | |
| 5241 | // Check byteLength. |
| 5242 | ['writeIntBE', 'writeIntLE'].forEach((fn) => { |
| 5243 | ['', '0', null, {}, [], () => {}, true, false, undefined].forEach( |
| 5244 | (bl) => { |
| 5245 | throws(() => data[fn](23, 0, bl), { name: 'RangeError' }); |
| 5246 | } |
| 5247 | ); |
| 5248 | |
| 5249 | [Infinity, -1].forEach((byteLength) => { |
| 5250 | throws(() => data[fn](23, 0, byteLength), { |
| 5251 | name: 'RangeError', |
| 5252 | }); |
| 5253 | }); |
| 5254 | |
| 5255 | [NaN, 1.01].forEach((byteLength) => { |
| 5256 | throws(() => data[fn](42, 0, byteLength), { |
| 5257 | name: 'RangeError', |
| 5258 | }); |
| 5259 | }); |
| 5260 | }); |
| 5261 | |
| 5262 | // Test 1 to 6 bytes. |
| 5263 | for (let i = 1; i <= 6; i++) { |
| 5264 | ['writeIntBE', 'writeIntLE'].forEach((fn) => { |
| 5265 | const min = -(2 ** (i * 8 - 1)); |
| 5266 | const max = 2 ** (i * 8 - 1) - 1; |
| 5267 | let _range = `>= ${min} and <= ${max}`; |
| 5268 | if (i > 4) { |
| 5269 | _range = `>= -(2 ** ${i * 8 - 1}) and < 2 ** ${i * 8 - 1}`; |
| 5270 | } |
| 5271 | [min - 1, max + 1].forEach((val) => { |
| 5272 | const _received = |
| 5273 | i > 4 |
| 5274 | ? String(val).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1_') |
| 5275 | : val; |
| 5276 | throws( |
| 5277 | () => { |
| 5278 | data[fn](val, 0, i); |
| 5279 | }, |
| 5280 | { |
| 5281 | name: 'RangeError', |
| 5282 | } |
| 5283 | ); |
| 5284 | }); |
| 5285 | |
| 5286 | ['', '0', null, {}, [], () => {}, true, false, undefined].forEach( |
| 5287 | (o) => { |
| 5288 | throws(() => data[fn](min, o, i), { |
| 5289 | name: 'TypeError', |
| 5290 | }); |
| 5291 | } |
| 5292 | ); |
| 5293 | |
| 5294 | [Infinity, -1, -4294967295].forEach((offset) => { |
| 5295 | throws(() => data[fn](min, offset, i), { |
| 5296 | name: 'RangeError', |
| 5297 | }); |
| 5298 | }); |
| 5299 | |
| 5300 | [NaN, 1.01].forEach((offset) => { |
| 5301 | throws(() => data[fn](max, offset, i), { |
| 5302 | name: 'RangeError', |
| 5303 | }); |
| 5304 | }); |
| 5305 | }); |
| 5306 | } |
| 5307 | } |
| 5308 | }, |
| 5309 | }; |
| 5310 | |
| 5311 | export const writeFloat = { |
| 5312 | test(ctrl, env, ctx) { |
| 5313 | const buffer = Buffer.allocUnsafe(8); |
| 5314 | |
| 5315 | buffer.writeFloatBE(1, 0); |
| 5316 | buffer.writeFloatLE(1, 4); |
| 5317 | ok( |
| 5318 | buffer.equals( |
| 5319 | new Uint8Array([0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f]) |
| 5320 | ) |
| 5321 | ); |
| 5322 | |
| 5323 | buffer.writeFloatBE(1 / 3, 0); |
| 5324 | buffer.writeFloatLE(1 / 3, 4); |
| 5325 | ok( |
| 5326 | buffer.equals( |
| 5327 | new Uint8Array([0x3e, 0xaa, 0xaa, 0xab, 0xab, 0xaa, 0xaa, 0x3e]) |
| 5328 | ) |
| 5329 | ); |
| 5330 | |
| 5331 | buffer.writeFloatBE(3.4028234663852886e38, 0); |
| 5332 | buffer.writeFloatLE(3.4028234663852886e38, 4); |
| 5333 | ok( |
| 5334 | buffer.equals( |
| 5335 | new Uint8Array([0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f]) |
| 5336 | ) |
| 5337 | ); |
| 5338 | |
| 5339 | buffer.writeFloatLE(1.1754943508222875e-38, 0); |
| 5340 | buffer.writeFloatBE(1.1754943508222875e-38, 4); |
| 5341 | ok( |
| 5342 | buffer.equals( |
| 5343 | new Uint8Array([0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00]) |
| 5344 | ) |
| 5345 | ); |
| 5346 | |
| 5347 | buffer.writeFloatBE(0 * -1, 0); |
| 5348 | buffer.writeFloatLE(0 * -1, 4); |
| 5349 | ok( |
| 5350 | buffer.equals( |
| 5351 | new Uint8Array([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]) |
| 5352 | ) |
| 5353 | ); |
| 5354 | |
| 5355 | buffer.writeFloatBE(Infinity, 0); |
| 5356 | buffer.writeFloatLE(Infinity, 4); |
| 5357 | ok( |
| 5358 | buffer.equals( |
| 5359 | new Uint8Array([0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f]) |
| 5360 | ) |
| 5361 | ); |
| 5362 | |
| 5363 | strictEqual(buffer.readFloatBE(0), Infinity); |
| 5364 | strictEqual(buffer.readFloatLE(4), Infinity); |
| 5365 | |
| 5366 | buffer.writeFloatBE(-Infinity, 0); |
| 5367 | buffer.writeFloatLE(-Infinity, 4); |
| 5368 | ok( |
| 5369 | buffer.equals( |
| 5370 | new Uint8Array([0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff]) |
| 5371 | ) |
| 5372 | ); |
| 5373 | |
| 5374 | strictEqual(buffer.readFloatBE(0), -Infinity); |
| 5375 | strictEqual(buffer.readFloatLE(4), -Infinity); |
| 5376 | |
| 5377 | buffer.writeFloatBE(NaN, 0); |
| 5378 | buffer.writeFloatLE(NaN, 4); |
| 5379 | |
| 5380 | // JS only knows a single NaN but there exist two platform specific |
| 5381 | // implementations. Therefore, allow both quiet and signalling NaNs. |
| 5382 | if (buffer[1] === 0xbf) { |
| 5383 | ok( |
| 5384 | buffer.equals( |
| 5385 | new Uint8Array([0x7f, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x7f]) |
| 5386 | ) |
| 5387 | ); |
| 5388 | } else { |
| 5389 | ok( |
| 5390 | buffer.equals( |
| 5391 | new Uint8Array([0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f]) |
| 5392 | ) |
| 5393 | ); |
| 5394 | } |
| 5395 | |
| 5396 | ok(Number.isNaN(buffer.readFloatBE(0))); |
| 5397 | ok(Number.isNaN(buffer.readFloatLE(4))); |
| 5398 | |
| 5399 | // OOB in writeFloat{LE,BE} should throw. |
| 5400 | { |
| 5401 | const small = Buffer.allocUnsafe(1); |
| 5402 | |
| 5403 | ['writeFloatLE', 'writeFloatBE'].forEach((fn) => { |
| 5404 | // Verify that default offset works fine. |
| 5405 | buffer[fn](23, undefined); |
| 5406 | buffer[fn](23); |
| 5407 | |
| 5408 | throws(() => small[fn](11.11, 0), { |
| 5409 | name: 'RangeError', |
| 5410 | }); |
| 5411 | |
| 5412 | ['', '0', null, {}, [], () => {}, true, false].forEach((off) => { |
| 5413 | throws(() => small[fn](23, off), { name: 'TypeError' }); |
| 5414 | }); |
| 5415 | |
| 5416 | [Infinity, -1, 5].forEach((offset) => { |
| 5417 | throws(() => buffer[fn](23, offset), { |
| 5418 | name: 'RangeError', |
| 5419 | }); |
| 5420 | }); |
| 5421 | |
| 5422 | [NaN, 1.01].forEach((offset) => { |
| 5423 | throws(() => buffer[fn](42, offset), { |
| 5424 | name: 'RangeError', |
| 5425 | }); |
| 5426 | }); |
| 5427 | }); |
| 5428 | } |
| 5429 | }, |
| 5430 | }; |
| 5431 | |
| 5432 | export const writeDouble = { |
| 5433 | test(ctrl, env, ctx) { |
| 5434 | const buffer = Buffer.allocUnsafe(16); |
| 5435 | |
| 5436 | buffer.writeDoubleBE(2.225073858507201e-308, 0); |
| 5437 | buffer.writeDoubleLE(2.225073858507201e-308, 8); |
| 5438 | ok( |
| 5439 | buffer.equals( |
| 5440 | new Uint8Array([ |
| 5441 | 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 5442 | 0xff, 0xff, 0xff, 0x0f, 0x00, |
| 5443 | ]) |
| 5444 | ) |
| 5445 | ); |
| 5446 | |
| 5447 | buffer.writeDoubleBE(1.0000000000000004, 0); |
| 5448 | buffer.writeDoubleLE(1.0000000000000004, 8); |
| 5449 | ok( |
| 5450 | buffer.equals( |
| 5451 | new Uint8Array([ |
| 5452 | 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, |
| 5453 | 0x00, 0x00, 0x00, 0xf0, 0x3f, |
| 5454 | ]) |
| 5455 | ) |
| 5456 | ); |
| 5457 | |
| 5458 | buffer.writeDoubleBE(-2, 0); |
| 5459 | buffer.writeDoubleLE(-2, 8); |
| 5460 | ok( |
| 5461 | buffer.equals( |
| 5462 | new Uint8Array([ |
| 5463 | 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 5464 | 0x00, 0x00, 0x00, 0x00, 0xc0, |
| 5465 | ]) |
| 5466 | ) |
| 5467 | ); |
| 5468 | |
| 5469 | buffer.writeDoubleBE(1.7976931348623157e308, 0); |
| 5470 | buffer.writeDoubleLE(1.7976931348623157e308, 8); |
| 5471 | ok( |
| 5472 | buffer.equals( |
| 5473 | new Uint8Array([ |
| 5474 | 0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 5475 | 0xff, 0xff, 0xff, 0xef, 0x7f, |
| 5476 | ]) |
| 5477 | ) |
| 5478 | ); |
| 5479 | |
| 5480 | buffer.writeDoubleBE(0 * -1, 0); |
| 5481 | buffer.writeDoubleLE(0 * -1, 8); |
| 5482 | ok( |
| 5483 | buffer.equals( |
| 5484 | new Uint8Array([ |
| 5485 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 5486 | 0x00, 0x00, 0x00, 0x00, 0x80, |
| 5487 | ]) |
| 5488 | ) |
| 5489 | ); |
| 5490 | |
| 5491 | buffer.writeDoubleBE(Infinity, 0); |
| 5492 | buffer.writeDoubleLE(Infinity, 8); |
| 5493 | |
| 5494 | ok( |
| 5495 | buffer.equals( |
| 5496 | new Uint8Array([ |
| 5497 | 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 5498 | 0x00, 0x00, 0x00, 0xf0, 0x7f, |
| 5499 | ]) |
| 5500 | ) |
| 5501 | ); |
| 5502 | |
| 5503 | strictEqual(buffer.readDoubleBE(0), Infinity); |
| 5504 | strictEqual(buffer.readDoubleLE(8), Infinity); |
| 5505 | |
| 5506 | buffer.writeDoubleBE(-Infinity, 0); |
| 5507 | buffer.writeDoubleLE(-Infinity, 8); |
| 5508 | |
| 5509 | ok( |
| 5510 | buffer.equals( |
| 5511 | new Uint8Array([ |
| 5512 | 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 5513 | 0x00, 0x00, 0x00, 0xf0, 0xff, |
| 5514 | ]) |
| 5515 | ) |
| 5516 | ); |
| 5517 | |
| 5518 | strictEqual(buffer.readDoubleBE(0), -Infinity); |
| 5519 | strictEqual(buffer.readDoubleLE(8), -Infinity); |
| 5520 | |
| 5521 | buffer.writeDoubleBE(NaN, 0); |
| 5522 | buffer.writeDoubleLE(NaN, 8); |
| 5523 | |
| 5524 | // JS only knows a single NaN but there exist two platform specific |
| 5525 | // implementations. Therefore, allow both quiet and signalling NaNs. |
| 5526 | if (buffer[1] === 0xf7) { |
| 5527 | ok( |
| 5528 | buffer.equals( |
| 5529 | new Uint8Array([ |
| 5530 | 0x7f, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 5531 | 0xff, 0xff, 0xff, 0xf7, 0x7f, |
| 5532 | ]) |
| 5533 | ) |
| 5534 | ); |
| 5535 | } else { |
| 5536 | ok( |
| 5537 | buffer.equals( |
| 5538 | new Uint8Array([ |
| 5539 | 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 5540 | 0x00, 0x00, 0x00, 0xf8, 0x7f, |
| 5541 | ]) |
| 5542 | ) |
| 5543 | ); |
| 5544 | } |
| 5545 | |
| 5546 | ok(Number.isNaN(buffer.readDoubleBE(0))); |
| 5547 | ok(Number.isNaN(buffer.readDoubleLE(8))); |
| 5548 | |
| 5549 | // OOB in writeDouble{LE,BE} should throw. |
| 5550 | { |
| 5551 | const small = Buffer.allocUnsafe(1); |
| 5552 | |
| 5553 | ['writeDoubleLE', 'writeDoubleBE'].forEach((fn) => { |
| 5554 | // Verify that default offset works fine. |
| 5555 | buffer[fn](23, undefined); |
| 5556 | buffer[fn](23); |
| 5557 | |
| 5558 | throws(() => small[fn](11.11, 0), { |
| 5559 | code: 'ERR_BUFFER_OUT_OF_BOUNDS', |
| 5560 | name: 'RangeError', |
| 5561 | message: 'Attempt to access memory outside buffer bounds', |
| 5562 | }); |
| 5563 | |
| 5564 | ['', '0', null, {}, [], () => {}, true, false].forEach((off) => { |
| 5565 | throws(() => small[fn](23, off), { name: 'TypeError' }); |
| 5566 | }); |
| 5567 | |
| 5568 | [Infinity, -1, 9].forEach((offset) => { |
| 5569 | throws(() => buffer[fn](23, offset), { |
| 5570 | name: 'RangeError', |
| 5571 | }); |
| 5572 | }); |
| 5573 | |
| 5574 | [NaN, 1.01].forEach((offset) => { |
| 5575 | throws(() => buffer[fn](42, offset), { |
| 5576 | name: 'RangeError', |
| 5577 | }); |
| 5578 | }); |
| 5579 | }); |
| 5580 | } |
| 5581 | }, |
| 5582 | }; |
| 5583 | |
| 5584 | export const write = { |
| 5585 | test(ctrl, env, ctx) { |
| 5586 | [-1, 10].forEach((offset) => { |
| 5587 | throws(() => Buffer.alloc(9).write('foo', offset), { |
| 5588 | name: 'RangeError', |
| 5589 | }); |
| 5590 | }); |
| 5591 | |
| 5592 | const resultMap = new Map([ |
| 5593 | ['utf8', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])], |
| 5594 | ['ucs2', Buffer.from([102, 0, 111, 0, 111, 0, 0, 0, 0])], |
| 5595 | ['ascii', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])], |
| 5596 | ['latin1', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])], |
| 5597 | ['binary', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])], |
| 5598 | ['utf16le', Buffer.from([102, 0, 111, 0, 111, 0, 0, 0, 0])], |
| 5599 | ['base64', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])], |
| 5600 | ['base64url', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])], |
| 5601 | ['hex', Buffer.from([102, 111, 111, 0, 0, 0, 0, 0, 0])], |
| 5602 | ]); |
| 5603 | |
| 5604 | // utf8, ucs2, ascii, latin1, utf16le |
| 5605 | const encodings = [ |
| 5606 | 'utf8', |
| 5607 | 'utf-8', |
| 5608 | 'ascii', |
| 5609 | 'latin1', |
| 5610 | 'binary', |
| 5611 | 'ucs2', |
| 5612 | 'ucs-2', |
| 5613 | 'utf16le', |
| 5614 | 'utf-16le', |
| 5615 | ]; |
| 5616 | |
| 5617 | encodings |
| 5618 | .reduce((es, e) => es.concat(e, e.toUpperCase()), []) |
| 5619 | .forEach((encoding) => { |
| 5620 | const buf = Buffer.alloc(9); |
| 5621 | const len = Buffer.byteLength('foo', encoding); |
| 5622 | strictEqual(buf.write('foo', 0, len, encoding), len); |
| 5623 | |
| 5624 | if (encoding.includes('-')) encoding = encoding.replace('-', ''); |
| 5625 | |
| 5626 | deepStrictEqual(buf, resultMap.get(encoding.toLowerCase())); |
| 5627 | }); |
| 5628 | |
| 5629 | // base64 |
| 5630 | ['base64', 'BASE64', 'base64url', 'BASE64URL'].forEach((encoding) => { |
| 5631 | const buf = Buffer.alloc(9); |
| 5632 | const len = Buffer.byteLength('Zm9v', encoding); |
| 5633 | |
| 5634 | strictEqual(buf.write('Zm9v', 0, len, encoding), len); |
| 5635 | deepStrictEqual(buf, resultMap.get(encoding.toLowerCase())); |
| 5636 | }); |
| 5637 | |
| 5638 | // hex |
| 5639 | ['hex', 'HEX'].forEach((encoding) => { |
| 5640 | const buf = Buffer.alloc(9); |
| 5641 | const len = Buffer.byteLength('666f6f', encoding); |
| 5642 | |
| 5643 | strictEqual(buf.write('666f6f', 0, len, encoding), len); |
| 5644 | deepStrictEqual(buf, resultMap.get(encoding.toLowerCase())); |
| 5645 | }); |
| 5646 | |
| 5647 | // Invalid encodings |
| 5648 | for (let i = 1; i < 10; i++) { |
| 5649 | const encoding = String(i).repeat(i); |
| 5650 | const error = { |
| 5651 | name: 'TypeError', |
| 5652 | }; |
| 5653 | |
| 5654 | ok(!Buffer.isEncoding(encoding)); |
| 5655 | throws(() => Buffer.alloc(9).write('foo', encoding), error); |
| 5656 | } |
| 5657 | |
| 5658 | // UCS-2 overflow CVE-2018-12115 |
| 5659 | for (let i = 1; i < 4; i++) { |
| 5660 | // Allocate two Buffers sequentially off the pool. Run more than once in case |
| 5661 | // we hit the end of the pool and don't get sequential allocations |
| 5662 | const x = Buffer.allocUnsafe(4).fill(0); |
| 5663 | const y = Buffer.allocUnsafe(4).fill(1); |
| 5664 | // Should not write anything, pos 3 doesn't have enough room for a 16-bit char |
| 5665 | strictEqual(x.write('ыыыыыы', 3, 'ucs2'), 0); |
| 5666 | // CVE-2018-12115 experienced via buffer overrun to next block in the pool |
| 5667 | strictEqual(Buffer.compare(y, Buffer.alloc(4, 1)), 0); |
| 5668 | } |
| 5669 | |
| 5670 | // Should not write any data when there is no space for 16-bit chars |
| 5671 | const z = Buffer.alloc(4, 0); |
| 5672 | strictEqual(z.write('\u0001', 3, 'ucs2'), 0); |
| 5673 | strictEqual(Buffer.compare(z, Buffer.alloc(4, 0)), 0); |
| 5674 | // Make sure longer strings are written up to the buffer end. |
| 5675 | strictEqual(z.write('abcd', 2), 2); |
| 5676 | deepStrictEqual([...z], [0, 0, 0x61, 0x62]); |
| 5677 | |
| 5678 | // Large overrun could corrupt the process |
| 5679 | strictEqual(Buffer.alloc(4).write('ыыыыыы'.repeat(100), 3, 'utf16le'), 0); |
| 5680 | |
| 5681 | { |
| 5682 | // .write() does not affect the byte after the written-to slice of the Buffer. |
| 5683 | // Refs: https://github.com/nodejs/node/issues/26422 |
| 5684 | const buf = Buffer.alloc(8); |
| 5685 | strictEqual(buf.write('ыы', 1, 'utf16le'), 4); |
| 5686 | deepStrictEqual([...buf], [0, 0x4b, 0x04, 0x4b, 0x04, 0, 0, 0]); |
| 5687 | } |
| 5688 | }, |
| 5689 | }; |
| 5690 | |
| 5691 | export const toString = { |
| 5692 | test(ctrl, env, ctx) { |
| 5693 | // utf8, ucs2, ascii, latin1, utf16le |
| 5694 | const encodings = [ |
| 5695 | 'utf8', |
| 5696 | 'utf-8', |
| 5697 | 'ucs2', |
| 5698 | 'ucs-2', |
| 5699 | 'ascii', |
| 5700 | 'latin1', |
| 5701 | 'binary', |
| 5702 | 'utf16le', |
| 5703 | 'utf-16le', |
| 5704 | ]; |
| 5705 | |
| 5706 | encodings |
| 5707 | .reduce((es, e) => es.concat(e, e.toUpperCase()), []) |
| 5708 | .forEach((encoding) => { |
| 5709 | strictEqual(Buffer.from('foo', encoding).toString(encoding), 'foo'); |
| 5710 | }); |
| 5711 | |
| 5712 | // base64 |
| 5713 | ['base64', 'BASE64'].forEach((encoding) => { |
| 5714 | strictEqual(Buffer.from('Zm9v', encoding).toString(encoding), 'Zm9v'); |
| 5715 | }); |
| 5716 | |
| 5717 | // hex |
| 5718 | ['hex', 'HEX'].forEach((encoding) => { |
| 5719 | strictEqual(Buffer.from('666f6f', encoding).toString(encoding), '666f6f'); |
| 5720 | }); |
| 5721 | |
| 5722 | // default utf-8 if undefined |
| 5723 | strictEqual(Buffer.from('utf-8').toString(), 'utf-8'); |
| 5724 | |
| 5725 | const invalidEncodings = Array.from({ length: 10 }, (_, i) => |
| 5726 | String(i + 1).repeat(i + 1) |
| 5727 | ); |
| 5728 | // Invalid encodings |
| 5729 | for (const encoding of [...invalidEncodings, null]) { |
| 5730 | const error = { |
| 5731 | code: 'ERR_UNKNOWN_ENCODING', |
| 5732 | name: 'TypeError', |
| 5733 | message: `Unknown encoding: ${encoding}`, |
| 5734 | }; |
| 5735 | ok(!Buffer.isEncoding(encoding)); |
| 5736 | throws(() => Buffer.from('foo').toString(encoding), error); |
| 5737 | } |
| 5738 | }, |
| 5739 | }; |
| 5740 | |
| 5741 | export const toStringRangeError = { |
| 5742 | test(ctrl, env, ctx) { |
| 5743 | const len = 1422561062959; |
| 5744 | const message = { |
| 5745 | code: 'ERR_OUT_OF_RANGE', |
| 5746 | name: 'RangeError', |
| 5747 | }; |
| 5748 | throws(() => Buffer(len).toString('utf8'), message); |
| 5749 | throws(() => SlowBuffer(len).toString('utf8'), message); |
| 5750 | throws(() => Buffer.alloc(len).toString('utf8'), message); |
| 5751 | throws(() => Buffer.allocUnsafe(len).toString('utf8'), message); |
| 5752 | throws(() => Buffer.allocUnsafeSlow(len).toString('utf8'), message); |
| 5753 | }, |
| 5754 | }; |
| 5755 | |
| 5756 | export const toStringRange = { |
| 5757 | test(ctrl, env, ctx) { |
| 5758 | const rangeBuffer = Buffer.from('abc'); |
| 5759 | // If start >= buffer's length, empty string will be returned |
| 5760 | strictEqual(rangeBuffer.toString('ascii', 3), ''); |
| 5761 | strictEqual(rangeBuffer.toString('ascii', +Infinity), ''); |
| 5762 | strictEqual(rangeBuffer.toString('ascii', 3.14, 3), ''); |
| 5763 | strictEqual(rangeBuffer.toString('ascii', 'Infinity', 3), ''); |
| 5764 | |
| 5765 | // If end <= 0, empty string will be returned |
| 5766 | strictEqual(rangeBuffer.toString('ascii', 1, 0), ''); |
| 5767 | strictEqual(rangeBuffer.toString('ascii', 1, -1.2), ''); |
| 5768 | strictEqual(rangeBuffer.toString('ascii', 1, -100), ''); |
| 5769 | strictEqual(rangeBuffer.toString('ascii', 1, -Infinity), ''); |
| 5770 | |
| 5771 | // If start < 0, start will be taken as zero |
| 5772 | strictEqual(rangeBuffer.toString('ascii', -1, 3), 'abc'); |
| 5773 | strictEqual(rangeBuffer.toString('ascii', -1.99, 3), 'abc'); |
| 5774 | strictEqual(rangeBuffer.toString('ascii', -Infinity, 3), 'abc'); |
| 5775 | strictEqual(rangeBuffer.toString('ascii', '-1', 3), 'abc'); |
| 5776 | strictEqual(rangeBuffer.toString('ascii', '-1.99', 3), 'abc'); |
| 5777 | strictEqual(rangeBuffer.toString('ascii', '-Infinity', 3), 'abc'); |
| 5778 | |
| 5779 | // If start is an invalid integer, start will be taken as zero |
| 5780 | strictEqual(rangeBuffer.toString('ascii', 'node.js', 3), 'abc'); |
| 5781 | strictEqual(rangeBuffer.toString('ascii', {}, 3), 'abc'); |
| 5782 | strictEqual(rangeBuffer.toString('ascii', [], 3), 'abc'); |
| 5783 | strictEqual(rangeBuffer.toString('ascii', NaN, 3), 'abc'); |
| 5784 | strictEqual(rangeBuffer.toString('ascii', null, 3), 'abc'); |
| 5785 | strictEqual(rangeBuffer.toString('ascii', undefined, 3), 'abc'); |
| 5786 | strictEqual(rangeBuffer.toString('ascii', false, 3), 'abc'); |
| 5787 | strictEqual(rangeBuffer.toString('ascii', '', 3), 'abc'); |
| 5788 | |
| 5789 | // But, if start is an integer when coerced, then it will be coerced and used. |
| 5790 | strictEqual(rangeBuffer.toString('ascii', '-1', 3), 'abc'); |
| 5791 | strictEqual(rangeBuffer.toString('ascii', '1', 3), 'bc'); |
| 5792 | strictEqual(rangeBuffer.toString('ascii', '-Infinity', 3), 'abc'); |
| 5793 | strictEqual(rangeBuffer.toString('ascii', '3', 3), ''); |
| 5794 | strictEqual(rangeBuffer.toString('ascii', Number(3), 3), ''); |
| 5795 | strictEqual(rangeBuffer.toString('ascii', '3.14', 3), ''); |
| 5796 | strictEqual(rangeBuffer.toString('ascii', '1.99', 3), 'bc'); |
| 5797 | strictEqual(rangeBuffer.toString('ascii', '-1.99', 3), 'abc'); |
| 5798 | strictEqual(rangeBuffer.toString('ascii', 1.99, 3), 'bc'); |
| 5799 | strictEqual(rangeBuffer.toString('ascii', true, 3), 'bc'); |
| 5800 | |
| 5801 | // If end > buffer's length, end will be taken as buffer's length |
| 5802 | strictEqual(rangeBuffer.toString('ascii', 0, 5), 'abc'); |
| 5803 | strictEqual(rangeBuffer.toString('ascii', 0, 6.99), 'abc'); |
| 5804 | strictEqual(rangeBuffer.toString('ascii', 0, Infinity), 'abc'); |
| 5805 | strictEqual(rangeBuffer.toString('ascii', 0, '5'), 'abc'); |
| 5806 | strictEqual(rangeBuffer.toString('ascii', 0, '6.99'), 'abc'); |
| 5807 | strictEqual(rangeBuffer.toString('ascii', 0, 'Infinity'), 'abc'); |
| 5808 | |
| 5809 | // If end is an invalid integer, end will be taken as buffer's length |
| 5810 | strictEqual(rangeBuffer.toString('ascii', 0, 'node.js'), ''); |
| 5811 | strictEqual(rangeBuffer.toString('ascii', 0, {}), ''); |
| 5812 | strictEqual(rangeBuffer.toString('ascii', 0, NaN), ''); |
| 5813 | strictEqual(rangeBuffer.toString('ascii', 0, undefined), 'abc'); |
| 5814 | strictEqual(rangeBuffer.toString('ascii', 0), 'abc'); |
| 5815 | strictEqual(rangeBuffer.toString('ascii', 0, null), ''); |
| 5816 | strictEqual(rangeBuffer.toString('ascii', 0, []), ''); |
| 5817 | strictEqual(rangeBuffer.toString('ascii', 0, false), ''); |
| 5818 | strictEqual(rangeBuffer.toString('ascii', 0, ''), ''); |
| 5819 | |
| 5820 | // But, if end is an integer when coerced, then it will be coerced and used. |
| 5821 | strictEqual(rangeBuffer.toString('ascii', 0, '-1'), ''); |
| 5822 | strictEqual(rangeBuffer.toString('ascii', 0, '1'), 'a'); |
| 5823 | strictEqual(rangeBuffer.toString('ascii', 0, '-Infinity'), ''); |
| 5824 | strictEqual(rangeBuffer.toString('ascii', 0, '3'), 'abc'); |
| 5825 | strictEqual(rangeBuffer.toString('ascii', 0, Number(3)), 'abc'); |
| 5826 | strictEqual(rangeBuffer.toString('ascii', 0, '3.14'), 'abc'); |
| 5827 | strictEqual(rangeBuffer.toString('ascii', 0, '1.99'), 'a'); |
| 5828 | strictEqual(rangeBuffer.toString('ascii', 0, '-1.99'), ''); |
| 5829 | strictEqual(rangeBuffer.toString('ascii', 0, 1.99), 'a'); |
| 5830 | strictEqual(rangeBuffer.toString('ascii', 0, true), 'a'); |
| 5831 | |
| 5832 | // Try toString() with an object as an encoding |
| 5833 | strictEqual( |
| 5834 | rangeBuffer.toString({ |
| 5835 | toString: function () { |
| 5836 | return 'ascii'; |
| 5837 | }, |
| 5838 | }), |
| 5839 | 'abc' |
| 5840 | ); |
| 5841 | |
| 5842 | // Try toString() with 0 and null as the encoding |
| 5843 | throws( |
| 5844 | () => { |
| 5845 | rangeBuffer.toString(0, 1, 2); |
| 5846 | }, |
| 5847 | { |
| 5848 | name: 'TypeError', |
| 5849 | }, |
| 5850 | 'toString() with 0 and null as the encoding should have thrown' |
| 5851 | ); |
| 5852 | |
| 5853 | throws( |
| 5854 | () => { |
| 5855 | rangeBuffer.toString(null, 1, 2); |
| 5856 | }, |
| 5857 | { |
| 5858 | name: 'TypeError', |
| 5859 | }, |
| 5860 | 'toString() with null encoding should have thrown' |
| 5861 | ); |
| 5862 | }, |
| 5863 | }; |
| 5864 | |
| 5865 | export const inspect = { |
| 5866 | // test-buffer-inspect.js |
| 5867 | async test(ctrl, env, ctx) { |
| 5868 | let b = Buffer.allocUnsafe(60); |
| 5869 | b.fill('0123456789'.repeat(6)); |
| 5870 | |
| 5871 | let s = buffer.SlowBuffer(60); |
| 5872 | s.fill('0123456789'.repeat(6)); |
| 5873 | |
| 5874 | let expected = |
| 5875 | '<Buffer 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 ... 10 more bytes>'; |
| 5876 | |
| 5877 | strictEqual(util.inspect(b), expected); |
| 5878 | strictEqual(util.inspect(s), expected); |
| 5879 | |
| 5880 | b = Buffer.allocUnsafe(2); |
| 5881 | b.fill('12'); |
| 5882 | |
| 5883 | s = buffer.SlowBuffer(2); |
| 5884 | s.fill('12'); |
| 5885 | |
| 5886 | expected = '<Buffer 31 32>'; |
| 5887 | |
| 5888 | strictEqual(util.inspect(b), expected); |
| 5889 | strictEqual(util.inspect(s), expected); |
| 5890 | |
| 5891 | b.inspect = undefined; |
| 5892 | b.prop = new Uint8Array(0); |
| 5893 | strictEqual( |
| 5894 | util.inspect(b), |
| 5895 | '<Buffer 31 32, inspect: undefined, prop: Uint8Array(0) []>' |
| 5896 | ); |
| 5897 | |
| 5898 | b = Buffer.alloc(0); |
| 5899 | b.prop = 123; |
| 5900 | |
| 5901 | strictEqual(util.inspect(b), '<Buffer prop: 123>'); |
| 5902 | }, |
| 5903 | }; |
| 5904 | |
| 5905 | export const isAsciiTest = { |
| 5906 | test(ctrl, env, ctx) { |
| 5907 | const encoder = new TextEncoder(); |
| 5908 | strictEqual(isAscii(encoder.encode('hello')), true); |
| 5909 | strictEqual(isAscii(encoder.encode('ğ')), false); |
| 5910 | strictEqual(isAscii(Buffer.from([])), true); |
| 5911 | |
| 5912 | [ |
| 5913 | undefined, |
| 5914 | '', |
| 5915 | 'hello', |
| 5916 | false, |
| 5917 | true, |
| 5918 | 0, |
| 5919 | 1, |
| 5920 | 0n, |
| 5921 | 1n, |
| 5922 | Symbol(), |
| 5923 | () => {}, |
| 5924 | {}, |
| 5925 | [], |
| 5926 | null, |
| 5927 | ].forEach((input) => { |
| 5928 | throws(() => isAscii(input)); |
| 5929 | }); |
| 5930 | }, |
| 5931 | }; |
| 5932 | |
| 5933 | export const isUtf8Test = { |
| 5934 | test(ctrl, env, ctx) { |
| 5935 | const encoder = new TextEncoder(); |
| 5936 | |
| 5937 | strictEqual(isUtf8(encoder.encode('hello')), true); |
| 5938 | strictEqual(isUtf8(encoder.encode('ğ')), true); |
| 5939 | strictEqual(isUtf8(Buffer.from([])), true); |
| 5940 | |
| 5941 | // Taken from test/fixtures/wpt/encoding/textdecoder-fatal.any.js |
| 5942 | [ |
| 5943 | [0xff], // 'invalid code' |
| 5944 | [0xc0], // 'ends early' |
| 5945 | [0xe0], // 'ends early 2' |
| 5946 | [0xc0, 0x00], // 'invalid trail' |
| 5947 | [0xc0, 0xc0], // 'invalid trail 2' |
| 5948 | [0xe0, 0x00], // 'invalid trail 3' |
| 5949 | [0xe0, 0xc0], // 'invalid trail 4' |
| 5950 | [0xe0, 0x80, 0x00], // 'invalid trail 5' |
| 5951 | [0xe0, 0x80, 0xc0], // 'invalid trail 6' |
| 5952 | [0xfc, 0x80, 0x80, 0x80, 0x80, 0x80], // '> 0x10FFFF' |
| 5953 | [0xfe, 0x80, 0x80, 0x80, 0x80, 0x80], // 'obsolete lead byte' |
| 5954 | |
| 5955 | // Overlong encodings |
| 5956 | [0xc0, 0x80], // 'overlong U+0000 - 2 bytes' |
| 5957 | [0xe0, 0x80, 0x80], // 'overlong U+0000 - 3 bytes' |
| 5958 | [0xf0, 0x80, 0x80, 0x80], // 'overlong U+0000 - 4 bytes' |
| 5959 | [0xf8, 0x80, 0x80, 0x80, 0x80], // 'overlong U+0000 - 5 bytes' |
| 5960 | [0xfc, 0x80, 0x80, 0x80, 0x80, 0x80], // 'overlong U+0000 - 6 bytes' |
| 5961 | |
| 5962 | [0xc1, 0xbf], // 'overlong U+007F - 2 bytes' |
| 5963 | [0xe0, 0x81, 0xbf], // 'overlong U+007F - 3 bytes' |
| 5964 | [0xf0, 0x80, 0x81, 0xbf], // 'overlong U+007F - 4 bytes' |
| 5965 | [0xf8, 0x80, 0x80, 0x81, 0xbf], // 'overlong U+007F - 5 bytes' |
| 5966 | [0xfc, 0x80, 0x80, 0x80, 0x81, 0xbf], // 'overlong U+007F - 6 bytes' |
| 5967 | |
| 5968 | [0xe0, 0x9f, 0xbf], // 'overlong U+07FF - 3 bytes' |
| 5969 | [0xf0, 0x80, 0x9f, 0xbf], // 'overlong U+07FF - 4 bytes' |
| 5970 | [0xf8, 0x80, 0x80, 0x9f, 0xbf], // 'overlong U+07FF - 5 bytes' |
| 5971 | [0xfc, 0x80, 0x80, 0x80, 0x9f, 0xbf], // 'overlong U+07FF - 6 bytes' |
| 5972 | |
| 5973 | [0xf0, 0x8f, 0xbf, 0xbf], // 'overlong U+FFFF - 4 bytes' |
| 5974 | [0xf8, 0x80, 0x8f, 0xbf, 0xbf], // 'overlong U+FFFF - 5 bytes' |
| 5975 | [0xfc, 0x80, 0x80, 0x8f, 0xbf, 0xbf], // 'overlong U+FFFF - 6 bytes' |
| 5976 | |
| 5977 | [0xf8, 0x84, 0x8f, 0xbf, 0xbf], // 'overlong U+10FFFF - 5 bytes' |
| 5978 | [0xfc, 0x80, 0x84, 0x8f, 0xbf, 0xbf], // 'overlong U+10FFFF - 6 bytes' |
| 5979 | |
| 5980 | // UTF-16 surrogates encoded as code points in UTF-8 |
| 5981 | [0xed, 0xa0, 0x80], // 'lead surrogate' |
| 5982 | [0xed, 0xb0, 0x80], // 'trail surrogate' |
| 5983 | [0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80], // 'surrogate pair' |
| 5984 | ].forEach((input) => { |
| 5985 | strictEqual(isUtf8(Buffer.from(input)), false); |
| 5986 | }); |
| 5987 | |
| 5988 | [null, undefined, 'hello', true, false].forEach((input) => { |
| 5989 | throws(() => isUtf8(input)); |
| 5990 | }); |
| 5991 | }, |
| 5992 | }; |
| 5993 | |
| 5994 | // Adapted from test/parallel/test-icu-transcode.js |
| 5995 | export const transcodeTest = { |
| 5996 | test(ctrl, env, ctx) { |
| 5997 | const orig = Buffer.from('těst ☕', 'utf8'); |
| 5998 | const tests = { |
| 5999 | latin1: [0x74, 0x3f, 0x73, 0x74, 0x20, 0x3f], |
| 6000 | ascii: [0x74, 0x3f, 0x73, 0x74, 0x20, 0x3f], |
| 6001 | ucs2: [ |
| 6002 | 0x74, 0x00, 0x1b, 0x01, 0x73, 0x00, 0x74, 0x00, 0x20, 0x00, 0x15, 0x26, |
| 6003 | ], |
| 6004 | }; |
| 6005 | |
| 6006 | for (const test in tests) { |
| 6007 | const dest = transcode(orig, 'utf8', test); |
| 6008 | strictEqual( |
| 6009 | dest.length, |
| 6010 | tests[test].length, |
| 6011 | `utf8->${test} length (${dest.length}, ${tests[test].length})` |
| 6012 | ); |
| 6013 | for (let n = 0; n < tests[test].length; n++) { |
| 6014 | strictEqual(dest[n], tests[test][n], `utf8->${test} char ${n}`); |
| 6015 | } |
| 6016 | } |
| 6017 | |
| 6018 | { |
| 6019 | const dest = transcode(Buffer.from(tests.ucs2), 'ucs2', 'utf8'); |
| 6020 | strictEqual(dest.toString(), orig.toString()); |
| 6021 | } |
| 6022 | |
| 6023 | // Test utf16le to ascii/latin1 output length |
| 6024 | { |
| 6025 | const input = Buffer.from('AAA', 'utf16le'); |
| 6026 | strictEqual(input.length, 6); |
| 6027 | const asciiOutput = transcode(input, 'utf16le', 'ascii'); |
| 6028 | strictEqual(asciiOutput.length, 3); |
| 6029 | deepStrictEqual(asciiOutput, Buffer.from('AAA', 'ascii')); |
| 6030 | const latin1Output = transcode(input, 'utf16le', 'latin1'); |
| 6031 | strictEqual(latin1Output.length, 3); |
| 6032 | deepStrictEqual(latin1Output, Buffer.from('AAA', 'latin1')); |
| 6033 | } |
| 6034 | |
| 6035 | { |
| 6036 | const utf8 = Buffer.from('€'.repeat(4000), 'utf8'); |
| 6037 | const ucs2 = Buffer.from('€'.repeat(4000), 'ucs2'); |
| 6038 | const utf8_to_ucs2 = transcode(utf8, 'utf8', 'ucs2'); |
| 6039 | const ucs2_to_utf8 = transcode(ucs2, 'ucs2', 'utf8'); |
| 6040 | deepStrictEqual(utf8, ucs2_to_utf8); |
| 6041 | deepStrictEqual(ucs2, utf8_to_ucs2); |
| 6042 | strictEqual(ucs2_to_utf8.toString('utf8'), utf8_to_ucs2.toString('ucs2')); |
| 6043 | } |
| 6044 | |
| 6045 | { |
| 6046 | deepStrictEqual( |
| 6047 | transcode(Buffer.from('hi', 'ascii'), 'ascii', 'utf16le'), |
| 6048 | Buffer.from('hi', 'utf16le') |
| 6049 | ); |
| 6050 | deepStrictEqual( |
| 6051 | transcode(Buffer.from('hi', 'latin1'), 'latin1', 'utf16le'), |
| 6052 | Buffer.from('hi', 'utf16le') |
| 6053 | ); |
| 6054 | deepStrictEqual( |
| 6055 | transcode(Buffer.from('hä', 'latin1'), 'latin1', 'utf16le'), |
| 6056 | Buffer.from('hä', 'utf16le') |
| 6057 | ); |
| 6058 | } |
| 6059 | |
| 6060 | { |
| 6061 | const dest = transcode(new Uint8Array(), 'utf8', 'latin1'); |
| 6062 | strictEqual(dest.length, 0); |
| 6063 | } |
| 6064 | |
| 6065 | // Test that Uint8Array arguments are okay. |
| 6066 | { |
| 6067 | const uint8array = new Uint8Array(Buffer.from('hä', 'latin1')); |
| 6068 | deepStrictEqual( |
| 6069 | transcode(uint8array, 'latin1', 'utf16le'), |
| 6070 | Buffer.from('hä', 'utf16le') |
| 6071 | ); |
| 6072 | } |
| 6073 | |
| 6074 | // Invalid arguments should fail |
| 6075 | throws(() => transcode(null, 'utf8', 'ascii')); |
| 6076 | throws(() => transcode(Buffer.from('a'), 'b', 'utf8')); |
| 6077 | throws(() => transcode(Buffer.from('a'), 'uf8', 'b')); |
| 6078 | |
| 6079 | // Throws error for buffer bigger than 128mb. |
| 6080 | { |
| 6081 | const ISOLATE_MAX_SIZE = 134217728; |
| 6082 | const val = Buffer.from('a'.repeat(ISOLATE_MAX_SIZE)); |
| 6083 | |
| 6084 | throws(() => transcode(val, 'utf16le', 'utf8')); |
| 6085 | throws(() => transcode(val, 'latin1', 'utf16le')); |
| 6086 | } |
| 6087 | |
| 6088 | // Make sure same fromEncoding and toEncoding results in copy. |
| 6089 | { |
| 6090 | const original = Buffer.from('a'); |
| 6091 | const copied_value = transcode(original, 'utf8', 'utf8'); |
| 6092 | // Let's detach the copied_value |
| 6093 | const _ = copied_value.buffer.transfer(); |
| 6094 | ok(copied_value.buffer.detached); |
| 6095 | ok(!original.buffer.detached); |
| 6096 | } |
| 6097 | |
| 6098 | // Same encoding types should return in a value that replaces |
| 6099 | // invalid characters with replacement characters. |
| 6100 | deepStrictEqual( |
| 6101 | transcode(Buffer.from([0x80]), 'utf8', 'utf8'), |
| 6102 | Buffer.from([0xef, 0xbf, 0xbd]) |
| 6103 | ); |
| 6104 | }, |
| 6105 | }; |
| 6106 | |
| 6107 | // TranscodeFromUTF16 should not over-allocate the output buffer. |
| 6108 | // Regression test for a bug where `limit * sizeof(char16_t)` doubled the |
| 6109 | // allocation and `destPtr.size()` passed char16_t element count instead of |
| 6110 | // byte count to ucnv_fromUChars. |
| 6111 | export const transcodeFromUTF16BufferSizeTest = { |
| 6112 | test() { |
| 6113 | const utf16 = Buffer.from('Hello', 'utf16le'); |
| 6114 | const latin1 = transcode(utf16, 'utf16le', 'latin1'); |
| 6115 | strictEqual(latin1.length, 5); |
| 6116 | strictEqual(latin1.buffer.byteLength, latin1.length); |
| 6117 | }, |
| 6118 | }; |
| 6119 | |
| 6120 | // Invalid UTF-8 input to transcode('utf8', 'utf16le') should produce |
| 6121 | // "Unable to transcode buffer", not an internal assertion mismatch. |
| 6122 | // Regression test for a bug where JSG_REQUIRE(actual == expected) threw |
| 6123 | // before the `if (actual == 0) return kj::none` path could be reached. |
| 6124 | export const transcodeUTF8ToUTF16InvalidInputTest = { |
| 6125 | test() { |
| 6126 | throws( |
| 6127 | () => |
| 6128 | transcode( |
| 6129 | Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x80]), |
| 6130 | 'utf8', |
| 6131 | 'utf16le' |
| 6132 | ), |
| 6133 | { message: /Unable to transcode buffer/ } |
| 6134 | ); |
| 6135 | }, |
| 6136 | }; |
| 6137 | |
| 6138 | // TranscodeFromUTF16 should reject odd-byte UTF-16LE input, matching |
| 6139 | // the guard that TranscodeUTF8FromUTF16 already has. |
| 6140 | // Regression test for a bug where `source.size() / sizeof(char16_t)` |
| 6141 | // silently dropped the trailing byte. |
| 6142 | export const transcodeFromUTF16OddByteInputTest = { |
| 6143 | test() { |
| 6144 | const oddInput = Buffer.from([0x41, 0x00, 0x42]); |
| 6145 | throws(() => transcode(oddInput, 'utf16le', 'utf8')); |
| 6146 | throws(() => transcode(oddInput, 'utf16le', 'latin1')); |
| 6147 | throws(() => transcode(oddInput, 'utf16le', 'ascii')); |
| 6148 | }, |
| 6149 | }; |
| 6150 | |
| 6151 | // Tests are taken from Node.js |
| 6152 | // https://github.com/nodejs/node/blob/a4f609fa/test/parallel/test-file.js |
| 6153 | export const fileTest = { |
| 6154 | test() { |
| 6155 | throws(() => new File(), TypeError); |
| 6156 | throws(() => new File([]), TypeError); |
| 6157 | throws(() => File.prototype.name, TypeError); |
| 6158 | throws(() => File.prototype.lastModified, TypeError); |
| 6159 | |
| 6160 | { |
| 6161 | const keys = Object.keys(File.prototype).sort(); |
| 6162 | deepStrictEqual(keys, ['lastModified', 'name']); |
| 6163 | } |
| 6164 | |
| 6165 | { |
| 6166 | const file = new File([], 'dummy.txt.exe'); |
| 6167 | strictEqual(file.name, 'dummy.txt.exe'); |
| 6168 | strictEqual(file.size, 0); |
| 6169 | strictEqual(typeof file.lastModified, 'number'); |
| 6170 | ok(file.lastModified <= Date.now()); |
| 6171 | } |
| 6172 | |
| 6173 | { |
| 6174 | const toPrimitive = { |
| 6175 | [Symbol.toPrimitive]() { |
| 6176 | return 'NaN'; |
| 6177 | }, |
| 6178 | }; |
| 6179 | |
| 6180 | const invalidLastModified = [null, 'string', false, toPrimitive]; |
| 6181 | |
| 6182 | for (const lastModified of invalidLastModified) { |
| 6183 | const file = new File([], '', { lastModified }); |
| 6184 | strictEqual(file.lastModified, 0); |
| 6185 | } |
| 6186 | } |
| 6187 | |
| 6188 | { |
| 6189 | const file = new File([], '', { lastModified: undefined }); |
| 6190 | notStrictEqual(file.lastModified, 0); |
| 6191 | } |
| 6192 | |
| 6193 | { |
| 6194 | const toPrimitive = { |
| 6195 | [Symbol.toPrimitive]() { |
| 6196 | throw new TypeError('boom'); |
| 6197 | }, |
| 6198 | }; |
| 6199 | |
| 6200 | const throwValues = [BigInt(3n), toPrimitive]; |
| 6201 | |
| 6202 | for (const lastModified of throwValues) { |
| 6203 | throws(() => new File([], '', { lastModified }), TypeError); |
| 6204 | } |
| 6205 | } |
| 6206 | |
| 6207 | { |
| 6208 | const valid = [ |
| 6209 | { |
| 6210 | [Symbol.toPrimitive]() { |
| 6211 | return 10; |
| 6212 | }, |
| 6213 | }, |
| 6214 | new Number(10), |
| 6215 | 10, |
| 6216 | ]; |
| 6217 | |
| 6218 | for (const lastModified of valid) { |
| 6219 | strictEqual(new File([], '', { lastModified }).lastModified, 10); |
| 6220 | } |
| 6221 | } |
| 6222 | |
| 6223 | { |
| 6224 | function MyClass() {} |
| 6225 | MyClass.prototype.lastModified = 10; |
| 6226 | |
| 6227 | const file = new File([], '', new MyClass()); |
| 6228 | strictEqual(file.lastModified, 10); |
| 6229 | } |
| 6230 | |
| 6231 | { |
| 6232 | let counter = 0; |
| 6233 | new File([], '', { |
| 6234 | get lastModified() { |
| 6235 | counter++; |
| 6236 | return 10; |
| 6237 | }, |
| 6238 | }); |
| 6239 | strictEqual(counter, 1); |
| 6240 | } |
| 6241 | }, |
| 6242 | }; |
| 6243 | |
| 6244 | // Ref: https://github.com/cloudflare/workerd/issues/2538 |
| 6245 | export const sliceOffsetLimits = { |
| 6246 | test() { |
| 6247 | // Make sure the second parameter represents the "end" index, not length. |
| 6248 | strictEqual(Buffer.from('abcd').utf8Slice(2, 3).toString(), 'c'); |
| 6249 | // Make sure to handle (end < start) edge case. |
| 6250 | strictEqual(Buffer.from('abcd').utf8Slice(1, 0).toString(), ''); |
| 6251 | }, |
| 6252 | }; |
| 6253 | |
| 6254 | // Ref: https://github.com/unjs/unenv/pull/325 |
| 6255 | // Without `.bind(globalThis)` the following tests fail. |
| 6256 | export const invalidThisTests = { |
| 6257 | async test() { |
| 6258 | const bufferModule = await import('node:buffer'); |
| 6259 | strictEqual(bufferModule.btoa('hello'), 'aGVsbG8='); |
| 6260 | strictEqual(bufferModule.atob('aGVsbG8='), 'hello'); |
| 6261 | ok(new bufferModule.File([], 'file')); |
| 6262 | ok(new bufferModule.Blob([])); |
| 6263 | }, |
| 6264 | }; |