From 9d45e42dc0298ea8241132142d3100358fe99dc4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 20 Nov 2021 07:45:41 +0100 Subject: Adding upstream version 1.2.0. Signed-off-by: Daniel Baumann --- src/decko.js | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/decko.js (limited to 'src/decko.js') diff --git a/src/decko.js b/src/decko.js new file mode 100644 index 0000000..298e092 --- /dev/null +++ b/src/decko.js @@ -0,0 +1,98 @@ + +const EMPTY = {}; +const HOP = Object.prototype.hasOwnProperty; + +let fns = { + /** let cachedFn = memoize(originalFn); */ + memoize(fn, opt=EMPTY) { + let cache = opt.cache || {}; + return function(...a) { + let k = String(a[0]); + if (opt.caseSensitive===false) k = k.toLowerCase(); + return HOP.call(cache,k) ? cache[k] : (cache[k] = fn.apply(this, a)); + }; + }, + + /** let throttled = debounce(10, console.log); */ + debounce(fn, opts) { + if (typeof opts==='function') { let p = fn; fn = opts; opts = p; } + let delay = opts && opts.delay || opts || 0, + args, context, timer; + return function(...a) { + args = a; + context = this; + if (!timer) timer = setTimeout( () => { + fn.apply(context, args); + args = context = timer = null; + }, delay); + }; + }, + + bind(target, key, { value: fn }) { + return { + configurable: true, + get() { + let value = fn.bind(this); + Object.defineProperty(this, key, { + value, + configurable: true, + writable: true + }); + return value; + } + }; + } +}; + + +let memoize = multiMethod(fns.memoize), + debounce = multiMethod(fns.debounce), + bind = multiMethod((f,c)=>f.bind(c), ()=>fns.bind); + +export { memoize, debounce, bind }; +export default { memoize, debounce, bind }; + + +/** Creates a function that supports the following calling styles: + * d() - returns an unconfigured decorator + * d(opts) - returns a configured decorator + * d(fn, opts) - returns a decorated proxy to `fn` + * d(target, key, desc) - the decorator itself + * + * @Example: + * // simple identity deco: + * let d = multiMethod( fn => fn ); + * + * class Foo { + * @d + * bar() { } + * + * @d() + * baz() { } + * + * @d({ opts }) + * bat() { } + * + * bap = d(() => {}) + * } + */ +function multiMethod(inner, deco) { + deco = deco || inner.decorate || decorator(inner); + let d = deco(); + return (...args) => { + let l = args.length; + return (l<2 ? deco : (l>2 ? d : inner))(...args); + }; +} + +/** Returns function supports the forms: + * deco(target, key, desc) -> decorate a method + * deco(Fn) -> call the decorator proxy on a function + */ +function decorator(fn) { + return opt => ( + typeof opt==='function' ? fn(opt) : (target, key, desc) => { + desc.value = fn(desc.value, opt, target, key, desc); + } + ); +} -- cgit v1.2.3