tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nan-canonicalization.js (7368B)


      1 // Test NaN canonicalisation when reading from a DataView.
      2 
      3 load(libdir + "dataview.js");
      4 
      5 // Float16
      6 function testF16() {
      7  function writeBE(ui16, value) {
      8    let ui8 = new Uint8Array(ui16.buffer);
      9 
     10    ui8[0] = (value >> 8) & 0xff;
     11    ui8[1] = (value >> 0) & 0xff;
     12  }
     13 
     14  function writeLE(ui16, value) {
     15    let ui8 = new Uint8Array(ui16.buffer);
     16 
     17    ui8[0] = (value >> 0) & 0xff;
     18    ui8[1] = (value >> 8) & 0xff;
     19  }
     20 
     21  // Smallest and largest SNaNs and QNaNs, with and without sign-bit set.
     22  const NaNs = [
     23    0x7C01, 0x7DFF, 0x7E00, 0x7FFF,
     24    0xFC01, 0xFDFF, 0xFE00, 0xFFFF,
     25  ];
     26 
     27  const canonicalNaN = new Uint16Array(new Float16Array([NaN]).buffer)[0];
     28 
     29  // Load from array so that Ion doesn't treat as constants.
     30  const True = [true, 1];
     31  const False = [false, 0];
     32 
     33  function f() {
     34    let src_ui16 = new Uint16Array(1);
     35 
     36    let dst_f16 = new Float16Array(1);
     37    let dst_ui16 = new Uint16Array(dst_f16.buffer);
     38 
     39    let dv = new DataView(src_ui16.buffer);
     40 
     41    for (let i = 0; i < 100; ++i) {
     42      let nan = NaNs[i % NaNs.length];
     43 
     44      // Write to typed array, implicitly using native endian.
     45      src_ui16[0] = nan;
     46      dst_f16[0] = dv.getFloat16(0, nativeIsLittleEndian);
     47      assertEq(dst_ui16[0], canonicalNaN);
     48 
     49      // Write and read using big endian. |isLittleEndian| parameter is absent.
     50      writeBE(src_ui16, nan);
     51      dst_f16[0] = dv.getFloat16(0);
     52      assertEq(dst_ui16[0], canonicalNaN);
     53 
     54      // Write and read using big endian. |isLittleEndian| parameter is a constant.
     55      writeBE(src_ui16, nan);
     56      dst_f16[0] = dv.getFloat16(0, false);
     57      assertEq(dst_ui16[0], canonicalNaN);
     58 
     59      // Write and read using little endian. |isLittleEndian| parameter is a constant.
     60      writeLE(src_ui16, nan);
     61      dst_f16[0] = dv.getFloat16(0, true);
     62      assertEq(dst_ui16[0], canonicalNaN);
     63 
     64      // Write and read using big endian.
     65      writeBE(src_ui16, nan);
     66      dst_f16[0] = dv.getFloat16(0, False[i & 1]);
     67      assertEq(dst_ui16[0], canonicalNaN);
     68 
     69      // Write and read using little endian.
     70      writeLE(src_ui16, nan);
     71      dst_f16[0] = dv.getFloat16(0, True[i & 1]);
     72      assertEq(dst_ui16[0], canonicalNaN);
     73    }
     74  }
     75 
     76  for (let i = 0; i < 2; ++i) f();
     77 }
     78 testF16();
     79 
     80 // Float32
     81 function testF32() {
     82  function writeBE(ui32, value) {
     83    let ui8 = new Uint8Array(ui32.buffer);
     84 
     85    ui8[0] = (value >> 24) & 0xff;
     86    ui8[1] = (value >> 16) & 0xff;
     87    ui8[2] = (value >> 8) & 0xff;
     88    ui8[3] = (value >> 0) & 0xff;
     89  }
     90 
     91  function writeLE(ui32, value) {
     92    let ui8 = new Uint8Array(ui32.buffer);
     93 
     94    ui8[0] = (value >> 0) & 0xff;
     95    ui8[1] = (value >> 8) & 0xff;
     96    ui8[2] = (value >> 16) & 0xff;
     97    ui8[3] = (value >> 24) & 0xff;
     98  }
     99 
    100  // Smallest and largest SNaNs and QNaNs, with and without sign-bit set.
    101  const NaNs = [
    102    0x7F80_0001, 0x7FBF_FFFF, 0x7FC0_0000, 0x7FFF_FFFF,
    103    0xFF80_0001, 0xFFBF_FFFF, 0xFFC0_0000, 0xFFFF_FFFF,
    104  ];
    105 
    106  const canonicalNaN = new Uint32Array(new Float32Array([NaN]).buffer)[0];
    107 
    108  // Load from array so that Ion doesn't treat as constants.
    109  const True = [true, 1];
    110  const False = [false, 0];
    111 
    112  function f() {
    113    let src_ui32 = new Uint32Array(1);
    114 
    115    let dst_f32 = new Float32Array(1);
    116    let dst_ui32 = new Uint32Array(dst_f32.buffer);
    117 
    118    let dv = new DataView(src_ui32.buffer);
    119 
    120    for (let i = 0; i < 100; ++i) {
    121      let nan = NaNs[i % NaNs.length];
    122 
    123      // Write to typed array, implicitly using native endian.
    124      src_ui32[0] = nan;
    125      dst_f32[0] = dv.getFloat32(0, nativeIsLittleEndian);
    126      assertEq(dst_ui32[0], canonicalNaN);
    127 
    128      // Write and read using big endian. |isLittleEndian| parameter is absent.
    129      writeBE(src_ui32, nan);
    130      dst_f32[0] = dv.getFloat32(0);
    131      assertEq(dst_ui32[0], canonicalNaN);
    132 
    133      // Write and read using big endian. |isLittleEndian| parameter is a constant.
    134      writeBE(src_ui32, nan);
    135      dst_f32[0] = dv.getFloat32(0, false);
    136      assertEq(dst_ui32[0], canonicalNaN);
    137 
    138      // Write and read using little endian. |isLittleEndian| parameter is a constant.
    139      writeLE(src_ui32, nan);
    140      dst_f32[0] = dv.getFloat32(0, true);
    141      assertEq(dst_ui32[0], canonicalNaN);
    142 
    143      // Write and read using big endian.
    144      writeBE(src_ui32, nan);
    145      dst_f32[0] = dv.getFloat32(0, False[i & 1]);
    146      assertEq(dst_ui32[0], canonicalNaN);
    147 
    148      // Write and read using little endian.
    149      writeLE(src_ui32, nan);
    150      dst_f32[0] = dv.getFloat32(0, True[i & 1]);
    151      assertEq(dst_ui32[0], canonicalNaN);
    152    }
    153  }
    154 
    155  for (let i = 0; i < 2; ++i) f();
    156 }
    157 testF32();
    158 
    159 // Float64
    160 function testF64() {
    161  function writeBE(ui64, value) {
    162    let ui8 = new Uint8Array(ui64.buffer);
    163 
    164    ui8[0] = Number((value >> 56n) & 0xffn);
    165    ui8[1] = Number((value >> 48n) & 0xffn);
    166    ui8[2] = Number((value >> 40n) & 0xffn);
    167    ui8[3] = Number((value >> 32n) & 0xffn);
    168    ui8[4] = Number((value >> 24n) & 0xffn);
    169    ui8[5] = Number((value >> 16n) & 0xffn);
    170    ui8[6] = Number((value >> 8n) & 0xffn);
    171    ui8[7] = Number((value >> 0n) & 0xffn);
    172  }
    173 
    174  function writeLE(ui64, value) {
    175    let ui8 = new Uint8Array(ui64.buffer);
    176 
    177    ui8[0] = Number((value >> 0n) & 0xffn);
    178    ui8[1] = Number((value >> 8n) & 0xffn);
    179    ui8[2] = Number((value >> 16n) & 0xffn);
    180    ui8[3] = Number((value >> 24n) & 0xffn);
    181    ui8[4] = Number((value >> 32n) & 0xffn);
    182    ui8[5] = Number((value >> 40n) & 0xffn);
    183    ui8[6] = Number((value >> 48n) & 0xffn);
    184    ui8[7] = Number((value >> 56n) & 0xffn);
    185  }
    186 
    187  // Smallest and largest SNaNs and QNaNs, with and without sign-bit set.
    188  const NaNs = [
    189    0x7FF0_0000_0000_0001n, 0x7FF7_FFFF_FFFF_FFFFn, 0x7FF8_0000_0000_0000n, 0x7FFF_FFFF_FFFF_FFFFn,
    190    0xFFF0_0000_0000_0001n, 0xFFF7_FFFF_FFFF_FFFFn, 0xFFF8_0000_0000_0000n, 0xFFFF_FFFF_FFFF_FFFFn,
    191  ];
    192 
    193  const canonicalNaN = new BigUint64Array(new Float64Array([NaN]).buffer)[0];
    194 
    195  // Load from array so that Ion doesn't treat as constants.
    196  const True = [true, 1];
    197  const False = [false, 0];
    198 
    199  function f() {
    200    let src_ui64 = new BigUint64Array(1);
    201 
    202    let dst_f64 = new Float64Array(1);
    203    let dst_ui64 = new BigUint64Array(dst_f64.buffer);
    204 
    205    let dv = new DataView(src_ui64.buffer);
    206 
    207    for (let i = 0; i < 100; ++i) {
    208      let nan = NaNs[i % NaNs.length];
    209 
    210      src_ui64[0] = nan;
    211      dst_f64[0] = dv.getFloat64(0, nativeIsLittleEndian);
    212      assertEq(dst_ui64[0], canonicalNaN);
    213 
    214      // Write and read using big endian. |isLittleEndian| parameter is absent.
    215      writeBE(src_ui64, nan);
    216      dst_f64[0] = dv.getFloat64(0);
    217      assertEq(dst_ui64[0], canonicalNaN);
    218 
    219      // Write and read using big endian. |isLittleEndian| parameter is a constant.
    220      writeBE(src_ui64, nan);
    221      dst_f64[0] = dv.getFloat64(0, false);
    222      assertEq(dst_ui64[0], canonicalNaN);
    223 
    224      // Write and read using little endian. |isLittleEndian| parameter is a constant.
    225      writeLE(src_ui64, nan);
    226      dst_f64[0] = dv.getFloat64(0, true);
    227      assertEq(dst_ui64[0], canonicalNaN);
    228 
    229      // Write and read using big endian.
    230      writeBE(src_ui64, nan);
    231      dst_f64[0] = dv.getFloat64(0, False[i & 1]);
    232      assertEq(dst_ui64[0], canonicalNaN);
    233 
    234      // Write and read using little endian.
    235      writeLE(src_ui64, nan);
    236      dst_f64[0] = dv.getFloat64(0, True[i & 1]);
    237      assertEq(dst_ui64[0], canonicalNaN);
    238    }
    239  }
    240 
    241  for (let i = 0; i < 2; ++i) f();
    242 }
    243 testF64();