PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/csp/csp.operations.js

https://gitlab.com/jjogle/blog
JavaScript | 1096 lines | 990 code | 74 blank | 32 comment | 115 complexity | 84863500a5e1fa0240cccf2b033b42bd MD5 | raw file
Possible License(s): BSD-3-Clause
  1. "use strict";
  2. var mapcat = regeneratorRuntime.mark(function mapcat(f, src, dst) {
  3. var value, seq, length, i;
  4. return regeneratorRuntime.wrap(function mapcat$(context$1$0) {
  5. while (true) switch (context$1$0.prev = context$1$0.next) {
  6. case 0:
  7. if (!true) {
  8. context$1$0.next = 22;
  9. break;
  10. }
  11. context$1$0.next = 3;
  12. return take(src);
  13. case 3: value = context$1$0.sent;
  14. if (!(value === CLOSED)) {
  15. context$1$0.next = 9;
  16. break;
  17. }
  18. dst.close();
  19. return context$1$0.abrupt("break", 22);
  20. case 9: seq = f(value);
  21. length = seq.length;
  22. i = 0;
  23. case 12:
  24. if (!(i < length)) {
  25. context$1$0.next = 18;
  26. break;
  27. }
  28. context$1$0.next = 15;
  29. return put(dst, seq[i]);
  30. case 15: i++;
  31. context$1$0.next = 12;
  32. break;
  33. case 18:
  34. if (!dst.is_closed()) {
  35. context$1$0.next = 20;
  36. break;
  37. }
  38. return context$1$0.abrupt("break", 22);
  39. case 20: context$1$0.next = 0;
  40. break;
  41. case 22:
  42. case "end": return context$1$0.stop();
  43. }
  44. }, mapcat, this);
  45. });
  46. var Box = require("./impl/channels").Box;
  47. var csp = require("./csp.core"), go = csp.go, spawn = csp.spawn, take = csp.take, put = csp.put, takeAsync = csp.takeAsync, putAsync = csp.putAsync, alts = csp.alts, chan = csp.chan, CLOSED = csp.CLOSED;
  48. function mapFrom(f, ch) {
  49. return {
  50. is_closed: function () {
  51. return ch.is_closed();
  52. },
  53. close: function () {
  54. ch.close();
  55. },
  56. _put: function (value, handler) {
  57. return ch._put(value, handler);
  58. },
  59. _take: function (handler) {
  60. var result = ch._take({
  61. is_active: function () {
  62. return handler.is_active();
  63. },
  64. commit: function () {
  65. var take_cb = handler.commit();
  66. return function (value) {
  67. return take_cb(value === CLOSED ? CLOSED : f(value));
  68. };
  69. }
  70. });
  71. if (result) {
  72. var value = result.value;
  73. return new Box(value === CLOSED ? CLOSED : f(value));
  74. } else {
  75. return null;
  76. }
  77. }
  78. };
  79. }
  80. function mapInto(f, ch) {
  81. return {
  82. is_closed: function () {
  83. return ch.is_closed();
  84. },
  85. close: function () {
  86. ch.close();
  87. },
  88. _put: function (value, handler) {
  89. return ch._put(f(value), handler);
  90. },
  91. _take: function (handler) {
  92. return ch._take(handler);
  93. }
  94. };
  95. }
  96. function filterFrom(p, ch, bufferOrN) {
  97. var out = chan(bufferOrN);
  98. go(regeneratorRuntime.mark(function callee$1$0() {
  99. var value;
  100. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  101. while (true) switch (context$2$0.prev = context$2$0.next) {
  102. case 0:
  103. if (!true) {
  104. context$2$0.next = 12;
  105. break;
  106. }
  107. context$2$0.next = 3;
  108. return take(ch);
  109. case 3: value = context$2$0.sent;
  110. if (!(value === CLOSED)) {
  111. context$2$0.next = 7;
  112. break;
  113. }
  114. out.close();
  115. return context$2$0.abrupt("break", 12);
  116. case 7:
  117. if (!p(value)) {
  118. context$2$0.next = 10;
  119. break;
  120. }
  121. context$2$0.next = 10;
  122. return put(out, value);
  123. case 10: context$2$0.next = 0;
  124. break;
  125. case 12:
  126. case "end": return context$2$0.stop();
  127. }
  128. }, callee$1$0, this);
  129. }));
  130. return out;
  131. }
  132. function filterInto(p, ch) {
  133. return {
  134. is_closed: function () {
  135. return ch.is_closed();
  136. },
  137. close: function () {
  138. ch.close();
  139. },
  140. _put: function (value, handler) {
  141. if (p(value)) {
  142. return ch._put(value, handler);
  143. } else {
  144. return new Box(!ch.is_closed());
  145. }
  146. },
  147. _take: function (handler) {
  148. return ch._take(handler);
  149. }
  150. };
  151. }
  152. function removeFrom(p, ch) {
  153. return filterFrom(function (value) {
  154. return !p(value);
  155. }, ch);
  156. }
  157. function removeInto(p, ch) {
  158. return filterInto(function (value) {
  159. return !p(value);
  160. }, ch);
  161. }
  162. function mapcatFrom(f, ch, bufferOrN) {
  163. var out = chan(bufferOrN);
  164. spawn(mapcat(f, ch, out));
  165. return out;
  166. }
  167. function mapcatInto(f, ch, bufferOrN) {
  168. var src = chan(bufferOrN);
  169. spawn(mapcat(f, src, ch));
  170. return src;
  171. }
  172. function pipe(src, dst, keepOpen) {
  173. go(regeneratorRuntime.mark(function callee$1$0() {
  174. var value;
  175. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  176. while (true) switch (context$2$0.prev = context$2$0.next) {
  177. case 0:
  178. if (!true) {
  179. context$2$0.next = 13;
  180. break;
  181. }
  182. context$2$0.next = 3;
  183. return take(src);
  184. case 3: value = context$2$0.sent;
  185. if (!(value === CLOSED)) {
  186. context$2$0.next = 7;
  187. break;
  188. }
  189. if (!keepOpen) {
  190. dst.close();
  191. }
  192. return context$2$0.abrupt("break", 13);
  193. case 7: context$2$0.next = 9;
  194. return put(dst, value);
  195. case 9:
  196. if (context$2$0.sent) {
  197. context$2$0.next = 11;
  198. break;
  199. }
  200. return context$2$0.abrupt("break", 13);
  201. case 11: context$2$0.next = 0;
  202. break;
  203. case 13:
  204. case "end": return context$2$0.stop();
  205. }
  206. }, callee$1$0, this);
  207. }));
  208. return dst;
  209. }
  210. function split(p, ch, trueBufferOrN, falseBufferOrN) {
  211. var tch = chan(trueBufferOrN);
  212. var fch = chan(falseBufferOrN);
  213. go(regeneratorRuntime.mark(function callee$1$0() {
  214. var value;
  215. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  216. while (true) switch (context$2$0.prev = context$2$0.next) {
  217. case 0:
  218. if (!true) {
  219. context$2$0.next = 12;
  220. break;
  221. }
  222. context$2$0.next = 3;
  223. return take(ch);
  224. case 3: value = context$2$0.sent;
  225. if (!(value === CLOSED)) {
  226. context$2$0.next = 8;
  227. break;
  228. }
  229. tch.close();
  230. fch.close();
  231. return context$2$0.abrupt("break", 12);
  232. case 8: context$2$0.next = 10;
  233. return put(p(value) ? tch : fch, value);
  234. case 10: context$2$0.next = 0;
  235. break;
  236. case 12:
  237. case "end": return context$2$0.stop();
  238. }
  239. }, callee$1$0, this);
  240. }));
  241. return [tch, fch];
  242. }
  243. function reduce(f, init, ch) {
  244. return go(regeneratorRuntime.mark(function callee$1$0() {
  245. var result, value;
  246. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  247. while (true) switch (context$2$0.prev = context$2$0.next) {
  248. case 0: result = init;
  249. case 1:
  250. if (!true) {
  251. context$2$0.next = 12;
  252. break;
  253. }
  254. context$2$0.next = 4;
  255. return take(ch);
  256. case 4: value = context$2$0.sent;
  257. if (!(value === CLOSED)) {
  258. context$2$0.next = 9;
  259. break;
  260. }
  261. return context$2$0.abrupt("return", result);
  262. case 9:
  263. result = f(result, value);
  264. case 10: context$2$0.next = 1;
  265. break;
  266. case 12:
  267. case "end": return context$2$0.stop();
  268. }
  269. }, callee$1$0, this);
  270. }), [], true);
  271. }
  272. function onto(ch, coll, keepOpen) {
  273. return go(regeneratorRuntime.mark(function callee$1$0() {
  274. var length, i;
  275. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  276. while (true) switch (context$2$0.prev = context$2$0.next) {
  277. case 0: length = coll.length;
  278. i = 0;
  279. case 2:
  280. if (!(i < length)) {
  281. context$2$0.next = 8;
  282. break;
  283. }
  284. context$2$0.next = 5;
  285. return put(ch, coll[i]);
  286. case 5: i++;
  287. context$2$0.next = 2;
  288. break;
  289. case 8:
  290. if (!keepOpen) {
  291. ch.close();
  292. }
  293. case 9:
  294. case "end": return context$2$0.stop();
  295. }
  296. }, callee$1$0, this);
  297. }));
  298. }
  299. // TODO: Bounded?
  300. function fromColl(coll) {
  301. var ch = chan(coll.length);
  302. onto(ch, coll);
  303. return ch;
  304. }
  305. function map(f, chs, bufferOrN) {
  306. var out = chan(bufferOrN);
  307. var length = chs.length;
  308. // Array holding 1 round of values
  309. var values = new Array(length);
  310. // TODO: Not sure why we need a size-1 buffer here
  311. var dchan = chan(1);
  312. // How many more items this round
  313. var dcount;
  314. // put callbacks for each channel
  315. var dcallbacks = new Array(length);
  316. for (var i = 0; i < length; i++) {
  317. dcallbacks[i] = (function (i) {
  318. return function (value) {
  319. values[i] = value;
  320. dcount--;
  321. if (dcount === 0) {
  322. putAsync(dchan, values.slice(0));
  323. }
  324. };
  325. }(i));
  326. }
  327. go(regeneratorRuntime.mark(function callee$1$0() {
  328. var i, values;
  329. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  330. while (true) switch (context$2$0.prev = context$2$0.next) {
  331. case 0:
  332. if (!true) {
  333. context$2$0.next = 18;
  334. break;
  335. }
  336. dcount = length;
  337. // We could just launch n goroutines here, but for effciency we
  338. // don't
  339. for (i = 0; i < length; i++) {
  340. try {
  341. takeAsync(chs[i], dcallbacks[i]);
  342. } catch (e) {
  343. // FIX: Hmm why catching here?
  344. dcount--;
  345. }
  346. }
  347. context$2$0.next = 5;
  348. return take(dchan);
  349. case 5: values = context$2$0.sent;
  350. i = 0;
  351. case 7:
  352. if (!(i < length)) {
  353. context$2$0.next = 14;
  354. break;
  355. }
  356. if (!(values[i] === CLOSED)) {
  357. context$2$0.next = 11;
  358. break;
  359. }
  360. out.close();
  361. return context$2$0.abrupt("return");
  362. case 11: i++;
  363. context$2$0.next = 7;
  364. break;
  365. case 14: context$2$0.next = 16;
  366. return put(out, f.apply(null, values));
  367. case 16: context$2$0.next = 0;
  368. break;
  369. case 18:
  370. case "end": return context$2$0.stop();
  371. }
  372. }, callee$1$0, this);
  373. }));
  374. return out;
  375. }
  376. function merge(chs, bufferOrN) {
  377. var out = chan(bufferOrN);
  378. var actives = chs.slice(0);
  379. go(regeneratorRuntime.mark(function callee$1$0() {
  380. var r, value, i;
  381. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  382. while (true) switch (context$2$0.prev = context$2$0.next) {
  383. case 0:
  384. if (!true) {
  385. context$2$0.next = 15;
  386. break;
  387. }
  388. if (!(actives.length === 0)) {
  389. context$2$0.next = 3;
  390. break;
  391. }
  392. return context$2$0.abrupt("break", 15);
  393. case 3: context$2$0.next = 5;
  394. return alts(actives);
  395. case 5: r = context$2$0.sent;
  396. value = r.value;
  397. if (!(value === CLOSED)) {
  398. context$2$0.next = 11;
  399. break;
  400. }
  401. i = actives.indexOf(r.channel);
  402. actives.splice(i, 1);
  403. return context$2$0.abrupt("continue", 0);
  404. case 11: context$2$0.next = 13;
  405. return put(out, value);
  406. case 13: context$2$0.next = 0;
  407. break;
  408. case 15:
  409. out.close();
  410. case 16:
  411. case "end": return context$2$0.stop();
  412. }
  413. }, callee$1$0, this);
  414. }));
  415. return out;
  416. }
  417. function into(coll, ch) {
  418. var result = coll.slice(0);
  419. return reduce(function (result, item) {
  420. result.push(item);
  421. return result;
  422. }, result, ch);
  423. }
  424. function takeN(n, ch, bufferOrN) {
  425. var out = chan(bufferOrN);
  426. go(regeneratorRuntime.mark(function callee$1$0() {
  427. var i, value;
  428. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  429. while (true) switch (context$2$0.prev = context$2$0.next) {
  430. case 0: i = 0;
  431. case 1:
  432. if (!(i < n)) {
  433. context$2$0.next = 12;
  434. break;
  435. }
  436. context$2$0.next = 4;
  437. return take(ch);
  438. case 4: value = context$2$0.sent;
  439. if (!(value === CLOSED)) {
  440. context$2$0.next = 7;
  441. break;
  442. }
  443. return context$2$0.abrupt("break", 12);
  444. case 7: context$2$0.next = 9;
  445. return put(out, value);
  446. case 9: i++;
  447. context$2$0.next = 1;
  448. break;
  449. case 12:
  450. out.close();
  451. case 13:
  452. case "end": return context$2$0.stop();
  453. }
  454. }, callee$1$0, this);
  455. }));
  456. return out;
  457. }
  458. var NOTHING = {};
  459. function unique(ch, bufferOrN) {
  460. var out = chan(bufferOrN);
  461. var last = NOTHING;
  462. go(regeneratorRuntime.mark(function callee$1$0() {
  463. var value;
  464. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  465. while (true) switch (context$2$0.prev = context$2$0.next) {
  466. case 0:
  467. if (!true) {
  468. context$2$0.next = 13;
  469. break;
  470. }
  471. context$2$0.next = 3;
  472. return take(ch);
  473. case 3: value = context$2$0.sent;
  474. if (!(value === CLOSED)) {
  475. context$2$0.next = 6;
  476. break;
  477. }
  478. return context$2$0.abrupt("break", 13);
  479. case 6:
  480. if (!(value === last)) {
  481. context$2$0.next = 8;
  482. break;
  483. }
  484. return context$2$0.abrupt("continue", 0);
  485. case 8:
  486. last = value;
  487. context$2$0.next = 11;
  488. return put(out, value);
  489. case 11: context$2$0.next = 0;
  490. break;
  491. case 13:
  492. out.close();
  493. case 14:
  494. case "end": return context$2$0.stop();
  495. }
  496. }, callee$1$0, this);
  497. }));
  498. return out;
  499. }
  500. function partitionBy(f, ch, bufferOrN) {
  501. var out = chan(bufferOrN);
  502. var part = [];
  503. var last = NOTHING;
  504. go(regeneratorRuntime.mark(function callee$1$0() {
  505. var value, newItem;
  506. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  507. while (true) switch (context$2$0.prev = context$2$0.next) {
  508. case 0:
  509. if (!true) {
  510. context$2$0.next = 23;
  511. break;
  512. }
  513. context$2$0.next = 3;
  514. return take(ch);
  515. case 3: value = context$2$0.sent;
  516. if (!(value === CLOSED)) {
  517. context$2$0.next = 12;
  518. break;
  519. }
  520. if (!(part.length > 0)) {
  521. context$2$0.next = 8;
  522. break;
  523. }
  524. context$2$0.next = 8;
  525. return put(out, part);
  526. case 8:
  527. out.close();
  528. return context$2$0.abrupt("break", 23);
  529. case 12: newItem = f(value);
  530. if (!(newItem === last || last === NOTHING)) {
  531. context$2$0.next = 17;
  532. break;
  533. }
  534. part.push(value);
  535. context$2$0.next = 20;
  536. break;
  537. case 17: context$2$0.next = 19;
  538. return put(out, part);
  539. case 19:
  540. part = [value];
  541. case 20:
  542. last = newItem;
  543. case 21: context$2$0.next = 0;
  544. break;
  545. case 23:
  546. case "end": return context$2$0.stop();
  547. }
  548. }, callee$1$0, this);
  549. }));
  550. return out;
  551. }
  552. function partition(n, ch, bufferOrN) {
  553. var out = chan(bufferOrN);
  554. go(regeneratorRuntime.mark(function callee$1$0() {
  555. var part, i, value;
  556. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  557. while (true) switch (context$2$0.prev = context$2$0.next) {
  558. case 0:
  559. if (!true) {
  560. context$2$0.next = 21;
  561. break;
  562. }
  563. part = new Array(n);
  564. i = 0;
  565. case 3:
  566. if (!(i < n)) {
  567. context$2$0.next = 17;
  568. break;
  569. }
  570. context$2$0.next = 6;
  571. return take(ch);
  572. case 6: value = context$2$0.sent;
  573. if (!(value === CLOSED)) {
  574. context$2$0.next = 13;
  575. break;
  576. }
  577. if (!(i > 0)) {
  578. context$2$0.next = 11;
  579. break;
  580. }
  581. context$2$0.next = 11;
  582. return put(out, part.slice(0, i));
  583. case 11:
  584. out.close();
  585. return context$2$0.abrupt("return");
  586. case 13:
  587. part[i] = value;
  588. case 14: i++;
  589. context$2$0.next = 3;
  590. break;
  591. case 17: context$2$0.next = 19;
  592. return put(out, part);
  593. case 19: context$2$0.next = 0;
  594. break;
  595. case 21:
  596. case "end": return context$2$0.stop();
  597. }
  598. }, callee$1$0, this);
  599. }));
  600. return out;
  601. }
  602. // For channel identification
  603. var genId = (function () {
  604. var i = 0;
  605. return function () {
  606. i++;
  607. return "" + i;
  608. };
  609. })();
  610. var ID_ATTR = "__csp_channel_id";
  611. // TODO: Do we need to check with hasOwnProperty?
  612. function len(obj) {
  613. var count = 0;
  614. for (var p in obj) {
  615. count++;
  616. }
  617. return count;
  618. }
  619. function chanId(ch) {
  620. var id = ch[ID_ATTR];
  621. if (id === undefined) {
  622. id = ch[ID_ATTR] = genId();
  623. }
  624. return id;
  625. }
  626. var Mult = function (ch) {
  627. this.taps = {};
  628. this.ch = ch;
  629. };
  630. var Tap = function (channel, keepOpen) {
  631. this.channel = channel;
  632. this.keepOpen = keepOpen;
  633. };
  634. Mult.prototype.muxch = function () {
  635. return this.ch;
  636. };
  637. Mult.prototype.tap = function (ch, keepOpen) {
  638. var id = chanId(ch);
  639. this.taps[id] = new Tap(ch, keepOpen);
  640. };
  641. Mult.prototype.untap = function (ch) {
  642. delete this.taps[chanId(ch)];
  643. };
  644. Mult.prototype.untapAll = function () {
  645. this.taps = {};
  646. };
  647. function mult(ch) {
  648. var m = new Mult(ch);
  649. var dchan = chan(1);
  650. var dcount;
  651. function makeDoneCallback(tap) {
  652. return function (stillOpen) {
  653. dcount--;
  654. if (dcount === 0) {
  655. putAsync(dchan, true);
  656. }
  657. if (!stillOpen) {
  658. m.untap(tap.channel);
  659. }
  660. };
  661. }
  662. go(regeneratorRuntime.mark(function callee$1$0() {
  663. var value, id, t, taps, initDcount;
  664. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  665. while (true) switch (context$2$0.prev = context$2$0.next) {
  666. case 0:
  667. if (!true) {
  668. context$2$0.next = 17;
  669. break;
  670. }
  671. context$2$0.next = 3;
  672. return take(ch);
  673. case 3: value = context$2$0.sent;
  674. taps = m.taps;
  675. if (!(value === CLOSED)) {
  676. context$2$0.next = 9;
  677. break;
  678. }
  679. for (id in taps) {
  680. t = taps[id];
  681. if (!t.keepOpen) {
  682. t.channel.close();
  683. }
  684. }
  685. // TODO: Is this necessary?
  686. m.untapAll();
  687. return context$2$0.abrupt("break", 17);
  688. case 9:
  689. dcount = len(taps);
  690. initDcount = dcount;
  691. // Put value on tapping channels...
  692. for (id in taps) {
  693. t = taps[id];
  694. putAsync(t.channel, value, makeDoneCallback(t));
  695. }
  696. if (!(initDcount > 0)) {
  697. context$2$0.next = 15;
  698. break;
  699. }
  700. context$2$0.next = 15;
  701. return take(dchan);
  702. case 15: context$2$0.next = 0;
  703. break;
  704. case 17:
  705. case "end": return context$2$0.stop();
  706. }
  707. }, callee$1$0, this);
  708. }));
  709. return m;
  710. }
  711. mult.tap = function tap(m, ch, keepOpen) {
  712. m.tap(ch, keepOpen);
  713. return ch;
  714. };
  715. mult.untap = function untap(m, ch) {
  716. m.untap(ch);
  717. };
  718. mult.untapAll = function untapAll(m) {
  719. m.untapAll();
  720. };
  721. var Mix = function (ch) {
  722. this.ch = ch;
  723. this.stateMap = {};
  724. this.change = chan();
  725. this.soloMode = mix.MUTE;
  726. };
  727. Mix.prototype._changed = function () {
  728. putAsync(this.change, true);
  729. };
  730. Mix.prototype._getAllState = function () {
  731. var allState = {};
  732. var stateMap = this.stateMap;
  733. var solos = [];
  734. var mutes = [];
  735. var pauses = [];
  736. var reads;
  737. for (var id in stateMap) {
  738. var chanData = stateMap[id];
  739. var state = chanData.state;
  740. var channel = chanData.channel;
  741. if (state[mix.SOLO]) {
  742. solos.push(channel);
  743. }
  744. // TODO
  745. if (state[mix.MUTE]) {
  746. mutes.push(channel);
  747. }
  748. if (state[mix.PAUSE]) {
  749. pauses.push(channel);
  750. }
  751. }
  752. var i, n;
  753. if (this.soloMode === mix.PAUSE && solos.length > 0) {
  754. n = solos.length;
  755. reads = new Array(n + 1);
  756. for (i = 0; i < n; i++) {
  757. reads[i] = solos[i];
  758. }
  759. reads[n] = this.change;
  760. } else {
  761. reads = [];
  762. for (id in stateMap) {
  763. chanData = stateMap[id];
  764. channel = chanData.channel;
  765. if (pauses.indexOf(channel) < 0) {
  766. reads.push(channel);
  767. }
  768. }
  769. reads.push(this.change);
  770. }
  771. return {
  772. solos: solos,
  773. mutes: mutes,
  774. reads: reads
  775. };
  776. };
  777. Mix.prototype.admix = function (ch) {
  778. this.stateMap[chanId(ch)] = {
  779. channel: ch,
  780. state: {}
  781. };
  782. this._changed();
  783. };
  784. Mix.prototype.unmix = function (ch) {
  785. delete this.stateMap[chanId(ch)];
  786. this._changed();
  787. };
  788. Mix.prototype.unmixAll = function () {
  789. this.stateMap = {};
  790. this._changed();
  791. };
  792. Mix.prototype.toggle = function (updateStateList) {
  793. // [[ch1, {}], [ch2, {solo: true}]];
  794. var length = updateStateList.length;
  795. for (var i = 0; i < length; i++) {
  796. var ch = updateStateList[i][0];
  797. var id = chanId(ch);
  798. var updateState = updateStateList[i][1];
  799. var chanData = this.stateMap[id];
  800. if (!chanData) {
  801. chanData = this.stateMap[id] = {
  802. channel: ch,
  803. state: {}
  804. };
  805. }
  806. for (var mode in updateState) {
  807. chanData.state[mode] = updateState[mode];
  808. }
  809. }
  810. this._changed();
  811. };
  812. Mix.prototype.setSoloMode = function (mode) {
  813. if (VALID_SOLO_MODES.indexOf(mode) < 0) {
  814. throw new Error("Mode must be one of: ", VALID_SOLO_MODES.join(", "));
  815. }
  816. this.soloMode = mode;
  817. this._changed();
  818. };
  819. function mix(out) {
  820. var m = new Mix(out);
  821. go(regeneratorRuntime.mark(function callee$1$0() {
  822. var state, result, value, channel, solos, stillOpen;
  823. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  824. while (true) switch (context$2$0.prev = context$2$0.next) {
  825. case 0: state = m._getAllState();
  826. case 1:
  827. if (!true) {
  828. context$2$0.next = 23;
  829. break;
  830. }
  831. context$2$0.next = 4;
  832. return alts(state.reads);
  833. case 4: result = context$2$0.sent;
  834. value = result.value;
  835. channel = result.channel;
  836. if (!(value === CLOSED)) {
  837. context$2$0.next = 11;
  838. break;
  839. }
  840. delete m.stateMap[chanId(channel)];
  841. state = m._getAllState();
  842. return context$2$0.abrupt("continue", 1);
  843. case 11:
  844. if (!(channel === m.change)) {
  845. context$2$0.next = 14;
  846. break;
  847. }
  848. state = m._getAllState();
  849. return context$2$0.abrupt("continue", 1);
  850. case 14: solos = state.solos;
  851. if (!(solos.indexOf(channel) > -1 || (solos.length && !(m.mutes.indexOf(channel) > -1)))) {
  852. context$2$0.next = 21;
  853. break;
  854. }
  855. context$2$0.next = 18;
  856. return put(out, value);
  857. case 18: stillOpen = context$2$0.sent;
  858. if (stillOpen) {
  859. context$2$0.next = 21;
  860. break;
  861. }
  862. return context$2$0.abrupt("break", 23);
  863. case 21: context$2$0.next = 1;
  864. break;
  865. case 23:
  866. case "end": return context$2$0.stop();
  867. }
  868. }, callee$1$0, this);
  869. }));
  870. return m;
  871. }
  872. mix.MUTE = "mute";
  873. mix.PAUSE = "pause";
  874. mix.SOLO = "solo";
  875. var VALID_SOLO_MODES = [mix.MUTE, mix.PAUSE];
  876. mix.add = function admix(m, ch) {
  877. m.admix(ch);
  878. };
  879. mix.remove = function unmix(m, ch) {
  880. m.unmix(ch);
  881. };
  882. mix.removeAll = function unmixAll(m) {
  883. m.unmixAll();
  884. };
  885. mix.toggle = function toggle(m, updateStateList) {
  886. m.toggle(updateStateList);
  887. };
  888. mix.setSoloMode = function setSoloMode(m, mode) {
  889. m.setSoloMode(mode);
  890. };
  891. function constantlyNull() {
  892. return null;
  893. }
  894. var Pub = function (ch, topicFn, bufferFn) {
  895. this.ch = ch;
  896. this.topicFn = topicFn;
  897. this.bufferFn = bufferFn;
  898. this.mults = {};
  899. };
  900. Pub.prototype._ensureMult = function (topic) {
  901. var m = this.mults[topic];
  902. var bufferFn = this.bufferFn;
  903. if (!m) {
  904. m = this.mults[topic] = mult(chan(bufferFn(topic)));
  905. }
  906. return m;
  907. };
  908. Pub.prototype.sub = function (topic, ch, keepOpen) {
  909. var m = this._ensureMult(topic);
  910. return mult.tap(m, ch, keepOpen);
  911. };
  912. Pub.prototype.unsub = function (topic, ch) {
  913. var m = this.mults[topic];
  914. if (m) {
  915. mult.untap(m, ch);
  916. }
  917. };
  918. Pub.prototype.unsubAll = function (topic) {
  919. if (topic === undefined) {
  920. this.mults = {};
  921. } else {
  922. delete this.mults[topic];
  923. }
  924. };
  925. function pub(ch, topicFn, bufferFn) {
  926. bufferFn = bufferFn || constantlyNull;
  927. var p = new Pub(ch, topicFn, bufferFn);
  928. go(regeneratorRuntime.mark(function callee$1$0() {
  929. var value, mults, topic, m, stillOpen;
  930. return regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
  931. while (true) switch (context$2$0.prev = context$2$0.next) {
  932. case 0:
  933. if (!true) {
  934. context$2$0.next = 17;
  935. break;
  936. }
  937. context$2$0.next = 3;
  938. return take(ch);
  939. case 3: value = context$2$0.sent;
  940. mults = p.mults;
  941. if (!(value === CLOSED)) {
  942. context$2$0.next = 8;
  943. break;
  944. }
  945. for (topic in mults) {
  946. mults[topic].muxch().close();
  947. }
  948. return context$2$0.abrupt("break", 17);
  949. case 8:
  950. // TODO: Somehow ensure/document that this must return a string
  951. // (otherwise use proper (hash)maps)
  952. topic = topicFn(value);
  953. m = mults[topic];
  954. if (!m) {
  955. context$2$0.next = 15;
  956. break;
  957. }
  958. context$2$0.next = 13;
  959. return put(m.muxch(), value);
  960. case 13: stillOpen = context$2$0.sent;
  961. if (!stillOpen) {
  962. delete mults[topic];
  963. }
  964. case 15: context$2$0.next = 0;
  965. break;
  966. case 17:
  967. case "end": return context$2$0.stop();
  968. }
  969. }, callee$1$0, this);
  970. }));
  971. return p;
  972. }
  973. pub.sub = function sub(p, topic, ch, keepOpen) {
  974. return p.sub(topic, ch, keepOpen);
  975. };
  976. pub.unsub = function unsub(p, topic, ch) {
  977. p.unsub(topic, ch);
  978. };
  979. pub.unsubAll = function unsubAll(p, topic) {
  980. p.unsubAll(topic);
  981. };
  982. module.exports = {
  983. mapFrom: mapFrom,
  984. mapInto: mapInto,
  985. filterFrom: filterFrom,
  986. filterInto: filterInto,
  987. removeFrom: removeFrom,
  988. removeInto: removeInto,
  989. mapcatFrom: mapcatFrom,
  990. mapcatInto: mapcatInto,
  991. pipe: pipe,
  992. split: split,
  993. reduce: reduce,
  994. onto: onto,
  995. fromColl: fromColl,
  996. map: map,
  997. merge: merge,
  998. into: into,
  999. take: takeN,
  1000. unique: unique,
  1001. partition: partition,
  1002. partitionBy: partitionBy,
  1003. mult: mult,
  1004. mix: mix,
  1005. pub: pub
  1006. };
  1007. // Possible "fluid" interfaces:
  1008. // thread(
  1009. // [fromColl, [1, 2, 3, 4]],
  1010. // [mapFrom, inc],
  1011. // [into, []]
  1012. // )
  1013. // thread(
  1014. // [fromColl, [1, 2, 3, 4]],
  1015. // [mapFrom, inc, _],
  1016. // [into, [], _]
  1017. // )
  1018. // wrap()
  1019. // .fromColl([1, 2, 3, 4])
  1020. // .mapFrom(inc)
  1021. // .into([])
  1022. // .unwrap();