message: refactor(single): smaller impl
diff: @@ -6,8 +6,7 @@ import { MonoTypeOperatorFunction } from '../types';
  import { SequenceError } from '../util/SequenceError';
  import { NotFoundError } from '../util/NotFoundError';
  import { lift } from '../util/lift';
  -
  -const defaultPredicate = () => true;
  +import { OperatorSubscriber } from './OperatorSubscriber';
  /**
  * Returns an observable that asserts that only one value is
  @@ -90,47 +89,28 @@ const defaultPredicate = () => true;
  * the predicate or `undefined` when no items match.
  */
  export function single<T>(
  - predicate: (value: T, index: number, source: Observable<T>) => boolean = defaultPredicate
  + predicate?: (value: T, index: number, source: Observable<T>) => boolean
  ): MonoTypeOperatorFunction<T> {
  - return (source: Observable<T>) => lift(source, singleOperator(predicate));
  -}
  -
  -function singleOperator<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean) {
  - return function(this: Subscriber<T>, source: Observable<T>) {
  - let _hasValue = false;
  - let _seenValue = false;
  - let _value: T;
  - let _i = 0;
  - const _destination = this;
  -
  - return source.subscribe({
  - next: value => {
  - _seenValue = true;
  - let match = false;
  - try {
  - match = predicate(value, _i++, source);
  - } catch (err) {
  - _destination.error(err);
  - return;
  - }
  - if (match) {
  - if (_hasValue) {
  - _destination.error(new SequenceError('Too many matching values'));
  - } else {
  - _hasValue = true;
  - _value = value;
  - }
  + return (source: Observable<T>) => lift(source, function (this: Subscriber<T>, source: Observable<T>) {
  + const subscriber = this;
  + let hasValue = false;
  + let singleValue: T;
  + let seenValue = false;
  + let index = 0;
  + source.subscribe(new OperatorSubscriber(subscriber, value => {
  + seenValue = true;
  + if (!predicate || predicate(value, index++, source)) {
  + hasValue && subscriber.error(new SequenceError('Too many matching values'));
  + hasValue = true;
  + singleValue = value;
  }
  - },
  - error: err => _destination.error(err),
  - complete: () => {
  - if (_hasValue) {
  - _destination.next(_value);
  - _destination.complete();
  + }, undefined, () => {
  + if (hasValue) {
  + subscriber.next(singleValue);
  + subscriber.complete();
  } else {
  - _destination.error(_seenValue ? new NotFoundError('No matching values') : new EmptyError());
  + subscriber.error(seenValue ? new NotFoundError('No matching values') : new EmptyError())
  }
  - },
  + }))
  });
  - };
  }
  