UNPKG

spica

Version:

Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.

129 lines (119 loc) 4 kB
import { ObjectCreate } from './alias'; import { type, isPrimitive } from './type'; import { push } from './array'; export const assign = template((prop, target, source) => target[prop] = source[prop]); export const clone = template((prop, target, source) => { switch (type(source[prop])) { case 'Array': return target[prop] = source[prop].slice(); case 'Object': switch (type(target[prop])) { case 'Object': return target[prop] = clone(empty(source[prop]), source[prop]); default: return target[prop] = source[prop]; } default: return target[prop] = source[prop]; } }); export const overwrite = template((prop, target, source) => { switch (type(source[prop])) { case 'Array': return target[prop] = source[prop]; case 'Object': switch (type(target[prop])) { case 'Object': return overwrite(target[prop], source[prop]); default: return target[prop] = overwrite(empty(source[prop]), source[prop]); } default: return target[prop] = source[prop]; } }); export const extend = template((prop, target, source) => { switch (type(source[prop])) { case 'undefined': return; case 'Array': return target[prop] = source[prop]; case 'Object': switch (type(target[prop])) { case 'Object': return extend(target[prop], source[prop]); default: return target[prop] = extend(empty(source[prop]), source[prop]); } default: return target[prop] = source[prop]; } }); export const merge = template((prop, target, source) => { switch (type(source[prop])) { case 'undefined': return; case 'Array': switch (type(target[prop])) { case 'Array': return target[prop] = push(target[prop], source[prop]); default: return target[prop] = source[prop].slice(); } case 'Object': switch (type(target[prop])) { case 'Object': return merge(target[prop], source[prop]); default: return target[prop] = merge(empty(source[prop]), source[prop]); } default: return target[prop] = source[prop]; } }); export const inherit = template((prop, target, source) => { switch (type(source[prop])) { case 'undefined': return; case 'Array': return target[prop] = source[prop].slice(); case 'Object': switch (type(target[prop])) { case 'Object': assert(target.hasOwnProperty(prop)); return inherit(target[prop], source[prop]); default: return target[prop] = ObjectCreate(source[prop]); } default: return target[prop] = source[prop]; } }); export function template(strategy: (prop: string, target: object, source: object) => void) { return walk; function walk<T extends U, U extends object>(target: T, source: Partial<U>, ...sources: Partial<U>[]): T; function walk<T extends U, U extends object>(target: Partial<U>, source1: T, source2: Partial<U>, ...sources: Partial<U>[]): T; function walk<T extends object>(target: T, ...sources: Partial<T>[]): T; function walk<T extends object>(target: Partial<T>, source1: T, source2: Partial<T>, ...sources: Partial<T>[]): T; function walk<T extends object>(target: T, ...sources: T[]): T { assert(!isPrimitive(target)); if (isPrimitive(target)) return target; for (let i = 0; i < sources.length; ++i) { const source = sources[i]; if (source === target) continue; assert(!isPrimitive(source)); if (isPrimitive(source)) continue; assert(!isPrimitive(target) && !isPrimitive(source)); const keys = Object.keys(source); for (let i = 0; i < keys.length; ++i) { strategy(keys[i], target, source); } } return target; } } function empty(source: object): object { assert(type(source) === 'Object'); return source instanceof Object ? {} : ObjectCreate(null); }