FilterChain

Benchmark created on


Setup

const types = {
  string: 'string',
  number: 'number',
  object: 'object',
  childNodes: 'childNodes',
  state: 'state',
  function: 'function',
  domNode: 'domNode',
  unknown: 'unknown',
};

const primitiveTypes = [types.string, types.number];
class Value {
  constructor(any, type) {
    this._type = type || Value._getType(any);
    this._value = any;
  }
  get value() {
    return this._value;
  }
  is(type) {
    return this._type === type;
  }
  isPrimitive() {
    return primitiveTypes.includes(this._value); // todo here is a bug
  }
  static parse(any) {
    const type = Value._getType(any);
    return type === types.object
      ? new Value(parseObject(any), types.childNodes)
      : new Value(any, type);
  }
  static _getType(any) {
    const type = typeof any;
    if (type === types.object) {
      if (any instanceof State) {
        return types.state;
      }
      if (any instanceof Node) {
        return types.domNode;
      }
    }
    return type;
  }
}

Test runner

Ready to run.

Testing in
TestOps/sec
Version1
class FilterChain {
  constructor(...filters) {
    this.filters = filters;
  }
  apply(value) {
    let i = 0;
    const next = (value) => this.filters[++i](value, { next: next });
    return this.filters[i](value, { next: next });
  }
  static _filters = {
    _takePrimitive: function (value, chain) {
      console.log('_takePrimitive', value.isPrimitive());
      return value.isPrimitive() ? value : chain.next(value);
    },
    _takeDomNodeContent: function (value, chain) {
      console.log('_takeDomNodeContent');
      return value.is(types.domNode)
        ? new Value(value.value.textContent, types.string)
        : chain.next(value);
    },
    _endText: function (value) {
      console.log('_endText');
      return new Value(value.value + '', types.string);
    },
    /*
    _pass: function (value) {
      return value;
    },
    */
  };
  static text = new FilterChain(
    FilterChain._filters._takePrimitive,
    FilterChain._filters._takeDomNodeContent,
    FilterChain._filters._endText
  );
}

function test() {
  const val = new Value('foo');
  const filtered = FilterChain.text.apply(val);
  console.log(filtered);
}
test();
ready
Version2
class FilterChain {
  constructor(...filters) {
    this.filters = filters;
  }
  apply(value) {
    return ({
      i: 0,
      bind: function () {
        this.next = this.next.bind(this);
        return this;
      },
      apply: function (value, filters) {
        this.filters = filters;
        return this.next(value);
      },
      next: function (value) {
        return this.i < this.filters.length
          ? this.filters[this.i++](value, { next: this.next })
          : value;
      },
    })
      .bind()
      .apply(value, this.filters);
  }
  static _filters = {
    _takePrimitive: function (value, chain) {
      console.log('_takePrimitive', value.isPrimitive());
      return value.isPrimitive() ? value : chain.next(value);
    },
    _takeDomNodeContent: function (value, chain) {
      console.log('_takeDomNodeContent');
      return value.is(types.domNode)
        ? new Value(value.value.textContent, types.string)
        : chain.next(value);
    },
    _endText: function (value) {
      console.log('_endText');
      return new Value(value.value + '', types.string);
    },
    /*
    _pass: function (value) {
      return value;
    },
    */
  };
  static text = new FilterChain(
    FilterChain._filters._takePrimitive,
    FilterChain._filters._takeDomNodeContent,
    FilterChain._filters._endText
  );
}

function test() {
  const val = new Value('foo');
  const filtered = FilterChain.text.apply(val);
  console.log(filtered);
}
test();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.