JSlang.dev

JavaScript Deep Dives with Wolfram. Since 2015
Inclusive, Test-Driven, Spec-Focused, Collaborative.

June 03, 2021
TestsSource
WeakMap

Source Code

The source code we wrote during the event.

import {strict as assert} from 'assert';
import 'expose-gc';

describe('WeakMap - intro', () => {
  it('is a function', () => {
    assert.equal(typeof WeakMap, 'function');
  });

  xit('removing the last ref to the key, removes the entry from the WeakMap', () => {
    // WE can NOT verify that a gc'ed key is NOT in the WeakMap anymore,
    // we just have no reference to it
    let a = {};
    const map = new WeakMap([
      [a, 'the value of `a`'],
    ]);
    a = undefined;
    global.gc(); // requires `import 'expose-gc';`
    assert.equal(map.has(a), false); // <<<=== undefined (`a`) is not the actual key we used to add the element to the WeakMap
  });
  it('two refs to one object, remove one ref, with explicit gc THEN its still accessible', () => {
    let a = {};
    let b = a;
    const map = new WeakMap([
      [a, 'the value of `a`'],
    ]);
    a = null;
    global.gc(); // requires `import 'expose-gc';`
    assert.equal(map.get(b), 'the value of `a`');
    assert.equal(map.has(a), false);
  });
  it('null as a key throws a TypeError when creating the WeakMap (because its not an object)', () => {
    assert.throws(() => {
      const map = new WeakMap([
        [null, 'null'],
      ]);
    }, TypeError);
  });

  it('the key is still valid AFTER you added a property to the key', () => {
    const key = {};
    const map = new WeakMap([[key, 'keys value']]);
    key.x = 'ax or X';
    assert.equal(map.get(key), 'keys value');
  });
  it('`delete` a nested property with an external ref, keeps the value in the WeakMap', () => {
    const a = {key: {}};
    const b = a.key;
    const map = new WeakMap([[a.key, 'a.key']]);
    delete a.key;
    assert.equal(map.get(b), 'a.key');
  });

  it('using a value of WeakMap A as key for WeakMap B works', () => {
    const a = {};
    const mapA = new WeakMap([[a, {}]]);
    const mapB = new WeakMap([[mapA.get(a), 'the wormhole']]);
    assert.equal(mapB.get(mapA.get(a)), 'the wormhole');
  });

  it('`Number()` returns a number', () => {
    assert.equal(typeof Number(5), 'number');
  });
  it('`new Number()` returns an object', () => {
    assert.equal(typeof new Number(5), 'object');
  });
  it('`new Number` does NOT strictly equal `new Number`', () => {
    assert.notEqual(new Number(5), new Number(5));
  });
  it('`new Number` does NOT equal `new Number`', () => {
    const compared = new Number(5) == new Number(5);
    assert.equal(compared, false);
  });

  it('a reference is stable inside a timeout callback function', async () => {
    let a = {};
    const map = new WeakMap([[a, 'any value']]);
    const p = new Promise((resolve) => {
      setTimeout(() => {
        const b = a;
        a = {};
        resolve(b);
      }, 100);
    });
    const slowB = await p;
    assert.equal(map.get(slowB), 'any value');
  });
});