Example #1
0
export function arrayContentDidChange(array, startIdx, removeAmt, addAmt) {
  // if no args are passed assume everything changes
  if (startIdx === undefined) {
    startIdx = 0;
    removeAmt = addAmt = -1;
  } else {
    if (removeAmt === undefined) {
      removeAmt = -1;
    }

    if (addAmt === undefined) {
      addAmt = -1;
    }
  }

  let adding;
  if (startIdx >= 0 && addAmt >= 0 && get(array, 'hasEnumerableObservers')) {
    adding = [];
    let lim = startIdx + addAmt;

    for (let idx = startIdx; idx < lim; idx++) {
      adding.push(objectAt(array, idx));
    }
  } else {
    adding = addAmt;
  }

  array.enumerableContentDidChange(removeAmt, adding);

  if (array.__each) {
    array.__each.arrayDidChange(array, startIdx, removeAmt, addAmt);
  }

  sendEvent(array, '@array:change', [array, startIdx, removeAmt, addAmt]);

  let meta = peekMeta(array);
  let cache = meta && meta.readableCache();

  if (cache) {
    if (cache.firstObject !== undefined &&
        objectAt(array, 0) !== cacheFor.get(cache, 'firstObject')) {
      propertyWillChange(array, 'firstObject');
      propertyDidChange(array, 'firstObject');
    }
    if (cache.lastObject !== undefined &&
        objectAt(array, get(array, 'length') - 1) !== cacheFor.get(cache, 'lastObject')) {
      propertyWillChange(array, 'lastObject');
      propertyDidChange(array, 'lastObject');
    }
  }
  return array;
}
Example #2
0
export function arrayContentDidChange(array, startIdx, removeAmt, addAmt) {
  // if no args are passed assume everything changes
  if (startIdx === undefined) {
    startIdx = 0;
    removeAmt = addAmt = -1;
  } else {
    if (removeAmt === undefined) {
      removeAmt = -1;
    }

    if (addAmt === undefined) {
      addAmt = -1;
    }
  }

  if (addAmt < 0 || removeAmt < 0 || addAmt - removeAmt !== 0) {
    notifyPropertyChange(array, 'length');
  }

  notifyPropertyChange(array, '[]');

  eachProxyArrayDidChange(array, startIdx, removeAmt, addAmt);

  sendEvent(array, '@array:change', [array, startIdx, removeAmt, addAmt]);

  let meta = peekMeta(array);
  let cache = peekCacheFor(array);
  if (cache !== undefined) {
    let length = get(array, 'length');
    let addedAmount = (addAmt === -1 ? 0 : addAmt);
    let removedAmount = (removeAmt === -1 ? 0 : removeAmt);
    let delta = addedAmount - removedAmount;
    let previousLength = length - delta;

    let normalStartIdx = startIdx < 0 ? previousLength + startIdx : startIdx;
    if (cache.has('firstObject') && normalStartIdx === 0) {
      notifyPropertyChange(array, 'firstObject', meta);
    }

    if (cache.has('lastObject')) {
      let previousLastIndex = previousLength - 1;
      let lastAffectedIndex = normalStartIdx + removedAmount;
      if (previousLastIndex < lastAffectedIndex) {
        notifyPropertyChange(array, 'lastObject', meta);
      }
    }
  }

  return array;
}
Example #3
0
export function arrayContentWillChange(array, startIdx, removeAmt, addAmt) {
  // if no args are passed assume everything changes
  if (startIdx === undefined) {
    startIdx = 0;
    removeAmt = addAmt = -1;
  } else {
    if (removeAmt === undefined) {
      removeAmt = -1;
    }

    if (addAmt === undefined) {
      addAmt = -1;
    }
  }

  eachProxyArrayWillChange(array, startIdx, removeAmt, addAmt);

  sendEvent(array, '@array:before', [array, startIdx, removeAmt, addAmt]);

  return array;
}
Example #4
0
export function arrayContentWillChange(array, startIdx, removeAmt, addAmt) {
  let removing, lim;

  // if no args are passed assume everything changes
  if (startIdx === undefined) {
    startIdx = 0;
    removeAmt = addAmt = -1;
  } else {
    if (removeAmt === undefined) {
      removeAmt = -1;
    }

    if (addAmt === undefined) {
      addAmt = -1;
    }
  }

  if (array.__each) {
    array.__each.arrayWillChange(array, startIdx, removeAmt, addAmt);
  }

  sendEvent(array, '@array:before', [array, startIdx, removeAmt, addAmt]);

  if (startIdx >= 0 && removeAmt >= 0 && get(array, 'hasEnumerableObservers')) {
    removing = [];
    lim = startIdx + removeAmt;

    for (let idx = startIdx; idx < lim; idx++) {
      removing.push(objectAt(array, idx));
    }
  } else {
    removing = removeAmt;
  }

  array.enumerableContentWillChange(removing, addAmt);

  return array;
}
Example #5
0
    if (removing === -1) {
      removing = null;
    }

    if (adding === -1) {
      adding = null;
    }

    propertyWillChange(this, '[]');

    if (hasDelta) {
      propertyWillChange(this, 'length');
    }

    sendEvent(this, '@enumerable:before', [this, removing, adding]);

    return this;
  },

  /**
    Invoke this method when the contents of your enumerable has changed.
    This will notify any observers watching for content changes. If you are
    implementing an ordered enumerable (such as an array), also pass the
    start and end values where the content changed so that it can be used to
    notify range observers.

    @method enumerableContentDidChange
    @param {Ember.Enumerable|Number} removing An enumerable of the objects to
      be removed or the number of items to be removed.
    @param {Ember.Enumerable|Number} adding  An enumerable of the objects to
Example #6
0
    constructor() {
      if (!wasApplied) {
        Class.proto(); // prepare prototype...
      }

      if (arguments.length > 0) {
        initProperties = [arguments[0]];
      }

      this.__defineNonEnumerable(GUID_KEY_PROPERTY);
      let m = meta(this);
      let proto = m.proto;
      m.proto = this;

      if (initFactory) {
        m.factory = initFactory;
        initFactory = null;
      }
      if (initProperties) {
        // capture locally so we can clear the closed over variable
        let props = initProperties;
        initProperties = null;

        let concatenatedProperties = this.concatenatedProperties;
        let mergedProperties = this.mergedProperties;

        for (let i = 0; i < props.length; i++) {
          let properties = props[i];

          assert(
            'Ember.Object.create only accepts objects.',
            typeof properties === 'object' || properties === undefined
          );

          assert(
            'Ember.Object.create no longer supports mixing in other ' +
            'definitions, use .extend & .create separately instead.',
            !(properties instanceof Mixin)
          );

          if (!properties) { continue; }

          let keyNames = Object.keys(properties);

          for (let j = 0; j < keyNames.length; j++) {
            let keyName = keyNames[j];
            let value = properties[keyName];

            if (detectBinding(keyName)) {
              m.writeBindings(keyName, value);
            }

            let possibleDesc = this[keyName];
            let desc = (possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) ? possibleDesc : undefined;

            assert(
              'Ember.Object.create no longer supports defining computed ' +
              'properties. Define computed properties using extend() or reopen() ' +
              'before calling create().',
              !(value instanceof ComputedProperty)
            );
            assert(
              'Ember.Object.create no longer supports defining methods that call _super.',
              !(typeof value === 'function' && value.toString().indexOf('._super') !== -1)
            );
            assert(
              '`actions` must be provided at extend time, not at create time, ' +
              'when Ember.ActionHandler is used (i.e. views, controllers & routes).',
              !((keyName === 'actions') && ActionHandler.detect(this))
            );

            if (concatenatedProperties &&
                concatenatedProperties.length > 0 &&
                concatenatedProperties.indexOf(keyName) > -1) {
              let baseValue = this[keyName];

              if (baseValue) {
                if ('function' === typeof baseValue.concat) {
                  value = baseValue.concat(value);
                } else {
                  value = makeArray(baseValue).concat(value);
                }
              } else {
                value = makeArray(value);
              }
            }

            if (mergedProperties &&
                mergedProperties.length > 0 &&
                mergedProperties.indexOf(keyName) > -1) {
              let originalValue = this[keyName];

              value = assign({}, originalValue, value);
            }

            if (desc) {
              desc.set(this, keyName, value);
            } else {
              if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) {
                this.setUnknownProperty(keyName, value);
              } else {
                if (MANDATORY_SETTER) {
                  defineProperty(this, keyName, null, value); // setup mandatory setter
                } else {
                  this[keyName] = value;
                }
              }
            }
          }
        }
      }

      finishPartial(this, m);

      this.init(...arguments);

      this[POST_INIT]();

      m.proto = proto;
      finishChains(m);
      sendEvent(this, 'init', undefined, undefined, undefined, m);
    }
Example #7
0
      constructor(properties) {
        if (!wasApplied) {
          Class.proto(); // prepare prototype...
        }

        let self = this;

        if (initFactory !== void 0) {
          FACTORY_FOR.set(this, initFactory);
          initFactory = void 0;
        }

        let beforeInitCalled; // only used in debug builds to enable the proxy trap

        // using DEBUG here to avoid the extraneous variable when not needed
        if (DEBUG) {
          beforeInitCalled = true;
        }

        if (DEBUG && HAS_NATIVE_PROXY && typeof self.unknownProperty === 'function') {
          let messageFor = (obj, property) => {
            return (
              `You attempted to access the \`${String(property)}\` property (of ${obj}).\n` +
              `Since Ember 3.1, this is usually fine as you no longer need to use \`.get()\`\n` +
              `to access computed properties. However, in this case, the object in question\n` +
              `is a special kind of Ember object (a proxy). Therefore, it is still necessary\n` +
              `to use \`.get('${String(property)}')\` in this case.\n\n` +
              `If you encountered this error because of third-party code that you don't control,\n` +
              `there is more information at https://github.com/emberjs/ember.js/issues/16148, and\n` +
              `you can help us improve this error message by telling us more about what happened in\n` +
              `this situation.`
            );
          };

          /* globals Proxy Reflect */
          self = new Proxy(this, {
            get(target, property, receiver) {
              if (property === PROXY_CONTENT) {
                return target;
              } else if (
                beforeInitCalled ||
                typeof property === 'symbol' ||
                isInternalSymbol(property) ||
                property === 'toJSON' ||
                property === 'toString' ||
                property === 'toStringExtension' ||
                property === 'didDefineProperty' ||
                property === 'willWatchProperty' ||
                property === 'didUnwatchProperty' ||
                property === 'didAddListener' ||
                property === 'didRemoveListener' ||
                property === 'isDescriptor' ||
                property === '_onLookup' ||
                property in target
              ) {
                return Reflect.get(target, property, receiver);
              }

              let value = target.unknownProperty.call(receiver, property);

              if (typeof value !== 'function') {
                assert(messageFor(receiver, property), value === undefined || value === null);
              }
            },
          });

          FACTORY_FOR.set(self, FACTORY_FOR.get(this));
        }

        let m = meta(self);
        let proto = m.proto;
        m.proto = self;

        if (properties !== undefined) {
          assert(
            'EmberObject.create only accepts objects.',
            typeof properties === 'object' && properties !== null
          );

          assert(
            'EmberObject.create no longer supports mixing in other ' +
              'definitions, use .extend & .create separately instead.',
            !(properties instanceof Mixin)
          );

          let concatenatedProperties = self.concatenatedProperties;
          let mergedProperties = self.mergedProperties;
          let hasConcatenatedProps =
            concatenatedProperties !== undefined && concatenatedProperties.length > 0;
          let hasMergedProps = mergedProperties !== undefined && mergedProperties.length > 0;

          let keyNames = Object.keys(properties);

          for (let i = 0; i < keyNames.length; i++) {
            let keyName = keyNames[i];
            let value = properties[keyName];

            if (BINDING_SUPPORT && ENV._ENABLE_BINDING_SUPPORT && Mixin.detectBinding(keyName)) {
              m.writeBindings(keyName, value);
            }

            assert(
              'EmberObject.create no longer supports defining computed ' +
                'properties. Define computed properties using extend() or reopen() ' +
                'before calling create().',
              !(value instanceof ComputedProperty)
            );
            assert(
              'EmberObject.create no longer supports defining methods that call _super.',
              !(typeof value === 'function' && value.toString().indexOf('._super') !== -1)
            );
            assert(
              '`actions` must be provided at extend time, not at create time, ' +
                'when Ember.ActionHandler is used (i.e. views, controllers & routes).',
              !(keyName === 'actions' && ActionHandler.detect(this))
            );

            let possibleDesc = descriptorFor(self, keyName, m);
            let isDescriptor = possibleDesc !== undefined;

            if (!isDescriptor) {
              let baseValue = self[keyName];

              if (hasConcatenatedProps && concatenatedProperties.indexOf(keyName) > -1) {
                if (baseValue) {
                  value = makeArray(baseValue).concat(value);
                } else {
                  value = makeArray(value);
                }
              }

              if (hasMergedProps && mergedProperties.indexOf(keyName) > -1) {
                value = assign({}, baseValue, value);
              }
            }

            if (isDescriptor) {
              possibleDesc.set(self, keyName, value);
            } else if (typeof self.setUnknownProperty === 'function' && !(keyName in self)) {
              self.setUnknownProperty(keyName, value);
            } else {
              if (DEBUG) {
                defineProperty(self, keyName, null, value); // setup mandatory setter
              } else {
                self[keyName] = value;
              }
            }
          }
        }

        if (BINDING_SUPPORT && ENV._ENABLE_BINDING_SUPPORT) {
          Mixin.finishPartial(self, m);
        }

        // using DEBUG here to avoid the extraneous variable when not needed
        if (DEBUG) {
          beforeInitCalled = false;
        }
        self.init(...arguments);

        m.proto = proto;
        finishChains(m);
        sendEvent(self, 'init', undefined, undefined, undefined, m);

        // only return when in debug builds and `self` is the proxy created above
        if (DEBUG && self !== this) {
          return self;
        }
      }
Example #8
0
export function arrayContentDidChange(array, startIdx, removeAmt, addAmt) {
  // if no args are passed assume everything changes
  if (startIdx === undefined) {
    startIdx = 0;
    removeAmt = addAmt = -1;
  } else {
    if (removeAmt === undefined) {
      removeAmt = -1;
    }

    if (addAmt === undefined) {
      addAmt = -1;
    }
  }

  let adding;
  if (startIdx >= 0 && addAmt >= 0 && get(array, 'hasEnumerableObservers')) {
    adding = [];
    let lim = startIdx + addAmt;

    for (let idx = startIdx; idx < lim; idx++) {
      adding.push(objectAt(array, idx));
    }
  } else {
    adding = addAmt;
  }

  array.enumerableContentDidChange(removeAmt, adding);

  if (array.__each) {
    array.__each.arrayDidChange(array, startIdx, removeAmt, addAmt);
  }

  sendEvent(array, '@array:change', [array, startIdx, removeAmt, addAmt]);

  let meta = peekMeta(array);
  let cache = meta && meta.readableCache();
  if (cache !== undefined) {
    let length = get(array, 'length');
    let addedAmount = (addAmt === -1 ? 0 : addAmt);
    let removedAmount = (removeAmt === -1 ? 0 : removeAmt);
    let delta = addedAmount - removedAmount;
    let previousLength = length - delta;

    let normalStartIdx = startIdx < 0 ? previousLength + startIdx : startIdx;
    if (cache.firstObject !== undefined && normalStartIdx === 0) {
      propertyWillChange(array, 'firstObject');
      propertyDidChange(array, 'firstObject');
    }

    if (cache.lastObject !== undefined) {
      let previousLastIndex = previousLength - 1;
      let lastAffectedIndex = normalStartIdx + removedAmount;
      if (previousLastIndex < lastAffectedIndex) {
        propertyWillChange(array, 'lastObject');
        propertyDidChange(array, 'lastObject');
      }
   }
  }

  return array;
}
Example #9
0
    ```javascript
    person.on('didEat', function(food) {
      console.log('person ate some ' + food);
    });

    person.trigger('didEat', 'broccoli');

    // outputs: person ate some broccoli
    ```
    @method trigger
    @param {String} name The name of the event
    @param {Object...} args Optional arguments to pass on
    @public
  */
  trigger(name, ...args) {
    sendEvent(this, name, args);
  },

  /**
    Cancels subscription for given name, target, and method.

    @method off
    @param {String} name The name of the event
    @param {Object} target The target of the subscription
    @param {Function} method The function of the subscription
    @return this
    @public
  */
  off(name, target, method) {
    removeListener(this, name, target, method);
    return this;