UNPKG

@web-native-js/reflex

Version:

Reflex is a reactivity library.

110 lines (107 loc) 3.61 kB
/** * @imports */ import _arrFrom from '@web-native-js/commons/arr/from.js'; import _all from '@web-native-js/commons/arr/all.js'; import _isString from '@web-native-js/commons/js/isString.js'; import _isArray from '@web-native-js/commons/js/isArray.js'; import _isNumber from '@web-native-js/commons/js/isNumber.js'; import _isObject from '@web-native-js/commons/js/isObject.js'; import _isTypeObject from '@web-native-js/commons/js/isTypeObject.js'; import MutationEvent from './internal/MutationEvent.js'; import QueryEvent from './internal/QueryEvent.js'; import ObserverBase from './internal/ObserverBase.js'; import TrapBase from './internal/TrapBase.js'; import unlink from './unlink.js'; import link from './link.js'; import reflexHas from './has.js'; /** * Executes a "_setProp" type of operation on a target. * Fires any observers for the specific type that may be bound to target. * * @param bool define * @param array|object target * @param string|array keysOrPayload * @param mixed value * @param bool returnEvent * * @return bool|Event */ export default function(define, target, keysOrPayload, value = null, returnEvent = false) { if (!target || !_isTypeObject(target)) { throw new Error('Target must be of type object!'); } if (_isObject(keysOrPayload)) { returnEvent = value; } var keys = keysOrPayload, _data = {}, data = {}, created = []; var handleSet = (key, value, related) => { _data[key] = target[key]; if (!reflexHas(target, key)) { created.push(key); } // --------------------------------- var descriptor; if (define) { descriptor = value || {}; value = descriptor.value; } // Execute any "set" traps, otherwise "set" the default way var success, trapBase, defaultSet = function(_success) { if (!arguments.length) { if (descriptor) { Object.defineProperty(target, key, descriptor); } else { target[key] = value; } return true; } return _success; }; if (trapBase = TrapBase.getForTarget(target)) { var details = descriptor ? {type:'def', query:key, descriptor, related} : {type:'set', query:key, value, related}; success = trapBase.fire(new QueryEvent(target, details), defaultSet); } else { success = defaultSet(); } // --------------------------------- if (success) { data[key] = value; if (data[key] !== _data[key]) { // Unobserve outgoing value for bubbling if (_data[key] && _isTypeObject(_data[key])) { unlink(target, key, _data[key]); } // Observe incoming value for bubbling if (data[key] && _isTypeObject(data[key])) { link(target, key, data[key]); } } else { delete data[key]; delete _data[key]; } } else { delete _data[key]; } return success; }; // --------------------------------- var successStates = []; if (_isArray(keys) || ((_isString(keys) || _isNumber(keys)) && (keys = _arrFrom(keys)))) { successStates = keys.map(key => handleSet(key, value, keys)) } else if (_isObject(keysOrPayload)) { var payloadKeys = Object.keys(keysOrPayload); successStates = payloadKeys.map(key => handleSet(key, keysOrPayload[key], payloadKeys)) } // --------------------------------- var evt, mutationBase; if ((mutationBase = ObserverBase.getForTarget(target)) || returnEvent) { evt = new MutationEvent(target, {type:'set', data, _data, created}); if (mutationBase) { mutationBase.fire(evt); } } return returnEvent ? evt : _all(successStates, state => state); }