4.3.0 • Published 7 months ago

@contrast/stash v4.3.0

Weekly downloads
-
License
SEE LICENSE IN LI...
Repository
-
Last release
7 months ago

@contrast/stash

Node/v8 native module for attaching private data to JavaScript objects.

N.B. The key namespace is flat. To minimize the chance of collisions, it's important to implement namespacing in the string, e.g. @contrast#rasp instead of @contrast or rasp.

Usage

const { Stash } = require('@contrast/stash');

const stash = new Stash('contrast-security##rasp');

const obj = JSON.parse(req.body);

// the following could be `stash.setData(obj, true)` if no additional
// information is required.
stash.setData(obj, { tracked: true });

// meanwhile, back at the sink...
const trackingData = stash.getData(obj);
if (trackingData) {
  // this object is tracked, so check it out.
}

API

The file returns an object implementing the interface defined in index.d.ts.

Building locally

npm run build will build the project for your current OS and architecture. npm run build:dev passes the --debug flag which can be useful during development.

npm run download will pull the most recent build artifacts from GitHub.

Publishing

Simply run npm version and git push && git push --tags. CI will take care of releasing on version-tagged commits.

Supporting Software

Basic leak detection

test/basic.leak.js is a simple leak detection program that verifies the basic operation does not leak memory. Run it once with ITERATIONS set to 1_000_000 then run it again with ITERATIONS set to 2_000_000. The results from two of those runs follows. N.B. each iteration executes on a 1ms interval timer so it's not in a hard loop. This causes the test to take about 17 minutes per million iterations.

cooldown 0 - startup {
  rss: 41754624,
  heapTotal: 270336,
  heapUsed: -360016,
  external: 1992396,
  arrayBuffers: 1993208
}
per iteration { rss: 42, heapTotal: 0, heapUsed: -0, external: 2, arrayBuffers: 2 }

// 2 million iterations

cooldown 0 - startup {
  rss: 40701952,
  heapTotal: 270336,
  heapUsed: -458664,
  external: 1992396,
  arrayBuffers: 1993208
}
per iteration { rss: 20, heapTotal: 0, heapUsed: -0, external: 1, arrayBuffers: 1 }
 */

Benchmarking

The benchmark facility uses simple-bench, a benchmarking tool. The benchmark definition is scripts/simple-bench/benchmark.js and the script to run the benchmarks is scripts/simple-bench/simple-bench.sh. The shell script rebuilds stash with the class implementation included.

Style Guide

Style Guide

See .clang-format.

  • 4 spaces for indentation
  • open curly brace goes on the same line as the statement

Software Archeology

The distringuish repo was the starting point for this repo. While the code is completely different, the scaffolding for prebuildify, the scripts, and the CI are all taken from distringuish.

main.cc also contains a C++ class-based implementation instead of the JavaScript class. It was the first approach and was benchmarked against the second approach, which turned out to be faster. Defining CLASS_BASED during the compilation will cause that implementation to be built in addition to the one we're using. It's kept around because:

  • it's there and fully tested,
  • it's an alternate implementation that uses v8::Private::New() to create keys.
  • v8::Private::New() allows creating anonymous keys while ForApi() (what the second approach uses) does not.
  • it's easy to fold the #ifdef CLASS_BASED with an editor and skip over it.

References

Things hard to deduce from the v8 and node docs and source code.

How to make a persistent copyable

Changing the NAPI_VERSION at the top of main.cc can lead to hard-to-decipher errors when building for versions of node that didn't implement that version.

Standard references

v8 Private docs

Nan Private docs

N-API Doesn't do persistent strings

node-addon-api (the object-wrap.md example was my starting point)

4.3.0

7 months ago

4.2.2

1 year ago

4.2.1

1 year ago