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

hybridsjs / hybrids / 9387127968

05 Jun 2024 03:38PM UTC coverage: 46.684% (-53.3%) from 99.956%
9387127968

Pull #258

github

web-flow
Merge e936aa704 into 36d6e398d
Pull Request #258: feat: remove `content` property & add shadow mode detection to render property

611 of 1778 branches covered (34.36%)

69 of 97 new or added lines in 9 files covered. (71.13%)

1169 existing lines in 25 files now uncovered.

1049 of 2247 relevant lines covered (46.68%)

32.63 hits per line

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

64.49
/src/cache.js
1
import * as emitter from "./emitter.js";
2

3
const entries = new WeakMap();
2✔
4
const stack = new Set();
2✔
5

6
function dispatch(entry) {
7
  const contexts = [];
471✔
8
  let index = 0;
471✔
9

10
  while (entry) {
471✔
11
    entry.resolved = false;
626✔
12

13
    if (entry.contexts) {
626✔
14
      for (const context of entry.contexts) {
155✔
15
        if (!stack.has(context) && !contexts.includes(context)) {
155!
16
          contexts.push(context);
155✔
17
        }
18
      }
19
    }
20

21
    if (entry.observe) {
626✔
22
      emitter.add(entry.observe);
65✔
23
    }
24

25
    entry = contexts[index++];
626✔
26
  }
27
}
28

29
export function getEntry(target, key) {
30
  let map = entries.get(target);
915✔
31
  if (!map) {
915✔
32
    map = new Map();
93✔
33
    entries.set(target, map);
93✔
34
  }
35

36
  let entry = map.get(key);
915✔
37
  if (!entry) {
915✔
38
    entry = {
261✔
39
      key,
40
      target,
41
      value: undefined,
42
      assertValue: undefined,
43
      lastValue: undefined,
44
      resolved: false,
45
      contexts: undefined,
46
      deps: undefined,
47
      observe: undefined,
48
    };
49
    map.set(key, entry);
261✔
50
  }
51

52
  return entry;
915✔
53
}
54

55
export function getEntries(target) {
UNCOV
56
  const targetMap = entries.get(target);
×
UNCOV
57
  if (targetMap) return [...targetMap.values()];
×
UNCOV
58
  return [];
×
59
}
60

61
let context = null;
2✔
62
export function getCurrentValue() {
UNCOV
63
  return context?.value;
×
64
}
65

66
export function get(target, key, fn) {
67
  const entry = getEntry(target, key);
581✔
68

69
  if (context) {
581✔
70
    if (!entry.contexts) entry.contexts = new Set();
216✔
71
    if (!context.deps) context.deps = new Set();
216✔
72

73
    entry.contexts.add(context);
216✔
74
    context.deps.add(entry);
216✔
75
  }
76

77
  if (entry.resolved) return entry.value;
581✔
78

79
  if (entry.deps) {
399✔
80
    for (const depEntry of entry.deps) {
65✔
81
      depEntry.contexts.delete(entry);
72✔
82
    }
83
    entry.deps.clear();
65✔
84
  }
85

86
  const lastContext = context;
399✔
87

88
  try {
399✔
89
    if (stack.has(entry)) {
399!
UNCOV
90
      throw Error(`Circular get invocation is forbidden: '${key}'`);
×
91
    }
92

93
    context = entry;
399✔
94
    stack.add(entry);
399✔
95

96
    entry.value = fn(target, entry.assertValue);
399✔
97
    entry.resolved = true;
399✔
98

99
    context = lastContext;
399✔
100

101
    stack.delete(entry);
399✔
102
  } catch (e) {
UNCOV
103
    context = lastContext;
×
UNCOV
104
    stack.delete(entry);
×
105

UNCOV
106
    if (context) {
×
UNCOV
107
      context.deps.delete(entry);
×
UNCOV
108
      entry.contexts.delete(context);
×
109
    }
110

UNCOV
111
    throw e;
×
112
  }
113

114
  return entry.value;
399✔
115
}
116

117
export function assert(target, key, value) {
118
  const entry = getEntry(target, key);
74✔
119

120
  entry.value = undefined;
74✔
121
  entry.assertValue = value;
74✔
122

123
  dispatch(entry);
74✔
124
}
125

126
export function set(target, key, fn, value) {
UNCOV
127
  const entry = getEntry(target, key);
×
UNCOV
128
  const nextValue = fn(target, value, entry.value);
×
129

UNCOV
130
  if (nextValue !== entry.value) {
×
UNCOV
131
    entry.value = nextValue;
×
UNCOV
132
    entry.assertValue = undefined;
×
133

UNCOV
134
    dispatch(entry);
×
135
  }
136
}
137

138
export function observe(target, key, fn, callback) {
139
  const entry = getEntry(target, key);
172✔
140

141
  entry.observe = () => {
172✔
142
    const value = get(target, key, fn);
234✔
143

144
    if (value !== entry.lastValue) {
234!
145
      callback(target, value, entry.lastValue);
234✔
146
      entry.lastValue = value;
234✔
147
    }
148
  };
149

150
  try {
172✔
151
    entry.observe();
172✔
152
  } catch (e) {
UNCOV
153
    console.error(e);
×
154
  }
155

156
  return () => {
172✔
157
    entry.observe = undefined;
172✔
158
    entry.lastValue = undefined;
172✔
159
  };
160
}
161

162
const gc = new Set();
2✔
163
function deleteEntry(entry) {
UNCOV
164
  if (!gc.size) {
×
UNCOV
165
    setTimeout(() => {
×
UNCOV
166
      for (const e of gc) {
×
UNCOV
167
        if (!e.contexts || e.contexts.size === 0) {
×
UNCOV
168
          const targetMap = entries.get(e.target);
×
UNCOV
169
          targetMap.delete(e.key);
×
170
        }
171
      }
172

UNCOV
173
      gc.clear();
×
174
    });
175
  }
176

UNCOV
177
  gc.add(entry);
×
178
}
179

180
function invalidateEntry(entry, options) {
181
  dispatch(entry);
397✔
182

183
  if (options.clearValue) {
397!
UNCOV
184
    entry.value = undefined;
×
UNCOV
185
    entry.assertValue = undefined;
×
UNCOV
186
    entry.lastValue = undefined;
×
187
  }
188

189
  if (options.deleteEntry) {
397!
UNCOV
190
    if (entry.deps) {
×
UNCOV
191
      for (const depEntry of entry.deps) {
×
UNCOV
192
        depEntry.contexts.delete(entry);
×
193
      }
UNCOV
194
      entry.deps = undefined;
×
195
    }
196

UNCOV
197
    if (entry.contexts) {
×
UNCOV
198
      for (const context of entry.contexts) {
×
UNCOV
199
        context.deps.delete(entry);
×
200
      }
UNCOV
201
      entry.contexts = undefined;
×
202
    }
203

UNCOV
204
    deleteEntry(entry);
×
205
  }
206
}
207

208
export function invalidate(target, key, options = {}) {
88✔
209
  const entry = getEntry(target, key);
88✔
210
  invalidateEntry(entry, options);
88✔
211
}
212

213
export function invalidateAll(target, options = {}) {
104✔
214
  const targetMap = entries.get(target);
104✔
215
  if (targetMap) {
104!
216
    for (const entry of targetMap.values()) {
104✔
217
      invalidateEntry(entry, options);
309✔
218
    }
219
  }
220
}
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