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

infernojs / inferno / 13603195751

01 Mar 2025 09:03AM UTC coverage: 92.867% (-0.5%) from 93.357%
13603195751

push

github

Havunen
test github actions, instead of travis

1841 of 2109 branches covered (87.29%)

4049 of 4360 relevant lines covered (92.87%)

4153.88 hits per line

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

97.64
/packages/inferno-server/src/renderToString.ts
1
import { EMPTY_OBJ } from 'inferno';
17✔
2
import {
3
  isArray,
4
  isFunction,
5
  isInvalid,
6
  isNull,
7
  isNullOrUndef,
8
  isNumber,
9
  isString,
10
  throwError,
11
} from 'inferno-shared';
17✔
12
import { ChildFlags, VNodeFlags } from 'inferno-vnode-flags';
17✔
13
import { renderStyleAttribute } from './prop-renderers';
17✔
14
import {
15
  createDerivedState,
16
  escapeText,
17
  isAttributeNameSafe,
18
  renderFunctionalComponent,
19
  voidElements,
20
} from './utils';
17✔
21

22
function renderVNodeToString(vNode, parent, context): string {
23
  const flags = vNode.flags;
434✔
24
  const type = vNode.type;
434✔
25
  const props = vNode.props || EMPTY_OBJ;
434✔
26
  const children = vNode.children;
434✔
27

28
  if ((flags & VNodeFlags.Component) !== 0) {
434✔
29
    const isClass = flags & VNodeFlags.ComponentClass;
83✔
30

31
    if (isClass) {
83✔
32
      const instance = new type(props, context);
39✔
33
      const hasNewAPI = Boolean(type.getDerivedStateFromProps);
39✔
34
      instance.$BS = false;
39✔
35
      instance.$SSR = true;
39✔
36
      let childContext;
37
      if (isFunction(instance.getChildContext)) {
39✔
38
        childContext = instance.getChildContext();
10✔
39
      }
40

41
      if (isNullOrUndef(childContext)) {
39✔
42
        childContext = context;
29✔
43
      } else {
44
        childContext = { ...context, ...childContext };
10✔
45
      }
46
      if (instance.props === EMPTY_OBJ) {
39✔
47
        instance.props = props;
25✔
48
      }
49
      instance.context = context;
39✔
50
      if (!hasNewAPI && isFunction(instance.componentWillMount)) {
39✔
51
        instance.$BR = true;
10✔
52
        instance.componentWillMount();
10✔
53
        instance.$BR = false;
10✔
54
        const pending = instance.$PS;
10✔
55

56
        if (pending) {
10✔
57
          const state = instance.state;
4✔
58

59
          if (state === null) {
4✔
60
            instance.state = pending;
2✔
61
          } else {
62
            for (const key in pending) {
2✔
63
              state[key] = pending[key];
2✔
64
            }
65
          }
66
          instance.$PSS = false;
4✔
67
          instance.$PS = null;
4✔
68
        }
69
      }
70
      if (hasNewAPI) {
39✔
71
        instance.state = createDerivedState(instance, props, instance.state);
1✔
72
      }
73
      const renderOutput = instance.render(
39✔
74
        props,
75
        instance.state,
76
        instance.context,
77
      );
78
      // In case render returns invalid stuff
79
      if (isInvalid(renderOutput)) {
39✔
80
        return '<!--!-->';
4✔
81
      }
82
      if (isString(renderOutput)) {
35✔
83
        return escapeText(renderOutput);
2✔
84
      }
85
      if (isNumber(renderOutput)) {
33✔
86
        return renderOutput + '';
1✔
87
      }
88
      return renderVNodeToString(renderOutput, vNode, childContext);
32✔
89
    } else {
90
      const renderOutput = renderFunctionalComponent(vNode, context);
44✔
91

92
      if (isInvalid(renderOutput)) {
44✔
93
        return '<!--!-->';
1✔
94
      }
95
      if (isString(renderOutput)) {
43✔
96
        return escapeText(renderOutput);
1✔
97
      }
98
      if (isNumber(renderOutput)) {
42✔
99
        return renderOutput + '';
1✔
100
      }
101
      return renderVNodeToString(renderOutput, vNode, context);
41✔
102
    }
103
  } else if ((flags & VNodeFlags.Element) !== 0) {
351✔
104
    let renderedString = `<${type}`;
266✔
105
    let html;
106

107
    const isVoidElement = voidElements.has(type);
266✔
108
    const className = vNode.className;
266✔
109

110
    if (isString(className)) {
266✔
111
      renderedString += ` class="${escapeText(className)}"`;
17✔
112
    } else if (isNumber(className)) {
249✔
113
      renderedString += ` class="${className}"`;
1✔
114
    }
115

116
    if (!isNull(props)) {
266✔
117
      for (const prop in props) {
266✔
118
        const value = props[prop];
56✔
119

120
        switch (prop) {
56!
121
          case 'dangerouslySetInnerHTML':
122
            html = value.__html;
1✔
123
            break;
1✔
124
          case 'style':
125
            if (!isNullOrUndef(props.style)) {
16✔
126
              renderedString += renderStyleAttribute(props.style);
14✔
127
            }
128
            break;
16✔
129
          case 'children':
130
          case 'className':
131
            // Ignore
132
            break;
×
133
          case 'defaultValue':
134
            // Use default values if normal values are not present
135
            if (!props.value) {
4✔
136
              renderedString += ` value="${
3✔
137
                isString(value) ? escapeText(value) : value
3✔
138
              }"`;
139
            }
140
            break;
4✔
141
          case 'defaultChecked':
142
            // Use default values if normal values are not present
143
            if (!props.checked) {
1✔
144
              renderedString += ` checked="${value}"`;
1✔
145
            }
146
            break;
1✔
147
          default:
148
            if (isAttributeNameSafe(prop)) {
34✔
149
              if (isString(value)) {
31✔
150
                renderedString += ` ${prop}="${escapeText(value)}"`;
29✔
151
              } else if (isNumber(value)) {
2✔
152
                renderedString += ` ${prop}="${value}"`;
1✔
153
              } else if (value === true) {
1✔
154
                renderedString += ` ${prop}`;
1✔
155
              }
156
            }
157

158
            break;
34✔
159
        }
160
      }
161
      if (
266✔
162
        type === 'option' &&
270✔
163
        typeof props.value !== 'undefined' &&
164
        props.value === parent.props.value
165
      ) {
166
        // Parent value sets children value
167
        renderedString += ` selected`;
1✔
168
      }
169
    }
170
    if (isVoidElement) {
266✔
171
      renderedString += `>`;
9✔
172
    } else {
173
      renderedString += `>`;
257✔
174
      const childFlags = vNode.childFlags;
257✔
175

176
      if (childFlags === ChildFlags.HasVNodeChildren) {
257✔
177
        renderedString += renderVNodeToString(children, vNode, context);
66✔
178
      } else if (childFlags & ChildFlags.MultipleChildren) {
191✔
179
        for (let i = 0, len = children.length; i < len; ++i) {
40✔
180
          renderedString += renderVNodeToString(children[i], vNode, context);
105✔
181
        }
182
      } else if (childFlags === ChildFlags.HasTextChildren) {
151✔
183
        renderedString += children === '' ? ' ' : escapeText(children);
106✔
184
      } else if (html) {
45✔
185
        renderedString += html;
1✔
186
      }
187
      if (!isVoidElement) {
257✔
188
        renderedString += `</${type}>`;
257✔
189
      }
190
    }
191

192
    if (String(type).match(/[\s\n/='"\0<>]/)) {
266✔
193
      throw renderedString;
5✔
194
    }
195

196
    return renderedString;
261✔
197
  } else if ((flags & VNodeFlags.Text) !== 0) {
85✔
198
    return children === '' ? ' ' : escapeText(children);
71!
199
  } else if (isArray(vNode) || (flags & VNodeFlags.Fragment) !== 0) {
14✔
200
    const childFlags = vNode.childFlags;
12✔
201

202
    if (
12✔
203
      childFlags === ChildFlags.HasVNodeChildren ||
26✔
204
      (isArray(vNode) && vNode.length === 0)
205
    ) {
206
      return '<!--!-->';
2✔
207
    } else if (childFlags & ChildFlags.MultipleChildren || isArray(vNode)) {
10✔
208
      const tmpNodes = isArray(vNode) ? vNode : children;
10✔
209
      let renderedString = '';
10✔
210

211
      for (let i = 0, len = tmpNodes.length; i < len; ++i) {
10✔
212
        renderedString += renderVNodeToString(tmpNodes[i], vNode, context);
28✔
213
      }
214

215
      return renderedString;
10✔
216
    }
217
  } else {
218
    if (process.env.NODE_ENV !== 'production') {
2✔
219
      if (typeof vNode === 'object') {
2✔
220
        throwError(
1✔
221
          `renderToString() received an object that's not a valid VNode, you should stringify it first. Object: "${JSON.stringify(
222
            vNode,
223
          )}".`,
224
        );
225
      } else {
226
        throwError(
1✔
227
          `renderToString() expects a valid VNode, instead it received an object with the type "${typeof vNode}".`,
228
        );
229
      }
230
    }
231
    throwError();
×
232
  }
233

234
  return '';
×
235
}
236

237
export function renderToString(input: any): string {
160✔
238
  return renderVNodeToString(input, {}, {});
162✔
239
}
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