123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- "use strict";
- var customError = require("es5-ext/error/custom")
- , defineLength = require("es5-ext/function/_define-length")
- , partial = require("es5-ext/function/#/partial")
- , copy = require("es5-ext/object/copy")
- , normalizeOpts = require("es5-ext/object/normalize-options")
- , callable = require("es5-ext/object/valid-callable")
- , d = require("d")
- , WeakMap = require("es6-weak-map")
- , resolveLength = require("./resolve-length")
- , extensions = require("./registered-extensions")
- , resolveResolve = require("./resolve-resolve")
- , resolveNormalize = require("./resolve-normalize");
- var slice = Array.prototype.slice, defineProperties = Object.defineProperties;
- module.exports = function (memoize) {
- return function (fn/*, options*/) {
- var map, length, options = normalizeOpts(arguments[1]), memoized, resolve, normalizer;
- callable(fn);
- // Do not memoize already memoized function
- if (hasOwnProperty.call(fn, "__memoized__") && !options.force) return fn;
- length = resolveLength(options.length, fn.length, options.async && extensions.async);
- options.length = length ? length - 1 : 0;
- map = new WeakMap();
- if (options.resolvers) resolve = resolveResolve(options.resolvers);
- if (options.normalizer) normalizer = resolveNormalize(options.normalizer);
- if (
- length === 1 &&
- !normalizer &&
- !options.async &&
- !options.dispose &&
- !options.maxAge &&
- !options.max &&
- !options.refCounter
- ) {
- return defineProperties(
- function (obj) {
- var result, args = arguments;
- if (resolve) args = resolve(args);
- obj = args[0];
- if (map.has(obj)) return map.get(obj);
- result = fn.apply(this, args);
- if (map.has(obj)) {
- throw customError("Circular invocation", "CIRCULAR_INVOCATION");
- }
- map.set(obj, result);
- return result;
- },
- {
- __memoized__: d(true),
- delete: d(function (obj) {
- if (resolve) obj = resolve(arguments)[0];
- return map.delete(obj);
- })
- }
- );
- }
- memoized = defineProperties(
- defineLength(function (obj) {
- var memoizer, args = arguments;
- if (resolve) {
- args = resolve(args);
- obj = args[0];
- }
- memoizer = map.get(obj);
- if (!memoizer) {
- if (normalizer) {
- options = copy(options);
- options.normalizer = copy(normalizer);
- options.normalizer.get = partial.call(options.normalizer.get, obj);
- options.normalizer.set = partial.call(options.normalizer.set, obj);
- if (options.normalizer.delete) {
- options.normalizer.delete = partial.call(
- options.normalizer.delete, obj
- );
- }
- }
- map.set(obj, memoizer = memoize(partial.call(fn, obj), options));
- }
- return memoizer.apply(this, slice.call(args, 1));
- }, length),
- {
- __memoized__: d(true),
- delete: d(
- defineLength(function (obj) {
- var memoizer, args = arguments;
- if (resolve) {
- args = resolve(args);
- obj = args[0];
- }
- memoizer = map.get(obj);
- if (!memoizer) return;
- memoizer.delete.apply(this, slice.call(args, 1));
- }, length)
- )
- }
- );
- if (!options.refCounter) return memoized;
- defineProperties(memoized, {
- deleteRef: d(
- defineLength(function (obj) {
- var memoizer, args = arguments;
- if (resolve) {
- args = resolve(args);
- obj = args[0];
- }
- memoizer = map.get(obj);
- if (!memoizer) return null;
- return memoizer.deleteRef.apply(this, slice.call(args, 1));
- }, length)
- ),
- getRefCount: d(
- defineLength(function (obj) {
- var memoizer, args = arguments;
- if (resolve) {
- args = resolve(args);
- obj = args[0];
- }
- memoizer = map.get(obj);
- if (!memoizer) return 0;
- return memoizer.getRefCount.apply(this, slice.call(args, 1));
- }, length)
- )
- });
- return memoized;
- };
- };
|