UNPKG

2.38 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9Object.defineProperty(exports, "__esModule", { value: true });
10exports.memoize = void 0;
11/**
12 * A decorator that memoizes methods and getters.
13 *
14 * **Note**: Be cautious where and how to use this decorator as the size of the cache will grow unbounded.
15 *
16 * @see https://en.wikipedia.org/wiki/Memoization
17 */
18function memoize(target, propertyKey, descriptor) {
19 const descriptorPropertyName = descriptor.get ? 'get' : 'value';
20 const originalMethod = descriptor[descriptorPropertyName];
21 if (typeof originalMethod !== 'function') {
22 throw new Error('Memoize decorator can only be used on methods or get accessors.');
23 }
24 const cache = new Map();
25 return {
26 ...descriptor,
27 [descriptorPropertyName]: function (...args) {
28 for (const arg of args) {
29 if (!isJSONSerializable(arg)) {
30 throw new Error(`Argument ${isNonPrimitive(arg) ? arg.toString() : arg} is JSON serializable.`);
31 }
32 }
33 const key = JSON.stringify(args);
34 if (cache.has(key)) {
35 return cache.get(key);
36 }
37 const result = originalMethod.apply(this, args);
38 cache.set(key, result);
39 return result;
40 },
41 };
42}
43exports.memoize = memoize;
44/** Method to check if value is a non primitive. */
45function isNonPrimitive(value) {
46 return ((value !== null && typeof value === 'object') ||
47 typeof value === 'function' ||
48 typeof value === 'symbol');
49}
50/** Method to check if the values are JSON serializable */
51function isJSONSerializable(value) {
52 if (!isNonPrimitive(value)) {
53 // Can be seralized since it's a primitive.
54 return true;
55 }
56 let nestedValues;
57 if (Array.isArray(value)) {
58 // It's an array, check each item.
59 nestedValues = value;
60 }
61 else if (Object.prototype.toString.call(value) === '[object Object]') {
62 // It's a plain object, check each value.
63 nestedValues = Object.values(value);
64 }
65 if (!nestedValues || nestedValues.some((v) => !isJSONSerializable(v))) {
66 return false;
67 }
68 return true;
69}