Home Manual Reference Source Repository

docs/dom/decorators.js

import { get } from '../utils';

/**
 * A decorator that memoizes a functions computation based on the current
 * and previous value of other parameters.
 * @export
 * @param {...string[]} properties 
 * @returns {MethodDecorator} 
 */
export function MemoizeFrom(...properties: string[]): MethodDecorator {
  const propMap = new WeakMap();
  
  return (target: Object, name: string, descriptor: PropertyDescriptor): PropertyDescriptor => {
    const { value } = descriptor;
    let lastReturnValue;
    
    descriptor.value = function(...args: any[]): any {
      if (!propMap.has(this)) {
        propMap.set(this, {});
      }

      let props = propMap.get(this);
      let hasChanged = false;
      
      for (const prop of properties) {
        const result = get(this, prop);
        
        if (result !== props[prop]) {
          hasChanged = true;
        } 
        
        props[prop] = result;

        if (hasChanged) {
          break;
        }
      }            

      if (hasChanged) {
        lastReturnValue = value.apply(this, args);
      }

      return lastReturnValue;
    };

    return descriptor;
  };
}