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

yiminghe / next-compose-middlewares / 11850728506

15 Nov 2024 05:17AM UTC coverage: 66.724% (-2.7%) from 69.396%
11850728506

push

github

web-flow
add cache

54 of 125 branches covered (43.2%)

Branch coverage included in aggregate %.

26 of 49 new or added lines in 1 file covered. (53.06%)

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