Mirror: 🎩 A tiny but capable push & pull stream library for TypeScript and Flow
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Remove redundant Close/End guards from operators and add them to sources (#55)

* Remove strict end test from map operator

The map operator doesn't need to guard
against signals after End since it's a
safe and repeatable effect.

* Remove strict end guard from onEnd operator

The onEnd operator does run a side-effect, but
it can rely on the convention of no signals being
emitted after End/Close.

* Add Close guards to all sources

Since we now assume that sources behave
well and operators don't have to guard
Close events, unless they're dealing with
multiple sources and side-effects, the
sources can be amended instead.

authored by

Phil Plückthun and committed by
GitHub
d0ee5131 55cf86af

+45 -26
+5 -14
src/wonka_operators.re
··· 412 412 let onEnd = (f: (. unit) => unit): operatorT('a, 'a) => 413 413 curry(source => 414 414 curry(sink => { 415 - let ended = ref(false); 416 - 417 415 source((. signal) => 418 416 switch (signal) { 419 417 | Start(talkback) => ··· 421 419 Start( 422 420 (. signal) => { 423 421 switch (signal) { 424 - | Close when ! ended^ => 425 - ended := true; 426 - f(.); 427 - | Close 428 - | Pull => () 422 + | Close => f(.) 423 + | _ => () 429 424 }; 430 - 431 425 talkback(. signal); 432 426 }, 433 427 ), 434 428 ) 435 429 | End => 436 - if (! ended^) { 437 - ended := true; 438 - sink(. signal); 439 - f(.); 440 - } 430 + sink(. signal); 431 + f(.); 441 432 | _ => sink(. signal) 442 433 } 443 - ); 434 + ) 444 435 }) 445 436 ); 446 437
-1
src/wonka_operators.test.ts
··· 538 538 passesSinkClose(noop); 539 539 passesSourceEnd(noop); 540 540 passesSingleStart(noop); 541 - // TODO: passesStrictEnd(noop); 542 541 passesAsyncSequence(noop); 543 542 544 543 it('maps over values given a transform function', () => {
+40 -11
src/wonka_sources.re
··· 46 46 ended := true; 47 47 sink(. Push(x)); 48 48 sink(. End); 49 - | _ => () 49 + | Pull => () 50 + | Close => ended := true 50 51 }, 51 52 ), 52 53 ); 53 54 }); 54 55 56 + type makeStateT = { 57 + mutable teardown: (. unit) => unit, 58 + mutable ended: bool, 59 + }; 60 + 55 61 [@genType] 56 62 let make = (f: (. observerT('a)) => teardownT): sourceT('a) => 57 63 curry(sink => { 58 - let teardown = ref((.) => ()); 64 + let state: makeStateT = {teardown: (.) => (), ended: false}; 59 65 60 66 sink(. 61 67 Start( 62 68 (. signal) => 63 69 switch (signal) { 64 - | Close => teardown^(.) 65 - | Pull => () 70 + | Close when !state.ended => 71 + state.ended = true; 72 + state.teardown(.); 73 + | _ => () 66 74 }, 67 75 ), 68 76 ); 69 77 70 - teardown := 78 + state.teardown = 71 79 f(. { 72 - next: value => sink(. Push(value)), 73 - complete: () => sink(. End), 80 + next: value => 81 + if (!state.ended) { 82 + sink(. Push(value)); 83 + }, 84 + complete: () => 85 + if (!state.ended) { 86 + state.ended = true; 87 + sink(. End); 88 + }, 74 89 }); 75 90 }); 76 91 ··· 91 106 sink(. 92 107 Start( 93 108 (. signal) => 94 - if (signal === Close) { 95 - state.sinks = Rebel.Array.filter(state.sinks, x => x !== sink); 109 + switch (signal) { 110 + | Close => 111 + state.sinks = Rebel.Array.filter(state.sinks, x => x !== sink) 112 + | _ => () 96 113 }, 97 114 ), 98 115 ); ··· 114 131 115 132 [@genType] 116 133 let empty = (sink: sinkT('a)): unit => { 117 - sink(. Start(talkbackPlaceholder)); 118 - sink(. End); 134 + let ended = ref(false); 135 + sink(. 136 + Start( 137 + (. signal) => { 138 + switch (signal) { 139 + | Close => ended := true 140 + | _ => () 141 + } 142 + }, 143 + ), 144 + ); 145 + if (! ended^) { 146 + sink(. End); 147 + }; 119 148 }; 120 149 121 150 [@genType]