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

0% Statements 0/0
0% Branches 0/0
0% Functions 0/0
0% Lines 0/0

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                                                                                                                                                                                                                                                               
/* global Symbol */
import { A } from '@ember/array';
import { buildSelector, assign } from '../../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;
  }
}
 
if (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);
 
      if (window.Proxy) {
        descriptor.value = proxyIt(descriptor.value);
      }
    }
  };
 
  return descriptor;
}