isomorfeus-preact 10.8.0 → 10.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }