var assert = require('./assert'); var isTypeName = require('./isTypeName'); var isFunction = require('./isFunction'); var getTypeName = require('./getTypeName'); var isIdentity = require('./isIdentity'); var create = require('./create'); var is = require('./is'); var isArray = require('./isArray'); function getDefaultName(type) { return 'Array<' + getTypeName(type) + '>'; } function list(type, name) { if (process.env.NODE_ENV !== 'production') { assert(isFunction(type), function () { return 'Invalid argument type ' + assert.stringify(type) + ' supplied to list(type, [name]) combinator (expected a type)'; }); assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to list(type, [name]) combinator (expected a string)'; }); } var displayName = name || getDefaultName(type); var typeNameCache = getTypeName(type); var identity = isIdentity(type); // the list is identity iif type is identity function List(value, path) { if (process.env.NODE_ENV === 'production') { if (identity) { return value; // just trust the input if elements must not be hydrated } } if (process.env.NODE_ENV !== 'production') { path = path || [displayName]; assert(isArray(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/') + ' (expected an array of ' + typeNameCache + ')'; }); } var idempotent = true; // will remain true if I can reutilise the input var ret = []; // make a temporary copy, will be discarded if idempotent remains true for (var i = 0, len = value.length; i < len; i++ ) { var actual = value[i]; var instance = create(type, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(i + ': ' + typeNameCache) : null )); idempotent = idempotent && ( actual === instance ); ret.push(instance); } if (idempotent) { // implements idempotency ret = value; } if (process.env.NODE_ENV !== 'production') { Object.freeze(ret); } return ret; } List.meta = { kind: 'list', type: type, name: name, identity: identity }; List.displayName = displayName; List.is = function (x) { return isArray(x) && x.every(function (e) { return is(e, type); }); }; List.update = function (instance, patch) { return List(assert.update(instance, patch)); }; return List; } list.getDefaultName = getDefaultName; module.exports = list;