• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yiminghe / next-compose-middlewares / 11856910917

15 Nov 2024 01:12PM UTC coverage: 66.724%. Remained the same
11856910917

push

github

yiminghe
docs

54 of 125 branches covered (43.2%)

Branch coverage included in aggregate %.

2 of 3 new or added lines in 1 file covered. (66.67%)

335 of 458 relevant lines covered (73.14%)

3.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.14
/source/cache.ts
1
import { getNextContext } from './set-context';
2

3
const UNTERMINATED = 0;
3✔
4
const TERMINATED = 1;
3✔
5
const ERRORED = 2;
3✔
6

7
type UnterminatedCacheNode<T> = {
8
  s: 0;
9
  v: void;
10
  o: null | WeakMap<Function | Object, CacheNode<T>>;
11
  p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>;
12
};
13

14
type TerminatedCacheNode<T> = {
15
  s: 1;
16
  v: T;
17
  o: null | WeakMap<Function | Object, CacheNode<T>>;
18
  p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>;
19
};
20

21
type ErroredCacheNode<T> = {
22
  s: 2;
23
  v: any;
24
  o: null | WeakMap<Function | Object, CacheNode<T>>;
25
  p: null | Map<string | number | null | void | symbol | boolean, CacheNode<T>>;
26
};
27

28
type CacheNode<T> =
29
  | TerminatedCacheNode<T>
30
  | UnterminatedCacheNode<T>
31
  | ErroredCacheNode<T>;
32

33
function createCacheRoot<T>(): WeakMap<Function | Object, CacheNode<T>> {
34
  return new WeakMap();
4✔
35
}
36

37
function createCacheNode<T>(): CacheNode<T> {
38
  return {
4✔
39
    s: UNTERMINATED, // status, represents whether the cached computation returned a value or threw an error
40
    v: undefined, // value, either the cached result or an error, depending on s
41
    o: null, // object cache, a WeakMap where non-primitive arguments are stored
42
    p: null, // primitive cache, a regular Map where primitive arguments are stored.
43
  };
44
}
45
const key = '__next_compose_middlewares_cache_root';
3✔
46

47
function getFnMap() {
48
  const context: any = getNextContext();
16✔
49
  context[key] = context[key] || createCacheRoot();
16✔
50
  return context[key];
16✔
51
}
52

53
/**
54
 * cache function call on request level
55
 * @public
56
 */
57
export function cache<T extends Function>(fn: T): T {
58
  return function () {
2✔
59
    const fnMap: WeakMap<any, CacheNode<T>> = getFnMap();
16✔
60
    const fnNode = fnMap.get(fn);
16✔
61
    let cacheNode: CacheNode<T>;
62
    if (fnNode === undefined) {
16✔
63
      cacheNode = createCacheNode();
4✔
64
      fnMap.set(fn, cacheNode);
4✔
65
    } else {
66
      cacheNode = fnNode;
12✔
67
    }
68
    for (let i = 0, l = arguments.length; i < l; i++) {
16✔
69
      const arg = arguments[i];
×
70
      if (
×
71
        typeof arg === 'function' ||
×
72
        (typeof arg === 'object' && arg !== null)
73
      ) {
74
        // Objects go into a WeakMap
75
        let objectCache = cacheNode.o;
×
76
        if (objectCache === null) {
×
77
          cacheNode.o = objectCache = new WeakMap();
×
78
        }
79
        const objectNode = objectCache.get(arg);
×
80
        if (objectNode === undefined) {
×
81
          cacheNode = createCacheNode();
×
82
          objectCache.set(arg, cacheNode);
×
83
        } else {
84
          cacheNode = objectNode;
×
85
        }
86
      } else {
87
        // Primitives go into a regular Map
88
        let primitiveCache = cacheNode.p;
×
89
        if (primitiveCache === null) {
×
90
          cacheNode.p = primitiveCache = new Map();
×
91
        }
92
        const primitiveNode = primitiveCache.get(arg);
×
93
        if (primitiveNode === undefined) {
×
94
          cacheNode = createCacheNode();
×
95
          primitiveCache.set(arg, cacheNode);
×
96
        } else {
97
          cacheNode = primitiveNode;
×
98
        }
99
      }
100
    }
101
    if (cacheNode.s === TERMINATED) {
16✔
102
      return cacheNode.v;
12✔
103
    }
104
    if (cacheNode.s === ERRORED) {
4!
105
      throw cacheNode.v;
×
106
    }
107
    try {
4✔
108
      // $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.
109
      const result = fn.apply(null, arguments);
4✔
110
      const terminatedNode: TerminatedCacheNode<any> = cacheNode as any;
4✔
111
      terminatedNode.s = TERMINATED;
4✔
112
      terminatedNode.v = result;
4✔
113
      return result;
4✔
114
    } catch (error) {
115
      // We store the first error that's thrown and rethrow it.
NEW
116
      const erroredNode: ErroredCacheNode<any> = cacheNode as any;
×
117
      erroredNode.s = ERRORED;
×
118
      erroredNode.v = error;
×
119
      throw error;
×
120
    }
121
  } as any;
122
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc