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

preactjs / preact / 17693508934

13 Sep 2025 07:24AM UTC coverage: 98.512% (-1.0%) from 99.535%
17693508934

Pull #4916

github

web-flow
Merge 18b4a3fcd into 027142c20
Pull Request #4916: See whether always cloning improves perf and helps with mem issue

551 of 573 branches covered (96.16%)

2118 of 2150 relevant lines covered (98.51%)

820.28 hits per line

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

97.71
/debug/src/component-stack.js
1
import { options, Fragment } from 'preact';
1✔
2

1✔
3
/**
1✔
4
 * Get human readable name of the component/dom node
1✔
5
 * @param {import('./internal').VNode} vnode
6
 * @param {import('./internal').VNode} vnode
7
 * @returns {string}
8
 */
1✔
9
export function getDisplayName(vnode) {
1✔
10
        if (vnode.type === Fragment) {
1✔
11
                return 'Fragment';
117✔
12
        } else if (typeof vnode.type == 'function') {
117✔
13
                return vnode.type.displayName || vnode.type.name;
102✔
14
        } else if (typeof vnode.type == 'string') {
51✔
15
                return vnode.type;
51✔
16
        }
51✔
17

18
        return '#text';
51✔
19
}
51✔
20

21
/**
22
 * Used to keep track of the currently rendered `vnode` and print it
51✔
23
 * in debug messages.
51✔
24
 */
25
let renderStack = [];
45✔
26

45✔
27
/**
45✔
28
 * Keep track of the current owners. An owner describes a component
45✔
29
 * which was responsible to render a specific `vnode`. This exclude
45✔
30
 * children that are passed via `props.children`, because they belong
45✔
31
 * to the parent owner.
45✔
32
 *
45✔
33
 * ```jsx
45✔
34
 * const Foo = props => <div>{props.children}</div> // div's owner is Foo
45✔
35
 * const Bar = props => {
45✔
36
 *   return (
45✔
37
 *     <Foo><span /></Foo> // Foo's owner is Bar, span's owner is Bar
45✔
38
 *   )
39
 * }
45✔
40
 * ```
41
 *
42
 * Note: A `vnode` may be hoisted to the root scope due to compiler
45✔
43
 * optimiztions. In these cases the owner will be different.
45✔
44
 */
45✔
45
let ownerStack = [];
51✔
46

6✔
47
const ownerMap = new WeakMap();
1✔
48

1✔
49
/**
1✔
50
 * Get the currently rendered `vnode`
51
 * @returns {import('./internal').VNode | null}
1✔
52
 */
53
export function getCurrentVNode() {
1✔
54
        return renderStack.length > 0 ? renderStack[renderStack.length - 1] : null;
1✔
55
}
3✔
56

3✔
57
/**
3✔
58
 * If the user doesn't have `@babel/plugin-transform-react-jsx-source`
59
 * somewhere in his tool chain we can't print the filename and source
3✔
60
 * location of a component. In that case we just omit that, but we'll
61
 * print a helpful message to the console, notifying the user of it.
62
 */
3✔
63
let showJsxSourcePluginWarning = true;
3✔
64

3✔
65
/**
3✔
66
 * Check if a `vnode` is a possible owner.
3✔
67
 * @param {import('./internal').VNode} vnode
3✔
68
 */
3✔
69
function isPossibleOwner(vnode) {
1!
70
        return typeof vnode.type == 'function' && vnode.type != Fragment;
1✔
71
}
1,403✔
72

1,403✔
73
/**
1,403✔
74
 * Return the component stack that was captured up to this point.
1,403✔
75
 * @param {import('./internal').VNode} vnode
76
 * @returns {string}
1,403✔
77
 */
78
export function getOwnerStack(vnode) {
1,403✔
79
        const stack = [vnode];
753✔
80
        let next = vnode;
55✔
81
        while ((next = ownerMap.get(next)) != null) {
55✔
82
                stack.push(next);
55✔
83
        }
55✔
84

85
        return stack.reduce((acc, owner) => {
55!
86
                acc += `  in ${getDisplayName(owner)}`;
55✔
87

55✔
88
                const source = owner.__source;
55✔
89
                if (source) {
55✔
90
                        acc += ` (at ${source.fileName}:${source.lineNumber})`;
55!
91
                } else if (showJsxSourcePluginWarning) {
×
92
                        console.warn(
×
93
                                'Add @babel/plugin-transform-react-jsx-source to get a more detailed component stack. Note that you should not add it to production builds of your App for bundle size reasons.'
✔
94
                        );
95
                }
96
                showJsxSourcePluginWarning = false;
5✔
97

5✔
98
                return (acc += '\n');
5✔
99
        }, '');
5✔
100
}
5✔
101

5✔
102
/**
5✔
103
 * Setup code to capture the component trace while rendering. Note that
5✔
104
 * we cannot simply traverse `vnode._parent` upwards, because we have some
5✔
105
 * debug messages for `this.setState` where the `vnode` is `undefined`.
106
 */
107
export function setupComponentStack() {
5✔
108
        let oldDiff = options._diff;
5✔
109
        let oldDiffed = options.diffed;
5✔
110
        let oldRoot = options._root;
5✔
111
        let oldVNode = options.vnode;
5✔
112
        let oldRender = options._render;
5✔
113

114
        options.diffed = vnode => {
5✔
115
                if (isPossibleOwner(vnode)) {
5✔
116
                        ownerStack.pop();
5✔
117
                }
555✔
118
                renderStack.pop();
555✔
119
                if (oldDiffed) oldDiffed(vnode);
555✔
120
        };
141✔
121

141✔
122
        options._diff = vnode => {
555✔
123
                if (isPossibleOwner(vnode)) {
5✔
124
                        renderStack.push(vnode);
5✔
125
                }
126
                if (oldDiff) oldDiff(vnode);
575✔
127
        };
575✔
128

148✔
129
        options._root = (vnode, parent) => {
575✔
130
                ownerStack = [];
5✔
131
                if (oldRoot) oldRoot(vnode, parent);
5✔
132
        };
83✔
133

83✔
134
        options.vnode = vnode => {
83✔
135
                ownerMap.set(
5✔
136
                        vnode,
5✔
137
                        ownerStack.length > 0 ? ownerStack[ownerStack.length - 1] : null
622✔
138
                );
386✔
139
                if (oldVNode) oldVNode(vnode);
386✔
140
        };
386✔
141

386✔
142
        options._render = vnode => {
622✔
143
                if (isPossibleOwner(vnode)) {
5✔
144
                        ownerStack.push(vnode);
5✔
145
                }
5✔
146

5✔
147
                if (oldRender) oldRender(vnode);
5✔
148
        };
5✔
149
}
5✔
150

151
/**
5✔
152
 * Return the component stack that was captured up to this point.
153
 * @returns {string}
5✔
154
 */
5✔
155
export function captureOwnerStack() {
55✔
156
        return getOwnerStack(getCurrentVNode());
1✔
157
}
1✔
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