• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const common = require('../common');
4const assert = require('assert');
5const dc = require('diagnostics_channel');
6const { AsyncLocalStorage } = require('async_hooks');
7
8let n = 0;
9const thisArg = new Date();
10const inputs = [
11  { foo: 'bar' },
12  { baz: 'buz' },
13];
14
15const channel = dc.channel('test');
16
17// Bind a storage directly to published data
18const store1 = new AsyncLocalStorage();
19channel.bindStore(store1);
20let store1bound = true;
21
22// Bind a store with transformation of published data
23const store2 = new AsyncLocalStorage();
24channel.bindStore(store2, common.mustCall((data) => {
25  assert.strictEqual(data, inputs[n]);
26  return { data };
27}, 4));
28
29// Regular subscribers should see publishes from runStores calls
30channel.subscribe(common.mustCall((data) => {
31  if (store1bound) {
32    assert.deepStrictEqual(data, store1.getStore());
33  }
34  assert.deepStrictEqual({ data }, store2.getStore());
35  assert.strictEqual(data, inputs[n]);
36}, 4));
37
38// Verify stores are empty before run
39assert.strictEqual(store1.getStore(), undefined);
40assert.strictEqual(store2.getStore(), undefined);
41
42channel.runStores(inputs[n], common.mustCall(function(a, b) {
43  // Verify this and argument forwarding
44  assert.strictEqual(this, thisArg);
45  assert.strictEqual(a, 1);
46  assert.strictEqual(b, 2);
47
48  // Verify store 1 state matches input
49  assert.strictEqual(store1.getStore(), inputs[n]);
50
51  // Verify store 2 state has expected transformation
52  assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
53
54  // Should support nested contexts
55  n++;
56  channel.runStores(inputs[n], common.mustCall(function() {
57    // Verify this and argument forwarding
58    assert.strictEqual(this, undefined);
59
60    // Verify store 1 state matches input
61    assert.strictEqual(store1.getStore(), inputs[n]);
62
63    // Verify store 2 state has expected transformation
64    assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
65  }));
66  n--;
67
68  // Verify store 1 state matches input
69  assert.strictEqual(store1.getStore(), inputs[n]);
70
71  // Verify store 2 state has expected transformation
72  assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
73}), thisArg, 1, 2);
74
75// Verify stores are empty after run
76assert.strictEqual(store1.getStore(), undefined);
77assert.strictEqual(store2.getStore(), undefined);
78
79// Verify unbinding works
80assert.ok(channel.unbindStore(store1));
81store1bound = false;
82
83// Verify unbinding a store that is not bound returns false
84assert.ok(!channel.unbindStore(store1));
85
86n++;
87channel.runStores(inputs[n], common.mustCall(() => {
88  // Verify after unbinding store 1 will remain undefined
89  assert.strictEqual(store1.getStore(), undefined);
90
91  // Verify still bound store 2 receives expected data
92  assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
93}));
94
95// Contain transformer errors and emit on next tick
96const fail = new Error('fail');
97channel.bindStore(store1, () => {
98  throw fail;
99});
100
101let calledRunStores = false;
102process.once('uncaughtException', common.mustCall((err) => {
103  assert.strictEqual(calledRunStores, true);
104  assert.strictEqual(err, fail);
105}));
106
107channel.runStores(inputs[n], common.mustCall());
108calledRunStores = true;
109