npm package: @ronomon/reed-solomon
Description: Fast, reliable Reed-Solomon erasure coding as a native addon for Node.js
Author: Joran Dirk Greef
Latest version: 6.0.0

# reed-solomon
Fast, reliable Reed-Solomon erasure coding as a native addon for Node.js,
licensed under the [MIT License](https://en.wikipedia.org/wiki/MIT_License).

For an introduction to erasure coding, see this post by Brian Beach on the
[Backblaze blog](https://www.backblaze.com/blog/reed-solomon/).

* [Installation](#installation)
* [Performance](#performance)
* [Usage](#usage)
* [Tests](#tests)
* [Benchmark](#benchmark)

## Installation
```
npm install @ronomon/reed-solomon
```

## Performance
The native addon executes asynchronously in Node's threadpool without blocking the event loop:
```
       CPU | Intel(R) Xeon(R) CPU E3-1230 V2 @ 3.30GHz
     CORES | 8
   THREADS | 1

------------------------------------------------------------------
      DATA |     PARITY | SHARD SIZE |    LATENCY |     THROUGHPUT
------------------------------------------------------------------
         1 |          1 |       4096 |    0.202ms |     20.29 MB/s
         1 |          1 |      65536 |    0.038ms |   1720.57 MB/s
         1 |          1 |     262144 |    0.048ms |   5435.80 MB/s
------------------------------------------------------------------
         1 |          2 |       4096 |    0.020ms |    199.95 MB/s
         1 |          2 |      65536 |    0.025ms |   2606.39 MB/s
         1 |          2 |     262144 |    0.081ms |   3249.66 MB/s
------------------------------------------------------------------
         1 |          3 |       4096 |    0.023ms |    177.43 MB/s
         1 |          3 |      65536 |    0.033ms |   2004.03 MB/s
         1 |          3 |     262144 |    0.108ms |   2428.02 MB/s
------------------------------------------------------------------
         1 |          4 |       4096 |    0.027ms |    149.38 MB/s
         1 |          4 |      65536 |    0.041ms |   1611.52 MB/s
         1 |          4 |     262144 |    0.134ms |   1952.67 MB/s
------------------------------------------------------------------
         2 |          1 |       4096 |    0.041ms |    197.48 MB/s
         2 |          1 |      65536 |    0.057ms |   2285.90 MB/s
         2 |          1 |     262144 |    0.114ms |   4611.48 MB/s
------------------------------------------------------------------
         2 |          2 |       4096 |    0.049ms |    166.09 MB/s
         2 |          2 |      65536 |    0.075ms |   1736.75 MB/s
         2 |          2 |     262144 |    0.203ms |   2579.89 MB/s
------------------------------------------------------------------
         2 |          3 |       4096 |    0.064ms |    128.74 MB/s
         2 |          3 |      65536 |    0.093ms |   1414.32 MB/s
         2 |          3 |     262144 |    0.316ms |   1659.31 MB/s
------------------------------------------------------------------
         2 |          4 |       4096 |    0.060ms |    135.47 MB/s
         2 |          4 |      65536 |    0.111ms |   1182.68 MB/s
         2 |          4 |     262144 |    0.430ms |   1220.38 MB/s
------------------------------------------------------------------
         3 |          1 |       4096 |    0.065ms |    189.66 MB/s
         3 |          1 |      65536 |    0.076ms |   2602.82 MB/s
         3 |          1 |     262144 |    0.182ms |   4329.66 MB/s
------------------------------------------------------------------
         3 |          2 |       4096 |    0.059ms |    209.24 MB/s
         3 |          2 |      65536 |    0.095ms |   2073.39 MB/s
         3 |          2 |     262144 |    0.322ms |   2441.14 MB/s
------------------------------------------------------------------
         3 |          3 |       4096 |    0.060ms |    204.08 MB/s
         3 |          3 |      65536 |    0.119ms |   1649.52 MB/s
         3 |          3 |     262144 |    0.473ms |   1663.10 MB/s
------------------------------------------------------------------
         3 |          4 |       4096 |    0.076ms |    162.42 MB/s
         3 |          4 |      65536 |    0.227ms |    867.70 MB/s
         3 |          4 |     262144 |    0.618ms |   1273.22 MB/s
------------------------------------------------------------------
         4 |          1 |       4096 |    0.060ms |    273.79 MB/s
         4 |          1 |      65536 |    0.087ms |   3023.48 MB/s
         4 |          1 |     262144 |    0.228ms |   4596.09 MB/s
------------------------------------------------------------------
         4 |          2 |       4096 |    0.056ms |    294.79 MB/s
         4 |          2 |      65536 |    0.111ms |   2362.53 MB/s
         4 |          2 |     262144 |    0.407ms |   2577.41 MB/s
------------------------------------------------------------------
         4 |          3 |       4096 |    0.056ms |    294.13 MB/s
         4 |          3 |      65536 |    0.146ms |   1797.57 MB/s
         4 |          3 |     262144 |    0.623ms |   1681.80 MB/s
------------------------------------------------------------------
         4 |          4 |       4096 |    0.066ms |    248.58 MB/s
         4 |          4 |      65536 |    0.187ms |   1401.34 MB/s
         4 |          4 |     262144 |    0.857ms |   1222.92 MB/s
------------------------------------------------------------------
         5 |          1 |       4096 |    0.067ms |    305.98 MB/s
         5 |          1 |      65536 |    0.150ms |   2177.36 MB/s
         5 |          1 |     262144 |    0.311ms |   4208.79 MB/s
------------------------------------------------------------------
         5 |          2 |       4096 |    0.050ms |    407.33 MB/s
         5 |          2 |      65536 |    0.115ms |   2859.69 MB/s
         5 |          2 |     262144 |    0.500ms |   2621.67 MB/s
------------------------------------------------------------------
         5 |          3 |       4096 |    0.067ms |    304.29 MB/s
         5 |          3 |      65536 |    0.204ms |   1609.13 MB/s
         5 |          3 |     262144 |    0.772ms |   1698.20 MB/s
------------------------------------------------------------------
         5 |          4 |       4096 |    0.074ms |    276.14 MB/s
         5 |          4 |      65536 |    0.257ms |   1274.51 MB/s
         5 |          4 |     262144 |    1.071ms |   1223.68 MB/s
------------------------------------------------------------------
         6 |          1 |       4096 |    0.068ms |    361.53 MB/s
         6 |          1 |      65536 |    0.105ms |   3755.04 MB/s
         6 |          1 |     262144 |    0.354ms |   4439.00 MB/s
------------------------------------------------------------------
         6 |          2 |       4096 |    0.060ms |    409.94 MB/s
         6 |          2 |      65536 |    0.135ms |   2907.23 MB/s
         6 |          2 |     262144 |    0.590ms |   2664.83 MB/s
------------------------------------------------------------------
         6 |          3 |       4096 |    0.064ms |    384.48 MB/s
         6 |          3 |      65536 |    0.237ms |   1662.03 MB/s
         6 |          3 |     262144 |    0.961ms |   1637.34 MB/s
------------------------------------------------------------------
         6 |          4 |       4096 |    0.076ms |    323.20 MB/s
         6 |          4 |      65536 |    0.306ms |   1286.81 MB/s
         6 |          4 |     262144 |    1.269ms |   1239.15 MB/s
------------------------------------------------------------------
         7 |          1 |       4096 |    0.055ms |    518.41 MB/s
         7 |          1 |      65536 |    0.123ms |   3720.08 MB/s
         7 |          1 |     262144 |    0.401ms |   4574.62 MB/s
------------------------------------------------------------------
         7 |          2 |       4096 |    0.055ms |    523.62 MB/s
         7 |          2 |      65536 |    0.172ms |   2665.10 MB/s
         7 |          2 |     262144 |    0.693ms |   2648.54 MB/s
------------------------------------------------------------------
         7 |          3 |       4096 |    0.068ms |    422.02 MB/s
         7 |          3 |      65536 |    0.266ms |   1727.26 MB/s
         7 |          3 |     262144 |    1.100ms |   1668.10 MB/s
------------------------------------------------------------------
         7 |          4 |       4096 |    0.081ms |    352.39 MB/s
         7 |          4 |      65536 |    0.354ms |   1295.14 MB/s
         7 |          4 |     262144 |    1.501ms |   1222.15 MB/s
------------------------------------------------------------------
         8 |          1 |       4096 |    0.046ms |    710.37 MB/s
         8 |          1 |      65536 |    0.104ms |   5024.44 MB/s
         8 |          1 |     262144 |    0.357ms |   5867.80 MB/s
------------------------------------------------------------------
         8 |          2 |       4096 |    0.025ms |   1286.85 MB/s
         8 |          2 |      65536 |    0.130ms |   4019.83 MB/s
         8 |          2 |     262144 |    0.504ms |   4159.09 MB/s
------------------------------------------------------------------
         8 |          3 |       4096 |    0.040ms |    819.81 MB/s
         8 |          3 |      65536 |    0.183ms |   2857.84 MB/s
         8 |          3 |     262144 |    0.683ms |   3072.52 MB/s
------------------------------------------------------------------
         8 |          4 |       4096 |    0.031ms |   1049.90 MB/s
         8 |          4 |      65536 |    0.238ms |   2199.69 MB/s
         8 |          4 |     262144 |    0.983ms |   2133.64 MB/s
------------------------------------------------------------------
         9 |          1 |       4096 |    0.035ms |   1045.72 MB/s
         9 |          1 |      65536 |    0.085ms |   6926.25 MB/s
         9 |          1 |     262144 |    0.370ms |   6376.90 MB/s
------------------------------------------------------------------
         9 |          2 |       4096 |    0.038ms |    982.72 MB/s
         9 |          2 |      65536 |    0.147ms |   4005.27 MB/s
         9 |          2 |     262144 |    0.577ms |   4088.25 MB/s
------------------------------------------------------------------
         9 |          3 |       4096 |    0.041ms |    893.76 MB/s
         9 |          3 |      65536 |    0.224ms |   2629.15 MB/s
         9 |          3 |     262144 |    0.869ms |   2715.82 MB/s
------------------------------------------------------------------
         9 |          4 |       4096 |    0.043ms |    866.49 MB/s
         9 |          4 |      65536 |    0.331ms |   1779.40 MB/s
         9 |          4 |     262144 |    1.281ms |   1842.45 MB/s
------------------------------------------------------------------
        10 |          1 |       4096 |    0.027ms |   1508.91 MB/s
        10 |          1 |      65536 |    0.097ms |   6757.32 MB/s
        10 |          1 |     262144 |    0.421ms |   6233.25 MB/s
------------------------------------------------------------------
        10 |          2 |       4096 |    0.033ms |   1250.72 MB/s
        10 |          2 |      65536 |    0.167ms |   3925.31 MB/s
        10 |          2 |     262144 |    0.654ms |   4011.25 MB/s
------------------------------------------------------------------
        10 |          3 |       4096 |    0.040ms |   1025.30 MB/s
        10 |          3 |      65536 |    0.242ms |   2703.63 MB/s
        10 |          3 |     262144 |    1.047ms |   2504.04 MB/s
------------------------------------------------------------------
        10 |          4 |       4096 |    0.050ms |    824.13 MB/s
        10 |          4 |      65536 |    0.358ms |   1829.99 MB/s
        10 |          4 |     262144 |    1.393ms |   1881.64 MB/s
------------------------------------------------------------------
        11 |          1 |       4096 |    0.029ms |   1565.69 MB/s
        11 |          1 |      65536 |    0.107ms |   6725.60 MB/s
        11 |          1 |     262144 |    0.433ms |   6661.48 MB/s
------------------------------------------------------------------
        11 |          2 |       4096 |    0.041ms |   1108.18 MB/s
        11 |          2 |      65536 |    0.194ms |   3721.06 MB/s
        11 |          2 |     262144 |    0.685ms |   4207.69 MB/s
------------------------------------------------------------------
        11 |          3 |       4096 |    0.035ms |   1280.41 MB/s
        11 |          3 |      65536 |    0.265ms |   2718.35 MB/s
        11 |          3 |     262144 |    1.144ms |   2520.31 MB/s
------------------------------------------------------------------
        11 |          4 |       4096 |    0.051ms |    880.45 MB/s
        11 |          4 |      65536 |    0.417ms |   1727.85 MB/s
        11 |          4 |     262144 |    1.600ms |   1802.67 MB/s
------------------------------------------------------------------
        12 |          1 |       4096 |    0.042ms |   1168.18 MB/s
        12 |          1 |      65536 |    0.121ms |   6489.28 MB/s
        12 |          1 |     262144 |    0.442ms |   7124.52 MB/s
------------------------------------------------------------------
        12 |          2 |       4096 |    0.029ms |   1696.64 MB/s
        12 |          2 |      65536 |    0.188ms |   4185.55 MB/s
        12 |          2 |     262144 |    0.832ms |   3782.82 MB/s
------------------------------------------------------------------
        12 |          3 |       4096 |    0.059ms |    839.80 MB/s
        12 |          3 |      65536 |    0.323ms |   2434.45 MB/s
        12 |          3 |     262144 |    1.314ms |   2393.83 MB/s
------------------------------------------------------------------
        12 |          4 |       4096 |    0.066ms |    740.71 MB/s
        12 |          4 |      65536 |    0.445ms |   1767.18 MB/s
        12 |          4 |     262144 |    1.739ms |   1808.54 MB/s
------------------------------------------------------------------
        13 |          1 |       4096 |    0.029ms |   1832.60 MB/s
        13 |          1 |      65536 |    0.117ms |   7284.64 MB/s
        13 |          1 |     262144 |    0.519ms |   6566.15 MB/s
------------------------------------------------------------------
        13 |          2 |       4096 |    0.035ms |   1523.66 MB/s
        13 |          2 |      65536 |    0.242ms |   3514.81 MB/s
        13 |          2 |     262144 |    0.964ms |   3534.83 MB/s
------------------------------------------------------------------
        13 |          3 |       4096 |    0.045ms |   1187.89 MB/s
        13 |          3 |      65536 |    0.354ms |   2406.95 MB/s
        13 |          3 |     262144 |    1.457ms |   2339.49 MB/s
------------------------------------------------------------------
        13 |          4 |       4096 |    0.082ms |    648.33 MB/s
        13 |          4 |      65536 |    0.642ms |   1327.69 MB/s
        13 |          4 |     262144 |    2.542ms |   1340.53 MB/s
------------------------------------------------------------------
        14 |          1 |       4096 |    0.028ms |   2030.67 MB/s
        14 |          1 |      65536 |    0.122ms |   7500.05 MB/s
        14 |          1 |     262144 |    0.564ms |   6504.95 MB/s
------------------------------------------------------------------
        14 |          2 |       4096 |    0.039ms |   1471.78 MB/s
        14 |          2 |      65536 |    0.286ms |   3204.86 MB/s
        14 |          2 |     262144 |    1.078ms |   3404.64 MB/s
------------------------------------------------------------------
        14 |          3 |       4096 |    0.065ms |    888.39 MB/s
        14 |          3 |      65536 |    0.519ms |   1766.39 MB/s
        14 |          3 |     262144 |    2.019ms |   1817.82 MB/s
------------------------------------------------------------------
        14 |          4 |       4096 |    0.090ms |    634.96 MB/s
        14 |          4 |      65536 |    0.713ms |   1286.64 MB/s
        14 |          4 |     262144 |    2.817ms |   1302.66 MB/s
------------------------------------------------------------------
        15 |          1 |       4096 |    0.032ms |   1907.47 MB/s
        15 |          1 |      65536 |    0.140ms |   7040.96 MB/s
        15 |          1 |     262144 |    0.618ms |   6365.28 MB/s
------------------------------------------------------------------
        15 |          2 |       4096 |    0.047ms |   1315.35 MB/s
        15 |          2 |      65536 |    0.304ms |   3234.42 MB/s
        15 |          2 |     262144 |    1.130ms |   3481.12 MB/s
------------------------------------------------------------------
        15 |          3 |       4096 |    0.085ms |    726.10 MB/s
        15 |          3 |      65536 |    0.593ms |   1657.45 MB/s
        15 |          3 |     262144 |    2.148ms |   1830.25 MB/s
------------------------------------------------------------------
        15 |          4 |       4096 |    0.120ms |    513.61 MB/s
        15 |          4 |      65536 |    0.738ms |   1332.41 MB/s
        15 |          4 |     262144 |    3.033ms |   1296.38 MB/s
------------------------------------------------------------------
        16 |          1 |       4096 |    0.044ms |   1488.75 MB/s
        16 |          1 |      65536 |    0.134ms |   7848.64 MB/s
        16 |          1 |     262144 |    0.592ms |   7081.85 MB/s
------------------------------------------------------------------
        16 |          2 |       4096 |    0.043ms |   1512.59 MB/s
        16 |          2 |      65536 |    0.295ms |   3558.64 MB/s
        16 |          2 |     262144 |    1.184ms |   3542.97 MB/s
------------------------------------------------------------------
        16 |          3 |       4096 |    0.090ms |    732.23 MB/s
        16 |          3 |      65536 |    0.634ms |   1653.17 MB/s
        16 |          3 |     262144 |    2.428ms |   1727.20 MB/s
------------------------------------------------------------------
        16 |          4 |       4096 |    0.115ms |    571.62 MB/s
        16 |          4 |      65536 |    0.852ms |   1230.77 MB/s
        16 |          4 |     262144 |    3.396ms |   1234.95 MB/s
------------------------------------------------------------------
        17 |          1 |       4096 |    0.033ms |   2102.59 MB/s
        17 |          1 |      65536 |    0.172ms |   6482.07 MB/s
        17 |          1 |     262144 |    0.587ms |   7590.47 MB/s
------------------------------------------------------------------
        17 |          2 |       4096 |    0.040ms |   1741.43 MB/s
        17 |          2 |      65536 |    0.316ms |   3528.31 MB/s
        17 |          2 |     262144 |    1.334ms |   3341.86 MB/s
------------------------------------------------------------------
        17 |          3 |       4096 |    0.081ms |    854.85 MB/s
        17 |          3 |      65536 |    0.642ms |   1735.37 MB/s
        17 |          3 |     262144 |    2.657ms |   1677.29 MB/s
------------------------------------------------------------------
        17 |          4 |       4096 |    0.118ms |    590.97 MB/s
        17 |          4 |      65536 |    0.881ms |   1264.46 MB/s
        17 |          4 |     262144 |    3.677ms |   1211.94 MB/s
------------------------------------------------------------------
        18 |          1 |       4096 |    0.045ms |   1621.06 MB/s
        18 |          1 |      65536 |    0.161ms |   7337.85 MB/s
        18 |          1 |     262144 |    0.694ms |   6802.32 MB/s
------------------------------------------------------------------
        18 |          2 |       4096 |    0.061ms |   1217.39 MB/s
        18 |          2 |      65536 |    0.356ms |   3316.56 MB/s
        18 |          2 |     262144 |    1.457ms |   3239.25 MB/s
------------------------------------------------------------------
        18 |          3 |       4096 |    0.083ms |    885.94 MB/s
        18 |          3 |      65536 |    0.689ms |   1711.45 MB/s
        18 |          3 |     262144 |    2.853ms |   1653.91 MB/s
------------------------------------------------------------------
        18 |          4 |       4096 |    0.110ms |    672.03 MB/s
        18 |          4 |      65536 |    0.905ms |   1303.68 MB/s
        18 |          4 |     262144 |    3.965ms |   1189.92 MB/s
------------------------------------------------------------------
        19 |          1 |       4096 |    0.037ms |   2075.31 MB/s
        19 |          1 |      65536 |    0.217ms |   5737.11 MB/s
        19 |          1 |     262144 |    0.769ms |   6477.97 MB/s
------------------------------------------------------------------
        19 |          2 |       4096 |    0.061ms |   1283.72 MB/s
        19 |          2 |      65536 |    0.375ms |   3324.22 MB/s
        19 |          2 |     262144 |    1.532ms |   3250.41 MB/s
------------------------------------------------------------------
        19 |          3 |       4096 |    0.107ms |    727.70 MB/s
        19 |          3 |      65536 |    0.734ms |   1696.71 MB/s
        19 |          3 |     262144 |    2.993ms |   1664.30 MB/s
------------------------------------------------------------------
        19 |          4 |       4096 |    0.131ms |    595.96 MB/s
        19 |          4 |      65536 |    0.981ms |   1269.12 MB/s
        19 |          4 |     262144 |    4.167ms |   1195.18 MB/s
------------------------------------------------------------------
        20 |          1 |       4096 |    0.052ms |   1560.67 MB/s
        20 |          1 |      65536 |    0.202ms |   6493.22 MB/s
        20 |          1 |     262144 |    0.801ms |   6545.79 MB/s
------------------------------------------------------------------
        20 |          2 |       4096 |    0.054ms |   1506.94 MB/s
        20 |          2 |      65536 |    0.407ms |   3218.66 MB/s
        20 |          2 |     262144 |    1.635ms |   3205.88 MB/s
------------------------------------------------------------------
        20 |          3 |       4096 |    0.105ms |    776.62 MB/s
        20 |          3 |      65536 |    0.758ms |   1728.85 MB/s
        20 |          3 |     262144 |    3.167ms |   1655.57 MB/s
------------------------------------------------------------------
        20 |          4 |       4096 |    0.123ms |    666.05 MB/s
        20 |          4 |      65536 |    1.078ms |   1215.52 MB/s
        20 |          4 |     262144 |    4.415ms |   1187.52 MB/s
------------------------------------------------------------------
```
## Usage

#### Adjust threadpool size and control concurrency
Please see the [`crypto-async`](https://github.com/ronomon/crypto-async#adjust-threadpool-size-and-control-concurrency) module for advice on adjusting threadpool size and controlling concurrency.

#### Encoding Parity Shards
```javascript
var ReedSolomon = require('@ronomon/reed-solomon');

// Specify the number of data shards (<= ReedSolomon.MAX_K):
var k = 6;

// Specify the number of parity shards (<= ReedSolomon.MAX_M):
var m = 3; // Protect against the loss of any 3 data or parity shards.

// Create an encoding context (can be cached and re-used concurrently):
var context = ReedSolomon.create(k, m);

// Specify the size of each shard in bytes (must be a multiple of 8 bytes):
var shardSize = 65536;

// Allocate the data buffer containing all data shards:
var buffer = Buffer.alloc(shardSize * k);

// Specify the offset into the data buffer at which data shards begin:
// This allows you to include a header.
var bufferOffset = 0;

// Specify the size after this offset of all data shards:
// This allows you to include a footer.
var bufferSize = shardSize * k;

// Allocate the parity buffer containing all parity shards:
var parity = Buffer.alloc(shardSize * m);

// Specify the offset into the parity buffer at which parity shards begin:
// This allows you to include a header.
var parityOffset = 0;

// Specify the size after this offset of all parity shards:
// This allows you to include a footer.
var paritySize = shardSize * m;

// Specify the sources, present in buffer or parity (as bit flags):
// We are encoding parity shards, so we mark all data shards as sources.
var sources = 0;
for (var i = 0; i < k; i++) sources |= (1 << i);

// Specify the targets, missing in buffer or parity, which should be encoded:
// We are encoding parity shards, so we mark all parity shards as targets:
var targets = 0;
for (var i = k; i < k + m; i++) targets |= (1 << i);

// Encode all parity shards:
ReedSolomon.encode(
  context,
  sources,
  targets,
  buffer,
  bufferOffset,
  bufferSize,
  parity,
  parityOffset,
  paritySize,
  function(error) {
    if (error) throw error;
    // Parity shards now contain parity data.
  }
);
```

#### Encoding Corrupted Shards
```javascript
// Corrupt first data shard:
buffer[bufferOffset + (shardSize * 0)] = 255;

// Corrupt first parity shard:
parity[parityOffset + (shardSize * 0)] = 255;

// We still have enough parity to corrupt one more shard.

// Specify the targets, missing in buffer or parity, which should be encoded:
var targets = 0;
targets |= (1 << 0); // Data shard at index 0 needs to be encoded.
targets |= (1 << k); // Parity shard at index 6 (k + 0) needs to be encoded.

// Specify the sources, present in buffer or parity:
// We need at least k sources.
// For this example, we assume that a shard is a source if it is not a target.
// An optimization is available here:
// If a shard is not a source or target, it might not be encoded.
// The shard may be encoded if needed to encode other shards, but otherwise not.
var sources = 0;
for (var i = 0; i < k + m; i++) {
  if (targets & (1 << i)) continue;
  sources |= (1 << i);
}

// Encode the corrupted data and parity shards:
ReedSolomon.encode(
  context,
  sources,
  targets,
  buffer,
  bufferOffset,
  bufferSize,
  parity,
  parityOffset,
  paritySize,
  function(error) {
    if (error) throw error;
    // Data shard at index 0 has been repaired.
    // Parity shard at index 6 has been repaired.
  }
);
```

## Tests
`reed-solomon` ships with extensive tests, including a long-running fuzz test.
```
node test.js
```

## Benchmark
```
node benchmark.js
```