All files / addon-test-support/properties/collection main.js

100% Statements 45/45
87.5% Branches 14/16
100% Functions 14/14
100% Lines 44/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128                  284x 284x 284x 284x   284x             284x       108x       266x   266x 218x 218x   218x   218x   218x     218x   218x     266x       12x       12x       12x       6x       6x       72x   72x   72x 144x     72x       1x 1x 12x 12x 36x   12x         284x   2092x 2080x   2080x 12x       2080x           139x             284x   284x 284x         139x    
/* global Symbol */
import { A } from '@ember/array';
import { buildSelector, assign } from '../../-private/helpers';
import { create } from '../../create';
import { count } from '../count';
import Ceibo from 'ceibo';
 
export class Collection {
  constructor(scope, definition, parent, key) {
    this.scope = scope;
    this.definition = definition || {};
    this.parent = parent;
    this.key = key;
 
    this._itemCounter = create({
      count: count(scope, {
        resetScope: this.definition.resetScope,
        testContainer: this.definition.testContainer
      })
    }, { parent });
 
    this._items = [];
  }
 
  get length() {
    return this._itemCounter.count;
  }
 
  objectAt(index) {
    let { key } = this;
 
    if (typeof this._items[index] === 'undefined') {
      let { scope, definition, parent } = this;
      let itemScope = buildSelector({}, scope, { at: index });
 
      let finalizedDefinition = assign({}, definition);
 
      finalizedDefinition.scope = itemScope;
 
      let tree = create(finalizedDefinition, { parent });
 
      // Change the key of the root node
      Ceibo.meta(tree).key = `${key}[${index}]`;
 
      this._items[index] = tree;
    }
 
    return this._items[index];
  }
 
  filter(...args) {
    return this.toArray().filter(...args);
  }
 
  filterBy(...args) {
    return this.toArray().filterBy(...args);
  }
 
  forEach(...args) {
    return this.toArray().forEach(...args);
  }
 
  map(...args) {
    return this.toArray().map(...args);
  }
 
  mapBy(...args) {
    return this.toArray().mapBy(...args);
  }
 
  toArray() {
    let { length } = this;
 
    let array = A();
 
    for (let i = 0; i < length; i++) {
      array.push(this.objectAt(i));
    }
 
    return array;
  }
}
 
Eif (typeof (Symbol) !== 'undefined' && Symbol.iterator) {
  Collection.prototype[Symbol.iterator] = function() {
    let i = 0;
    let items = this.toArray();
    let next = () => ({ done: i >= items.length, value: items[i++] });
 
    return { next };
  }
}
 
function proxyIt(instance) {
  return new window.Proxy(instance, {
    get: function(target, name) {
      if (typeof(name) === 'number' || typeof(name) === 'string') {
        let index = parseInt(name, 10);
 
        if (!isNaN(index)) {
          return target.objectAt(index);
        }
      }
 
      return target[name];
    }
  });
}
 
export function collection(scope, definition) {
  let descriptor = {
    isDescriptor: true,
 
    setup(node, key) {
      // Set the value on the descriptor so that it will be picked up and applied by Ceibo.
      // This does mutate the descriptor, but because `setup` is always called before the
      // value is assigned we are guaranteed to get a new, unique Collection instance each time.
      descriptor.value = new Collection(scope, definition, node, key);
 
      Eif (window.Proxy) {
        descriptor.value = proxyIt(descriptor.value);
      }
    }
  };
 
  return descriptor;
}