/** * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule update */ /* global hasOwnProperty:true */ 'use strict'; var assign = require("./Object.assign"); var keyOf = require("./keyOf"); var invariant = require("./invariant"); var hasOwnProperty = {}.hasOwnProperty; function shallowCopy(x) { if (Array.isArray(x)) { return x.concat(); } else if (x && typeof x === 'object') { return assign(new x.constructor(), x); } else { return x; } } var COMMAND_PUSH = keyOf({$push: null}); var COMMAND_UNSHIFT = keyOf({$unshift: null}); var COMMAND_SPLICE = keyOf({$splice: null}); var COMMAND_SET = keyOf({$set: null}); var COMMAND_MERGE = keyOf({$merge: null}); var COMMAND_APPLY = keyOf({$apply: null}); var ALL_COMMANDS_LIST = [ COMMAND_PUSH, COMMAND_UNSHIFT, COMMAND_SPLICE, COMMAND_SET, COMMAND_MERGE, COMMAND_APPLY ]; var ALL_COMMANDS_SET = {}; ALL_COMMANDS_LIST.forEach(function(command) { ALL_COMMANDS_SET[command] = true; }); function invariantArrayCase(value, spec, command) { ("production" !== process.env.NODE_ENV ? invariant( Array.isArray(value), 'update(): expected target of %s to be an array; got %s.', command, value ) : invariant(Array.isArray(value))); var specValue = spec[command]; ("production" !== process.env.NODE_ENV ? invariant( Array.isArray(specValue), 'update(): expected spec of %s to be an array; got %s. ' + 'Did you forget to wrap your parameter in an array?', command, specValue ) : invariant(Array.isArray(specValue))); } function update(value, spec) { ("production" !== process.env.NODE_ENV ? invariant( typeof spec === 'object', 'update(): You provided a key path to update() that did not contain one ' + 'of %s. Did you forget to include {%s: ...}?', ALL_COMMANDS_LIST.join(', '), COMMAND_SET ) : invariant(typeof spec === 'object')); if (hasOwnProperty.call(spec, COMMAND_SET)) { ("production" !== process.env.NODE_ENV ? invariant( Object.keys(spec).length === 1, 'Cannot have more than one key in an object with %s', COMMAND_SET ) : invariant(Object.keys(spec).length === 1)); return spec[COMMAND_SET]; } var nextValue = shallowCopy(value); if (hasOwnProperty.call(spec, COMMAND_MERGE)) { var mergeObj = spec[COMMAND_MERGE]; ("production" !== process.env.NODE_ENV ? invariant( mergeObj && typeof mergeObj === 'object', 'update(): %s expects a spec of type \'object\'; got %s', COMMAND_MERGE, mergeObj ) : invariant(mergeObj && typeof mergeObj === 'object')); ("production" !== process.env.NODE_ENV ? invariant( nextValue && typeof nextValue === 'object', 'update(): %s expects a target of type \'object\'; got %s', COMMAND_MERGE, nextValue ) : invariant(nextValue && typeof nextValue === 'object')); assign(nextValue, spec[COMMAND_MERGE]); } if (hasOwnProperty.call(spec, COMMAND_PUSH)) { invariantArrayCase(value, spec, COMMAND_PUSH); spec[COMMAND_PUSH].forEach(function(item) { nextValue.push(item); }); } if (hasOwnProperty.call(spec, COMMAND_UNSHIFT)) { invariantArrayCase(value, spec, COMMAND_UNSHIFT); spec[COMMAND_UNSHIFT].forEach(function(item) { nextValue.unshift(item); }); } if (hasOwnProperty.call(spec, COMMAND_SPLICE)) { ("production" !== process.env.NODE_ENV ? invariant( Array.isArray(value), 'Expected %s target to be an array; got %s', COMMAND_SPLICE, value ) : invariant(Array.isArray(value))); ("production" !== process.env.NODE_ENV ? invariant( Array.isArray(spec[COMMAND_SPLICE]), 'update(): expected spec of %s to be an array of arrays; got %s. ' + 'Did you forget to wrap your parameters in an array?', COMMAND_SPLICE, spec[COMMAND_SPLICE] ) : invariant(Array.isArray(spec[COMMAND_SPLICE]))); spec[COMMAND_SPLICE].forEach(function(args) { ("production" !== process.env.NODE_ENV ? invariant( Array.isArray(args), 'update(): expected spec of %s to be an array of arrays; got %s. ' + 'Did you forget to wrap your parameters in an array?', COMMAND_SPLICE, spec[COMMAND_SPLICE] ) : invariant(Array.isArray(args))); nextValue.splice.apply(nextValue, args); }); } if (hasOwnProperty.call(spec, COMMAND_APPLY)) { ("production" !== process.env.NODE_ENV ? invariant( typeof spec[COMMAND_APPLY] === 'function', 'update(): expected spec of %s to be a function; got %s.', COMMAND_APPLY, spec[COMMAND_APPLY] ) : invariant(typeof spec[COMMAND_APPLY] === 'function')); nextValue = spec[COMMAND_APPLY](nextValue); } for (var k in spec) { if (!(ALL_COMMANDS_SET.hasOwnProperty(k) && ALL_COMMANDS_SET[k])) { nextValue[k] = update(value[k], spec[k]); } } return nextValue; } module.exports = update;