isomorfeus-preact 10.6.11 → 10.6.15

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