isomorfeus-preact 10.8.0 → 10.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isomorfeus_preact/preact/function_component/api.rb +24 -0
  3. data/lib/preact/version.rb +1 -1
  4. data/node_modules/.package-lock.json +5 -7
  5. data/node_modules/preact/compat/dist/compat.js +2 -2
  6. data/node_modules/preact/compat/dist/compat.js.map +1 -1
  7. data/node_modules/preact/compat/dist/compat.mjs +2 -2
  8. data/node_modules/preact/compat/dist/compat.module.js +2 -2
  9. data/node_modules/preact/compat/dist/compat.module.js.map +1 -1
  10. data/node_modules/preact/compat/dist/compat.umd.js +2 -2
  11. data/node_modules/preact/compat/dist/compat.umd.js.map +1 -1
  12. data/node_modules/preact/compat/src/index.d.ts +164 -155
  13. data/node_modules/preact/compat/src/index.js +223 -187
  14. data/node_modules/preact/compat/src/render.js +238 -238
  15. data/node_modules/preact/debug/dist/debug.js +2 -2
  16. data/node_modules/preact/debug/dist/debug.js.map +1 -1
  17. data/node_modules/preact/debug/dist/debug.mjs +2 -2
  18. data/node_modules/preact/debug/dist/debug.module.js +2 -2
  19. data/node_modules/preact/debug/dist/debug.module.js.map +1 -1
  20. data/node_modules/preact/debug/dist/debug.umd.js +2 -2
  21. data/node_modules/preact/debug/dist/debug.umd.js.map +1 -1
  22. data/node_modules/preact/debug/src/debug.js +437 -444
  23. data/node_modules/preact/devtools/dist/devtools.js +2 -2
  24. data/node_modules/preact/devtools/dist/devtools.js.map +1 -1
  25. data/node_modules/preact/devtools/dist/devtools.mjs +2 -2
  26. data/node_modules/preact/devtools/dist/devtools.module.js +2 -2
  27. data/node_modules/preact/devtools/dist/devtools.module.js.map +1 -1
  28. data/node_modules/preact/devtools/dist/devtools.umd.js +2 -2
  29. data/node_modules/preact/devtools/dist/devtools.umd.js.map +1 -1
  30. data/node_modules/preact/devtools/src/devtools.js +10 -10
  31. data/node_modules/preact/hooks/dist/hooks.js +2 -2
  32. data/node_modules/preact/hooks/dist/hooks.js.map +1 -1
  33. data/node_modules/preact/hooks/dist/hooks.mjs +2 -2
  34. data/node_modules/preact/hooks/dist/hooks.module.js +2 -2
  35. data/node_modules/preact/hooks/dist/hooks.module.js.map +1 -1
  36. data/node_modules/preact/hooks/dist/hooks.umd.js +2 -2
  37. data/node_modules/preact/hooks/dist/hooks.umd.js.map +1 -1
  38. data/node_modules/preact/hooks/src/index.js +417 -404
  39. data/node_modules/preact/hooks/src/internal.d.ts +3 -0
  40. data/node_modules/preact/package.json +304 -304
  41. data/node_modules/preact/src/jsx.d.ts +1014 -1013
  42. data/package.json +1 -1
  43. metadata +4 -4
@@ -1,444 +1,437 @@
1
- import { checkPropTypes } from './check-props';
2
- import { options, Component } from 'preact';
3
- import {
4
- ELEMENT_NODE,
5
- DOCUMENT_NODE,
6
- DOCUMENT_FRAGMENT_NODE
7
- } from './constants';
8
- import {
9
- getOwnerStack,
10
- setupComponentStack,
11
- getCurrentVNode,
12
- getDisplayName
13
- } from './component-stack';
14
- import { assign } from './util';
15
-
16
- const isWeakMapSupported = typeof WeakMap == 'function';
17
-
18
- function getClosestDomNodeParent(parent) {
19
- if (!parent) return {};
20
- if (typeof parent.type == 'function') {
21
- return getClosestDomNodeParent(parent._parent);
22
- }
23
- return parent;
24
- }
25
-
26
- export function initDebug() {
27
- setupComponentStack();
28
-
29
- let hooksAllowed = false;
30
-
31
- /* eslint-disable no-console */
32
- let oldBeforeDiff = options._diff;
33
- let oldDiffed = options.diffed;
34
- let oldVnode = options.vnode;
35
- let oldCatchError = options._catchError;
36
- let oldRoot = options._root;
37
- let oldHook = options._hook;
38
- const warnedComponents = !isWeakMapSupported
39
- ? null
40
- : {
41
- useEffect: new WeakMap(),
42
- useLayoutEffect: new WeakMap(),
43
- lazyPropTypes: new WeakMap()
44
- };
45
- const deprecations = [];
46
-
47
- options._catchError = (error, vnode, oldVNode, errorInfo) => {
48
- let component = vnode && vnode._component;
49
- if (component && typeof error.then == 'function') {
50
- const promise = error;
51
- error = new Error(
52
- `Missing Suspense. The throwing component was: ${getDisplayName(vnode)}`
53
- );
54
-
55
- let parent = vnode;
56
- for (; parent; parent = parent._parent) {
57
- if (parent._component && parent._component._childDidSuspend) {
58
- error = promise;
59
- break;
60
- }
61
- }
62
-
63
- // We haven't recovered and we know at this point that there is no
64
- // Suspense component higher up in the tree
65
- if (error instanceof Error) {
66
- throw error;
67
- }
68
- }
69
-
70
- try {
71
- errorInfo = errorInfo || {};
72
- errorInfo.componentStack = getOwnerStack(vnode);
73
- oldCatchError(error, vnode, oldVNode, errorInfo);
74
-
75
- // when an error was handled by an ErrorBoundary we will nontheless emit an error
76
- // event on the window object. This is to make up for react compatibility in dev mode
77
- // and thus make the Next.js dev overlay work.
78
- if (typeof error.then != 'function') {
79
- setTimeout(() => {
80
- throw error;
81
- });
82
- }
83
- } catch (e) {
84
- throw e;
85
- }
86
- };
87
-
88
- options._root = (vnode, parentNode) => {
89
- if (!parentNode) {
90
- throw new Error(
91
- 'Undefined parent passed to render(), this is the second argument.\n' +
92
- 'Check if the element is available in the DOM/has the correct id.'
93
- );
94
- }
95
-
96
- let isValid;
97
- switch (parentNode.nodeType) {
98
- case ELEMENT_NODE:
99
- case DOCUMENT_FRAGMENT_NODE:
100
- case DOCUMENT_NODE:
101
- isValid = true;
102
- break;
103
- default:
104
- isValid = false;
105
- }
106
-
107
- if (!isValid) {
108
- let componentName = getDisplayName(vnode);
109
- throw new Error(
110
- `Expected a valid HTML node as a second argument to render. Received ${parentNode} instead: render(<${componentName} />, ${parentNode});`
111
- );
112
- }
113
-
114
- if (oldRoot) oldRoot(vnode, parentNode);
115
- };
116
-
117
- options._diff = vnode => {
118
- let { type, _parent: parent } = vnode;
119
- let parentVNode = getClosestDomNodeParent(parent);
120
-
121
- hooksAllowed = true;
122
-
123
- if (type === undefined) {
124
- throw new Error(
125
- 'Undefined component passed to createElement()\n\n' +
126
- 'You likely forgot to export your component or might have mixed up default and named imports' +
127
- serializeVNode(vnode) +
128
- `\n\n${getOwnerStack(vnode)}`
129
- );
130
- } else if (type != null && typeof type == 'object') {
131
- if (type._children !== undefined && type._dom !== undefined) {
132
- throw new Error(
133
- `Invalid type passed to createElement(): ${type}\n\n` +
134
- 'Did you accidentally pass a JSX literal as JSX twice?\n\n' +
135
- ` let My${getDisplayName(vnode)} = ${serializeVNode(type)};\n` +
136
- ` let vnode = <My${getDisplayName(vnode)} />;\n\n` +
137
- 'This usually happens when you export a JSX literal and not the component.' +
138
- `\n\n${getOwnerStack(vnode)}`
139
- );
140
- }
141
-
142
- throw new Error(
143
- 'Invalid type passed to createElement(): ' +
144
- (Array.isArray(type) ? 'array' : type)
145
- );
146
- }
147
-
148
- if (
149
- (type === 'thead' || type === 'tfoot' || type === 'tbody') &&
150
- parentVNode.type !== 'table'
151
- ) {
152
- console.error(
153
- 'Improper nesting of table. Your <thead/tbody/tfoot> should have a <table> parent.' +
154
- serializeVNode(vnode) +
155
- `\n\n${getOwnerStack(vnode)}`
156
- );
157
- } else if (
158
- type === 'tr' &&
159
- parentVNode.type !== 'thead' &&
160
- parentVNode.type !== 'tfoot' &&
161
- parentVNode.type !== 'tbody' &&
162
- parentVNode.type !== 'table'
163
- ) {
164
- console.error(
165
- 'Improper nesting of table. Your <tr> should have a <thead/tbody/tfoot/table> parent.' +
166
- serializeVNode(vnode) +
167
- `\n\n${getOwnerStack(vnode)}`
168
- );
169
- } else if (type === 'td' && parentVNode.type !== 'tr') {
170
- console.error(
171
- 'Improper nesting of table. Your <td> should have a <tr> parent.' +
172
- serializeVNode(vnode) +
173
- `\n\n${getOwnerStack(vnode)}`
174
- );
175
- } else if (type === 'th' && parentVNode.type !== 'tr') {
176
- console.error(
177
- 'Improper nesting of table. Your <th> should have a <tr>.' +
178
- serializeVNode(vnode) +
179
- `\n\n${getOwnerStack(vnode)}`
180
- );
181
- }
182
-
183
- if (
184
- vnode.ref !== undefined &&
185
- typeof vnode.ref != 'function' &&
186
- typeof vnode.ref != 'object' &&
187
- !('$$typeof' in vnode) // allow string refs when preact-compat is installed
188
- ) {
189
- throw new Error(
190
- `Component's "ref" property should be a function, or an object created ` +
191
- `by createRef(), but got [${typeof vnode.ref}] instead\n` +
192
- serializeVNode(vnode) +
193
- `\n\n${getOwnerStack(vnode)}`
194
- );
195
- }
196
-
197
- if (typeof vnode.type == 'string') {
198
- for (const key in vnode.props) {
199
- if (
200
- key[0] === 'o' &&
201
- key[1] === 'n' &&
202
- typeof vnode.props[key] != 'function' &&
203
- vnode.props[key] != null
204
- ) {
205
- throw new Error(
206
- `Component's "${key}" property should be a function, ` +
207
- `but got [${typeof vnode.props[key]}] instead\n` +
208
- serializeVNode(vnode) +
209
- `\n\n${getOwnerStack(vnode)}`
210
- );
211
- }
212
- }
213
- }
214
-
215
- // Check prop-types if available
216
- if (typeof vnode.type == 'function' && vnode.type.propTypes) {
217
- if (
218
- vnode.type.displayName === 'Lazy' &&
219
- warnedComponents &&
220
- !warnedComponents.lazyPropTypes.has(vnode.type)
221
- ) {
222
- const m =
223
- 'PropTypes are not supported on lazy(). Use propTypes on the wrapped component itself. ';
224
- try {
225
- const lazyVNode = vnode.type();
226
- warnedComponents.lazyPropTypes.set(vnode.type, true);
227
- console.warn(
228
- m + `Component wrapped in lazy() is ${getDisplayName(lazyVNode)}`
229
- );
230
- } catch (promise) {
231
- console.warn(
232
- m + "We will log the wrapped component's name once it is loaded."
233
- );
234
- }
235
- }
236
-
237
- let values = vnode.props;
238
- if (vnode.type._forwarded) {
239
- values = assign({}, values);
240
- delete values.ref;
241
- }
242
-
243
- checkPropTypes(
244
- vnode.type.propTypes,
245
- values,
246
- 'prop',
247
- getDisplayName(vnode),
248
- () => getOwnerStack(vnode)
249
- );
250
- }
251
-
252
- if (oldBeforeDiff) oldBeforeDiff(vnode);
253
- };
254
-
255
- options._hook = (comp, index, type) => {
256
- if (!comp || !hooksAllowed) {
257
- throw new Error('Hook can only be invoked from render methods.');
258
- }
259
-
260
- if (oldHook) oldHook(comp, index, type);
261
- };
262
-
263
- // Ideally we'd want to print a warning once per component, but we
264
- // don't have access to the vnode that triggered it here. As a
265
- // compromise and to avoid flooding the console with warnings we
266
- // print each deprecation warning only once.
267
- const warn = (property, message) => ({
268
- get() {
269
- const key = 'get' + property + message;
270
- if (deprecations && deprecations.indexOf(key) < 0) {
271
- deprecations.push(key);
272
- console.warn(`getting vnode.${property} is deprecated, ${message}`);
273
- }
274
- },
275
- set() {
276
- const key = 'set' + property + message;
277
- if (deprecations && deprecations.indexOf(key) < 0) {
278
- deprecations.push(key);
279
- console.warn(`setting vnode.${property} is not allowed, ${message}`);
280
- }
281
- }
282
- });
283
-
284
- const deprecatedAttributes = {
285
- nodeName: warn('nodeName', 'use vnode.type'),
286
- attributes: warn('attributes', 'use vnode.props'),
287
- children: warn('children', 'use vnode.props.children')
288
- };
289
-
290
- const deprecatedProto = Object.create({}, deprecatedAttributes);
291
-
292
- options.vnode = vnode => {
293
- const props = vnode.props;
294
- if (
295
- vnode.type !== null &&
296
- props != null &&
297
- ('__source' in props || '__self' in props)
298
- ) {
299
- const newProps = (vnode.props = {});
300
- for (let i in props) {
301
- const v = props[i];
302
- if (i === '__source') vnode.__source = v;
303
- else if (i === '__self') vnode.__self = v;
304
- else newProps[i] = v;
305
- }
306
- }
307
-
308
- // eslint-disable-next-line
309
- vnode.__proto__ = deprecatedProto;
310
- if (oldVnode) oldVnode(vnode);
311
- };
312
-
313
- options.diffed = vnode => {
314
- // Check if the user passed plain objects as children. Note that we cannot
315
- // move this check into `options.vnode` because components can receive
316
- // children in any shape they want (e.g.
317
- // `<MyJSONFormatter>{{ foo: 123, bar: "abc" }}</MyJSONFormatter>`).
318
- // Putting this check in `options.diffed` ensures that
319
- // `vnode._children` is set and that we only validate the children
320
- // that were actually rendered.
321
- if (vnode._children) {
322
- vnode._children.forEach(child => {
323
- if (child && child.type === undefined) {
324
- // Remove internal vnode keys that will always be patched
325
- delete child._parent;
326
- delete child._depth;
327
- const keys = Object.keys(child).join(',');
328
- throw new Error(
329
- `Objects are not valid as a child. Encountered an object with the keys {${keys}}.` +
330
- `\n\n${getOwnerStack(vnode)}`
331
- );
332
- }
333
- });
334
- }
335
-
336
- hooksAllowed = false;
337
-
338
- if (oldDiffed) oldDiffed(vnode);
339
-
340
- if (vnode._children != null) {
341
- const keys = [];
342
- for (let i = 0; i < vnode._children.length; i++) {
343
- const child = vnode._children[i];
344
- if (!child || child.key == null) continue;
345
-
346
- const key = child.key;
347
- if (keys.indexOf(key) !== -1) {
348
- console.error(
349
- 'Following component has two or more children with the ' +
350
- `same key attribute: "${key}". This may cause glitches and misbehavior ` +
351
- 'in rendering process. Component: \n\n' +
352
- serializeVNode(vnode) +
353
- `\n\n${getOwnerStack(vnode)}`
354
- );
355
-
356
- // Break early to not spam the console
357
- break;
358
- }
359
-
360
- keys.push(key);
361
- }
362
- }
363
- };
364
- }
365
-
366
- const setState = Component.prototype.setState;
367
- Component.prototype.setState = function(update, callback) {
368
- if (this._vnode == null) {
369
- // `this._vnode` will be `null` during componentWillMount. But it
370
- // is perfectly valid to call `setState` during cWM. So we
371
- // need an additional check to verify that we are dealing with a
372
- // call inside constructor.
373
- if (this.state == null) {
374
- console.warn(
375
- `Calling "this.setState" inside the constructor of a component is a ` +
376
- `no-op and might be a bug in your application. Instead, set ` +
377
- `"this.state = {}" directly.\n\n${getOwnerStack(getCurrentVNode())}`
378
- );
379
- }
380
- } else if (this._parentDom == null) {
381
- console.warn(
382
- `Can't call "this.setState" on an unmounted component. This is a no-op, ` +
383
- `but it indicates a memory leak in your application. To fix, cancel all ` +
384
- `subscriptions and asynchronous tasks in the componentWillUnmount method.` +
385
- `\n\n${getOwnerStack(this._vnode)}`
386
- );
387
- }
388
-
389
- return setState.call(this, update, callback);
390
- };
391
-
392
- const forceUpdate = Component.prototype.forceUpdate;
393
- Component.prototype.forceUpdate = function(callback) {
394
- if (this._vnode == null) {
395
- console.warn(
396
- `Calling "this.forceUpdate" inside the constructor of a component is a ` +
397
- `no-op and might be a bug in your application.\n\n${getOwnerStack(
398
- getCurrentVNode()
399
- )}`
400
- );
401
- } else if (this._parentDom == null) {
402
- console.warn(
403
- `Can't call "this.forceUpdate" on an unmounted component. This is a no-op, ` +
404
- `but it indicates a memory leak in your application. To fix, cancel all ` +
405
- `subscriptions and asynchronous tasks in the componentWillUnmount method.` +
406
- `\n\n${getOwnerStack(this._vnode)}`
407
- );
408
- }
409
- return forceUpdate.call(this, callback);
410
- };
411
-
412
- /**
413
- * Serialize a vnode tree to a string
414
- * @param {import('./internal').VNode} vnode
415
- * @returns {string}
416
- */
417
- export function serializeVNode(vnode) {
418
- let { props } = vnode;
419
- let name = getDisplayName(vnode);
420
-
421
- let attrs = '';
422
- for (let prop in props) {
423
- if (props.hasOwnProperty(prop) && prop !== 'children') {
424
- let value = props[prop];
425
-
426
- // If it is an object but doesn't have toString(), use Object.toString
427
- if (typeof value == 'function') {
428
- value = `function ${value.displayName || value.name}() {}`;
429
- }
430
-
431
- value =
432
- Object(value) === value && !value.toString
433
- ? Object.prototype.toString.call(value)
434
- : value + '';
435
-
436
- attrs += ` ${prop}=${JSON.stringify(value)}`;
437
- }
438
- }
439
-
440
- let children = props.children;
441
- return `<${name}${attrs}${
442
- children && children.length ? '>..</' + name + '>' : ' />'
443
- }`;
444
- }
1
+ import { checkPropTypes } from './check-props';
2
+ import { options, Component } from 'preact';
3
+ import {
4
+ ELEMENT_NODE,
5
+ DOCUMENT_NODE,
6
+ DOCUMENT_FRAGMENT_NODE
7
+ } from './constants';
8
+ import {
9
+ getOwnerStack,
10
+ setupComponentStack,
11
+ getCurrentVNode,
12
+ getDisplayName
13
+ } from './component-stack';
14
+ import { assign } from './util';
15
+
16
+ const isWeakMapSupported = typeof WeakMap == 'function';
17
+
18
+ function getClosestDomNodeParent(parent) {
19
+ if (!parent) return {};
20
+ if (typeof parent.type == 'function') {
21
+ return getClosestDomNodeParent(parent._parent);
22
+ }
23
+ return parent;
24
+ }
25
+
26
+ export function initDebug() {
27
+ setupComponentStack();
28
+
29
+ let hooksAllowed = false;
30
+
31
+ /* eslint-disable no-console */
32
+ let oldBeforeDiff = options._diff;
33
+ let oldDiffed = options.diffed;
34
+ let oldVnode = options.vnode;
35
+ let oldCatchError = options._catchError;
36
+ let oldRoot = options._root;
37
+ let oldHook = options._hook;
38
+ const warnedComponents = !isWeakMapSupported
39
+ ? null
40
+ : {
41
+ useEffect: new WeakMap(),
42
+ useLayoutEffect: new WeakMap(),
43
+ lazyPropTypes: new WeakMap()
44
+ };
45
+ const deprecations = [];
46
+
47
+ options._catchError = (error, vnode, oldVNode, errorInfo) => {
48
+ let component = vnode && vnode._component;
49
+ if (component && typeof error.then == 'function') {
50
+ const promise = error;
51
+ error = new Error(
52
+ `Missing Suspense. The throwing component was: ${getDisplayName(vnode)}`
53
+ );
54
+
55
+ let parent = vnode;
56
+ for (; parent; parent = parent._parent) {
57
+ if (parent._component && parent._component._childDidSuspend) {
58
+ error = promise;
59
+ break;
60
+ }
61
+ }
62
+
63
+ // We haven't recovered and we know at this point that there is no
64
+ // Suspense component higher up in the tree
65
+ if (error instanceof Error) {
66
+ throw error;
67
+ }
68
+ }
69
+
70
+ try {
71
+ errorInfo = errorInfo || {};
72
+ errorInfo.componentStack = getOwnerStack(vnode);
73
+ oldCatchError(error, vnode, oldVNode, errorInfo);
74
+
75
+ // when an error was handled by an ErrorBoundary we will nontheless emit an error
76
+ // event on the window object. This is to make up for react compatibility in dev mode
77
+ // and thus make the Next.js dev overlay work.
78
+ if (typeof error.then != 'function') {
79
+ setTimeout(() => {
80
+ throw error;
81
+ });
82
+ }
83
+ } catch (e) {
84
+ throw e;
85
+ }
86
+ };
87
+
88
+ options._root = (vnode, parentNode) => {
89
+ if (!parentNode) {
90
+ throw new Error(
91
+ 'Undefined parent passed to render(), this is the second argument.\n' +
92
+ 'Check if the element is available in the DOM/has the correct id.'
93
+ );
94
+ }
95
+
96
+ let isValid;
97
+ switch (parentNode.nodeType) {
98
+ case ELEMENT_NODE:
99
+ case DOCUMENT_FRAGMENT_NODE:
100
+ case DOCUMENT_NODE:
101
+ isValid = true;
102
+ break;
103
+ default:
104
+ isValid = false;
105
+ }
106
+
107
+ if (!isValid) {
108
+ let componentName = getDisplayName(vnode);
109
+ throw new Error(
110
+ `Expected a valid HTML node as a second argument to render. Received ${parentNode} instead: render(<${componentName} />, ${parentNode});`
111
+ );
112
+ }
113
+
114
+ if (oldRoot) oldRoot(vnode, parentNode);
115
+ };
116
+
117
+ options._diff = vnode => {
118
+ let { type, _parent: parent } = vnode;
119
+ let parentVNode = getClosestDomNodeParent(parent);
120
+
121
+ hooksAllowed = true;
122
+
123
+ if (type === undefined) {
124
+ throw new Error(
125
+ 'Undefined component passed to createElement()\n\n' +
126
+ 'You likely forgot to export your component or might have mixed up default and named imports' +
127
+ serializeVNode(vnode) +
128
+ `\n\n${getOwnerStack(vnode)}`
129
+ );
130
+ } else if (type != null && typeof type == 'object') {
131
+ if (type._children !== undefined && type._dom !== undefined) {
132
+ throw new Error(
133
+ `Invalid type passed to createElement(): ${type}\n\n` +
134
+ 'Did you accidentally pass a JSX literal as JSX twice?\n\n' +
135
+ ` let My${getDisplayName(vnode)} = ${serializeVNode(type)};\n` +
136
+ ` let vnode = <My${getDisplayName(vnode)} />;\n\n` +
137
+ 'This usually happens when you export a JSX literal and not the component.' +
138
+ `\n\n${getOwnerStack(vnode)}`
139
+ );
140
+ }
141
+
142
+ throw new Error(
143
+ 'Invalid type passed to createElement(): ' +
144
+ (Array.isArray(type) ? 'array' : type)
145
+ );
146
+ }
147
+
148
+ if (
149
+ (type === 'thead' || type === 'tfoot' || type === 'tbody') &&
150
+ parentVNode.type !== 'table'
151
+ ) {
152
+ console.error(
153
+ 'Improper nesting of table. Your <thead/tbody/tfoot> should have a <table> parent.' +
154
+ serializeVNode(vnode) +
155
+ `\n\n${getOwnerStack(vnode)}`
156
+ );
157
+ } else if (
158
+ type === 'tr' &&
159
+ parentVNode.type !== 'thead' &&
160
+ parentVNode.type !== 'tfoot' &&
161
+ parentVNode.type !== 'tbody' &&
162
+ parentVNode.type !== 'table'
163
+ ) {
164
+ console.error(
165
+ 'Improper nesting of table. Your <tr> should have a <thead/tbody/tfoot/table> parent.' +
166
+ serializeVNode(vnode) +
167
+ `\n\n${getOwnerStack(vnode)}`
168
+ );
169
+ } else if (type === 'td' && parentVNode.type !== 'tr') {
170
+ console.error(
171
+ 'Improper nesting of table. Your <td> should have a <tr> parent.' +
172
+ serializeVNode(vnode) +
173
+ `\n\n${getOwnerStack(vnode)}`
174
+ );
175
+ } else if (type === 'th' && parentVNode.type !== 'tr') {
176
+ console.error(
177
+ 'Improper nesting of table. Your <th> should have a <tr>.' +
178
+ serializeVNode(vnode) +
179
+ `\n\n${getOwnerStack(vnode)}`
180
+ );
181
+ }
182
+
183
+ if (
184
+ vnode.ref !== undefined &&
185
+ typeof vnode.ref != 'function' &&
186
+ typeof vnode.ref != 'object' &&
187
+ !('$$typeof' in vnode) // allow string refs when preact-compat is installed
188
+ ) {
189
+ throw new Error(
190
+ `Component's "ref" property should be a function, or an object created ` +
191
+ `by createRef(), but got [${typeof vnode.ref}] instead\n` +
192
+ serializeVNode(vnode) +
193
+ `\n\n${getOwnerStack(vnode)}`
194
+ );
195
+ }
196
+
197
+ if (typeof vnode.type == 'string') {
198
+ for (const key in vnode.props) {
199
+ if (
200
+ key[0] === 'o' &&
201
+ key[1] === 'n' &&
202
+ typeof vnode.props[key] != 'function' &&
203
+ vnode.props[key] != null
204
+ ) {
205
+ throw new Error(
206
+ `Component's "${key}" property should be a function, ` +
207
+ `but got [${typeof vnode.props[key]}] instead\n` +
208
+ serializeVNode(vnode) +
209
+ `\n\n${getOwnerStack(vnode)}`
210
+ );
211
+ }
212
+ }
213
+ }
214
+
215
+ // Check prop-types if available
216
+ if (typeof vnode.type == 'function' && vnode.type.propTypes) {
217
+ if (
218
+ vnode.type.displayName === 'Lazy' &&
219
+ warnedComponents &&
220
+ !warnedComponents.lazyPropTypes.has(vnode.type)
221
+ ) {
222
+ const m =
223
+ 'PropTypes are not supported on lazy(). Use propTypes on the wrapped component itself. ';
224
+ try {
225
+ const lazyVNode = vnode.type();
226
+ warnedComponents.lazyPropTypes.set(vnode.type, true);
227
+ console.warn(
228
+ m + `Component wrapped in lazy() is ${getDisplayName(lazyVNode)}`
229
+ );
230
+ } catch (promise) {
231
+ console.warn(
232
+ m + "We will log the wrapped component's name once it is loaded."
233
+ );
234
+ }
235
+ }
236
+
237
+ let values = vnode.props;
238
+ if (vnode.type._forwarded) {
239
+ values = assign({}, values);
240
+ delete values.ref;
241
+ }
242
+
243
+ checkPropTypes(
244
+ vnode.type.propTypes,
245
+ values,
246
+ 'prop',
247
+ getDisplayName(vnode),
248
+ () => getOwnerStack(vnode)
249
+ );
250
+ }
251
+
252
+ if (oldBeforeDiff) oldBeforeDiff(vnode);
253
+ };
254
+
255
+ options._hook = (comp, index, type) => {
256
+ if (!comp || !hooksAllowed) {
257
+ throw new Error('Hook can only be invoked from render methods.');
258
+ }
259
+
260
+ if (oldHook) oldHook(comp, index, type);
261
+ };
262
+
263
+ // Ideally we'd want to print a warning once per component, but we
264
+ // don't have access to the vnode that triggered it here. As a
265
+ // compromise and to avoid flooding the console with warnings we
266
+ // print each deprecation warning only once.
267
+ const warn = (property, message) => ({
268
+ get() {
269
+ const key = 'get' + property + message;
270
+ if (deprecations && deprecations.indexOf(key) < 0) {
271
+ deprecations.push(key);
272
+ console.warn(`getting vnode.${property} is deprecated, ${message}`);
273
+ }
274
+ },
275
+ set() {
276
+ const key = 'set' + property + message;
277
+ if (deprecations && deprecations.indexOf(key) < 0) {
278
+ deprecations.push(key);
279
+ console.warn(`setting vnode.${property} is not allowed, ${message}`);
280
+ }
281
+ }
282
+ });
283
+
284
+ const deprecatedAttributes = {
285
+ nodeName: warn('nodeName', 'use vnode.type'),
286
+ attributes: warn('attributes', 'use vnode.props'),
287
+ children: warn('children', 'use vnode.props.children')
288
+ };
289
+
290
+ const deprecatedProto = Object.create({}, deprecatedAttributes);
291
+
292
+ options.vnode = vnode => {
293
+ const props = vnode.props;
294
+ if (
295
+ vnode.type !== null &&
296
+ props != null &&
297
+ ('__source' in props || '__self' in props)
298
+ ) {
299
+ const newProps = (vnode.props = {});
300
+ for (let i in props) {
301
+ const v = props[i];
302
+ if (i === '__source') vnode.__source = v;
303
+ else if (i === '__self') vnode.__self = v;
304
+ else newProps[i] = v;
305
+ }
306
+ }
307
+
308
+ // eslint-disable-next-line
309
+ vnode.__proto__ = deprecatedProto;
310
+ if (oldVnode) oldVnode(vnode);
311
+ };
312
+
313
+ options.diffed = vnode => {
314
+ // Check if the user passed plain objects as children. Note that we cannot
315
+ // move this check into `options.vnode` because components can receive
316
+ // children in any shape they want (e.g.
317
+ // `<MyJSONFormatter>{{ foo: 123, bar: "abc" }}</MyJSONFormatter>`).
318
+ // Putting this check in `options.diffed` ensures that
319
+ // `vnode._children` is set and that we only validate the children
320
+ // that were actually rendered.
321
+ if (vnode._children) {
322
+ vnode._children.forEach(child => {
323
+ if (child && child.type === undefined) {
324
+ // Remove internal vnode keys that will always be patched
325
+ delete child._parent;
326
+ delete child._depth;
327
+ const keys = Object.keys(child).join(',');
328
+ throw new Error(
329
+ `Objects are not valid as a child. Encountered an object with the keys {${keys}}.` +
330
+ `\n\n${getOwnerStack(vnode)}`
331
+ );
332
+ }
333
+ });
334
+ }
335
+
336
+ hooksAllowed = false;
337
+
338
+ if (oldDiffed) oldDiffed(vnode);
339
+
340
+ if (vnode._children != null) {
341
+ const keys = [];
342
+ for (let i = 0; i < vnode._children.length; i++) {
343
+ const child = vnode._children[i];
344
+ if (!child || child.key == null) continue;
345
+
346
+ const key = child.key;
347
+ if (keys.indexOf(key) !== -1) {
348
+ console.error(
349
+ 'Following component has two or more children with the ' +
350
+ `same key attribute: "${key}". This may cause glitches and misbehavior ` +
351
+ 'in rendering process. Component: \n\n' +
352
+ serializeVNode(vnode) +
353
+ `\n\n${getOwnerStack(vnode)}`
354
+ );
355
+
356
+ // Break early to not spam the console
357
+ break;
358
+ }
359
+
360
+ keys.push(key);
361
+ }
362
+ }
363
+ };
364
+ }
365
+
366
+ const setState = Component.prototype.setState;
367
+ Component.prototype.setState = function(update, callback) {
368
+ if (this._vnode == null) {
369
+ // `this._vnode` will be `null` during componentWillMount. But it
370
+ // is perfectly valid to call `setState` during cWM. So we
371
+ // need an additional check to verify that we are dealing with a
372
+ // call inside constructor.
373
+ if (this.state == null) {
374
+ console.warn(
375
+ `Calling "this.setState" inside the constructor of a component is a ` +
376
+ `no-op and might be a bug in your application. Instead, set ` +
377
+ `"this.state = {}" directly.\n\n${getOwnerStack(getCurrentVNode())}`
378
+ );
379
+ }
380
+ }
381
+
382
+ return setState.call(this, update, callback);
383
+ };
384
+
385
+ const forceUpdate = Component.prototype.forceUpdate;
386
+ Component.prototype.forceUpdate = function(callback) {
387
+ if (this._vnode == null) {
388
+ console.warn(
389
+ `Calling "this.forceUpdate" inside the constructor of a component is a ` +
390
+ `no-op and might be a bug in your application.\n\n${getOwnerStack(
391
+ getCurrentVNode()
392
+ )}`
393
+ );
394
+ } else if (this._parentDom == null) {
395
+ console.warn(
396
+ `Can't call "this.forceUpdate" on an unmounted component. This is a no-op, ` +
397
+ `but it indicates a memory leak in your application. To fix, cancel all ` +
398
+ `subscriptions and asynchronous tasks in the componentWillUnmount method.` +
399
+ `\n\n${getOwnerStack(this._vnode)}`
400
+ );
401
+ }
402
+ return forceUpdate.call(this, callback);
403
+ };
404
+
405
+ /**
406
+ * Serialize a vnode tree to a string
407
+ * @param {import('./internal').VNode} vnode
408
+ * @returns {string}
409
+ */
410
+ export function serializeVNode(vnode) {
411
+ let { props } = vnode;
412
+ let name = getDisplayName(vnode);
413
+
414
+ let attrs = '';
415
+ for (let prop in props) {
416
+ if (props.hasOwnProperty(prop) && prop !== 'children') {
417
+ let value = props[prop];
418
+
419
+ // If it is an object but doesn't have toString(), use Object.toString
420
+ if (typeof value == 'function') {
421
+ value = `function ${value.displayName || value.name}() {}`;
422
+ }
423
+
424
+ value =
425
+ Object(value) === value && !value.toString
426
+ ? Object.prototype.toString.call(value)
427
+ : value + '';
428
+
429
+ attrs += ` ${prop}=${JSON.stringify(value)}`;
430
+ }
431
+ }
432
+
433
+ let children = props.children;
434
+ return `<${name}${attrs}${
435
+ children && children.length ? '>..</' + name + '>' : ' />'
436
+ }`;
437
+ }