11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ciconst dc = require('diagnostics_channel');
61cb0ef41Sopenharmony_ciconst { AsyncLocalStorage } = require('async_hooks');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_cilet n = 0;
91cb0ef41Sopenharmony_ciconst thisArg = new Date();
101cb0ef41Sopenharmony_ciconst inputs = [
111cb0ef41Sopenharmony_ci  { foo: 'bar' },
121cb0ef41Sopenharmony_ci  { baz: 'buz' },
131cb0ef41Sopenharmony_ci];
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciconst channel = dc.channel('test');
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci// Bind a storage directly to published data
181cb0ef41Sopenharmony_ciconst store1 = new AsyncLocalStorage();
191cb0ef41Sopenharmony_cichannel.bindStore(store1);
201cb0ef41Sopenharmony_cilet store1bound = true;
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci// Bind a store with transformation of published data
231cb0ef41Sopenharmony_ciconst store2 = new AsyncLocalStorage();
241cb0ef41Sopenharmony_cichannel.bindStore(store2, common.mustCall((data) => {
251cb0ef41Sopenharmony_ci  assert.strictEqual(data, inputs[n]);
261cb0ef41Sopenharmony_ci  return { data };
271cb0ef41Sopenharmony_ci}, 4));
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci// Regular subscribers should see publishes from runStores calls
301cb0ef41Sopenharmony_cichannel.subscribe(common.mustCall((data) => {
311cb0ef41Sopenharmony_ci  if (store1bound) {
321cb0ef41Sopenharmony_ci    assert.deepStrictEqual(data, store1.getStore());
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci  assert.deepStrictEqual({ data }, store2.getStore());
351cb0ef41Sopenharmony_ci  assert.strictEqual(data, inputs[n]);
361cb0ef41Sopenharmony_ci}, 4));
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci// Verify stores are empty before run
391cb0ef41Sopenharmony_ciassert.strictEqual(store1.getStore(), undefined);
401cb0ef41Sopenharmony_ciassert.strictEqual(store2.getStore(), undefined);
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cichannel.runStores(inputs[n], common.mustCall(function(a, b) {
431cb0ef41Sopenharmony_ci  // Verify this and argument forwarding
441cb0ef41Sopenharmony_ci  assert.strictEqual(this, thisArg);
451cb0ef41Sopenharmony_ci  assert.strictEqual(a, 1);
461cb0ef41Sopenharmony_ci  assert.strictEqual(b, 2);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  // Verify store 1 state matches input
491cb0ef41Sopenharmony_ci  assert.strictEqual(store1.getStore(), inputs[n]);
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  // Verify store 2 state has expected transformation
521cb0ef41Sopenharmony_ci  assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // Should support nested contexts
551cb0ef41Sopenharmony_ci  n++;
561cb0ef41Sopenharmony_ci  channel.runStores(inputs[n], common.mustCall(function() {
571cb0ef41Sopenharmony_ci    // Verify this and argument forwarding
581cb0ef41Sopenharmony_ci    assert.strictEqual(this, undefined);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci    // Verify store 1 state matches input
611cb0ef41Sopenharmony_ci    assert.strictEqual(store1.getStore(), inputs[n]);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci    // Verify store 2 state has expected transformation
641cb0ef41Sopenharmony_ci    assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
651cb0ef41Sopenharmony_ci  }));
661cb0ef41Sopenharmony_ci  n--;
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  // Verify store 1 state matches input
691cb0ef41Sopenharmony_ci  assert.strictEqual(store1.getStore(), inputs[n]);
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  // Verify store 2 state has expected transformation
721cb0ef41Sopenharmony_ci  assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
731cb0ef41Sopenharmony_ci}), thisArg, 1, 2);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci// Verify stores are empty after run
761cb0ef41Sopenharmony_ciassert.strictEqual(store1.getStore(), undefined);
771cb0ef41Sopenharmony_ciassert.strictEqual(store2.getStore(), undefined);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci// Verify unbinding works
801cb0ef41Sopenharmony_ciassert.ok(channel.unbindStore(store1));
811cb0ef41Sopenharmony_cistore1bound = false;
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci// Verify unbinding a store that is not bound returns false
841cb0ef41Sopenharmony_ciassert.ok(!channel.unbindStore(store1));
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_cin++;
871cb0ef41Sopenharmony_cichannel.runStores(inputs[n], common.mustCall(() => {
881cb0ef41Sopenharmony_ci  // Verify after unbinding store 1 will remain undefined
891cb0ef41Sopenharmony_ci  assert.strictEqual(store1.getStore(), undefined);
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  // Verify still bound store 2 receives expected data
921cb0ef41Sopenharmony_ci  assert.deepStrictEqual(store2.getStore(), { data: inputs[n] });
931cb0ef41Sopenharmony_ci}));
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci// Contain transformer errors and emit on next tick
961cb0ef41Sopenharmony_ciconst fail = new Error('fail');
971cb0ef41Sopenharmony_cichannel.bindStore(store1, () => {
981cb0ef41Sopenharmony_ci  throw fail;
991cb0ef41Sopenharmony_ci});
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_cilet calledRunStores = false;
1021cb0ef41Sopenharmony_ciprocess.once('uncaughtException', common.mustCall((err) => {
1031cb0ef41Sopenharmony_ci  assert.strictEqual(calledRunStores, true);
1041cb0ef41Sopenharmony_ci  assert.strictEqual(err, fail);
1051cb0ef41Sopenharmony_ci}));
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_cichannel.runStores(inputs[n], common.mustCall());
1081cb0ef41Sopenharmony_cicalledRunStores = true;
109