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

preactjs / preact / 18079560091

28 Sep 2025 08:41PM UTC coverage: 42.93% (-56.6%) from 99.535%
18079560091

Pull #4925

github

web-flow
Merge 72c50c134 into 027142c20
Pull Request #4925: test: Switch tests to use `.jsx` file extension

86 of 128 branches covered (67.19%)

923 of 2150 relevant lines covered (42.93%)

1.7 hits per line

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

46.56
/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';
10✔
12
        } else if (typeof vnode.type == 'function') {
10!
13
                return vnode.type.displayName || vnode.type.name;
10✔
14
        } else if (typeof vnode.type == 'string') {
10!
15
                return vnode.type;
×
16
        }
×
17

18
        return '#text';
×
19
}
×
20

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

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

×
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
}
×
56

×
57
/**
×
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
×
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
 */
×
63
let showJsxSourcePluginWarning = true;
×
64

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

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

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

4✔
88
                const source = owner.__source;
4✔
89
                if (source) {
4✔
90
                        acc += ` (at ${source.fileName}:${source.lineNumber})`;
4✔
91
                } else if (showJsxSourcePluginWarning) {
1✔
92
                        console.warn(
1✔
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.'
1!
94
                        );
95
                }
96
                showJsxSourcePluginWarning = false;
×
97

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

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

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

6✔
122
        options._diff = vnode => {
24!
123
                if (isPossibleOwner(vnode)) {
×
124
                        renderStack.push(vnode);
✔
125
                }
126
                if (oldDiff) oldDiff(vnode);
24✔
127
        };
24✔
128

6✔
129
        options._root = (vnode, parent) => {
24!
130
                ownerStack = [];
×
131
                if (oldRoot) oldRoot(vnode, parent);
✔
132
        };
6✔
133

6✔
134
        options.vnode = vnode => {
6!
135
                ownerMap.set(
×
136
                        vnode,
✔
137
                        ownerStack.length > 0 ? ownerStack[ownerStack.length - 1] : null
24✔
138
                );
12✔
139
                if (oldVNode) oldVNode(vnode);
12✔
140
        };
12✔
141

12✔
142
        options._render = vnode => {
12!
143
                if (isPossibleOwner(vnode)) {
×
144
                        ownerStack.push(vnode);
×
145
                }
×
146

×
147
                if (oldRender) oldRender(vnode);
×
148
        };
×
149
}
×
150

151
/**
×
152
 * Return the component stack that was captured up to this point.
153
 * @returns {string}
×
154
 */
×
155
export function captureOwnerStack() {
4✔
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