import { arrayContentDidChange, arrayContentWillChange } from './array_events'; import { addListener, removeListener } from './events'; import { notifyPropertyChange } from './property_events'; import { get } from './property_get'; const EMPTY_ARRAY = Object.freeze([]); export function objectAt(array, index) { if (Array.isArray(array)) { return array[index]; } else { return array.objectAt(index); } } export function replace(array, start, deleteCount, items = EMPTY_ARRAY) { if (Array.isArray(array)) { replaceInNativeArray(array, start, deleteCount, items); } else { array.replace(start, deleteCount, items); } } const CHUNK_SIZE = 60000; // To avoid overflowing the stack, we splice up to CHUNK_SIZE items at a time. // See https://code.google.com/p/chromium/issues/detail?id=56588 for more details. export function replaceInNativeArray(array, start, deleteCount, items) { arrayContentWillChange(array, start, deleteCount, items.length); if (items.length <= CHUNK_SIZE) { array.splice(start, deleteCount, ...items); } else { array.splice(start, deleteCount); for (let i = 0; i < items.length; i += CHUNK_SIZE) { let chunk = items.slice(i, i + CHUNK_SIZE); array.splice(start + i, 0, ...chunk); } } arrayContentDidChange(array, start, deleteCount, items.length); } function arrayObserversHelper(obj, target, opts, operation, notify) { let willChange = (opts && opts.willChange) || 'arrayWillChange'; let didChange = (opts && opts.didChange) || 'arrayDidChange'; let hasObservers = get(obj, 'hasArrayObservers'); operation(obj, '@array:before', target, willChange); operation(obj, '@array:change', target, didChange); if (hasObservers === notify) { notifyPropertyChange(obj, 'hasArrayObservers'); } return obj; } export function addArrayObserver(array, target, opts) { return arrayObserversHelper(array, target, opts, addListener, false); } export function removeArrayObserver(array, target, opts) { return arrayObserversHelper(array, target, opts, removeListener, true); }