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,516 +1,516 @@
1
- import { EMPTY_OBJ } from '../constants';
2
- import { Component, getDomSibling } from '../component';
3
- import { Fragment } from '../create-element';
4
- import { diffChildren } from './children';
5
- import { diffProps, setProperty } from './props';
6
- import { assign, removeNode, slice } from '../util';
7
- import options from '../options';
8
-
9
- /**
10
- * Diff two virtual nodes and apply proper changes to the DOM
11
- * @param {import('../internal').PreactElement} parentDom The parent of the DOM element
12
- * @param {import('../internal').VNode} newVNode The new virtual node
13
- * @param {import('../internal').VNode} oldVNode The old virtual node
14
- * @param {object} globalContext The current context object. Modified by getChildContext
15
- * @param {boolean} isSvg Whether or not this element is an SVG node
16
- * @param {Array<import('../internal').PreactElement>} excessDomChildren
17
- * @param {Array<import('../internal').Component>} commitQueue List of components
18
- * which have callbacks to invoke in commitRoot
19
- * @param {import('../internal').PreactElement} oldDom The current attached DOM
20
- * element any new dom elements should be placed around. Likely `null` on first
21
- * render (except when hydrating). Can be a sibling DOM element when diffing
22
- * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.
23
- * @param {boolean} [isHydrating] Whether or not we are in hydration
24
- */
25
- export function diff(
26
- parentDom,
27
- newVNode,
28
- oldVNode,
29
- globalContext,
30
- isSvg,
31
- excessDomChildren,
32
- commitQueue,
33
- oldDom,
34
- isHydrating
35
- ) {
36
- let tmp,
37
- newType = newVNode.type;
38
-
39
- // When passing through createElement it assigns the object
40
- // constructor as undefined. This to prevent JSON-injection.
41
- if (newVNode.constructor !== undefined) return null;
42
-
43
- // If the previous diff bailed out, resume creating/hydrating.
44
- if (oldVNode._hydrating != null) {
45
- isHydrating = oldVNode._hydrating;
46
- oldDom = newVNode._dom = oldVNode._dom;
47
- // if we resume, we want the tree to be "unlocked"
48
- newVNode._hydrating = null;
49
- excessDomChildren = [oldDom];
50
- }
51
-
52
- if ((tmp = options._diff)) tmp(newVNode);
53
-
54
- try {
55
- outer: if (typeof newType == 'function') {
56
- let c, isNew, oldProps, oldState, snapshot, clearProcessingException;
57
- let newProps = newVNode.props;
58
-
59
- // Necessary for createContext api. Setting this property will pass
60
- // the context value as `this.context` just for this component.
61
- tmp = newType.contextType;
62
- let provider = tmp && globalContext[tmp._id];
63
- let componentContext = tmp
64
- ? provider
65
- ? provider.props.value
66
- : tmp._defaultValue
67
- : globalContext;
68
-
69
- // Get component and set it to `c`
70
- if (oldVNode._component) {
71
- c = newVNode._component = oldVNode._component;
72
- clearProcessingException = c._processingException = c._pendingError;
73
- } else {
74
- // Instantiate the new component
75
- if ('prototype' in newType && newType.prototype.render) {
76
- // @ts-ignore The check above verifies that newType is suppose to be constructed
77
- newVNode._component = c = new newType(newProps, componentContext); // eslint-disable-line new-cap
78
- } else {
79
- // @ts-ignore Trust me, Component implements the interface we want
80
- newVNode._component = c = new Component(newProps, componentContext);
81
- c.constructor = newType;
82
- c.render = doRender;
83
- }
84
- if (provider) provider.sub(c);
85
-
86
- c.props = newProps;
87
- if (!c.state) c.state = {};
88
- c.context = componentContext;
89
- c._globalContext = globalContext;
90
- isNew = c._dirty = true;
91
- c._renderCallbacks = [];
92
- }
93
-
94
- // Invoke getDerivedStateFromProps
95
- if (c._nextState == null) {
96
- c._nextState = c.state;
97
- }
98
- if (newType.getDerivedStateFromProps != null) {
99
- if (c._nextState == c.state) {
100
- c._nextState = assign({}, c._nextState);
101
- }
102
-
103
- assign(
104
- c._nextState,
105
- newType.getDerivedStateFromProps(newProps, c._nextState)
106
- );
107
- }
108
-
109
- oldProps = c.props;
110
- oldState = c.state;
111
-
112
- // Invoke pre-render lifecycle methods
113
- if (isNew) {
114
- if (
115
- newType.getDerivedStateFromProps == null &&
116
- c.componentWillMount != null
117
- ) {
118
- c.componentWillMount();
119
- }
120
-
121
- if (c.componentDidMount != null) {
122
- c._renderCallbacks.push(c.componentDidMount);
123
- }
124
- } else {
125
- if (
126
- newType.getDerivedStateFromProps == null &&
127
- newProps !== oldProps &&
128
- c.componentWillReceiveProps != null
129
- ) {
130
- c.componentWillReceiveProps(newProps, componentContext);
131
- }
132
-
133
- if (
134
- (!c._force &&
135
- c.shouldComponentUpdate != null &&
136
- c.shouldComponentUpdate(
137
- newProps,
138
- c._nextState,
139
- componentContext
140
- ) === false) ||
141
- newVNode._original === oldVNode._original
142
- ) {
143
- c.props = newProps;
144
- c.state = c._nextState;
145
- // More info about this here: https://gist.github.com/JoviDeCroock/bec5f2ce93544d2e6070ef8e0036e4e8
146
- if (newVNode._original !== oldVNode._original) c._dirty = false;
147
- c._vnode = newVNode;
148
- newVNode._dom = oldVNode._dom;
149
- newVNode._children = oldVNode._children;
150
- newVNode._children.forEach(vnode => {
151
- if (vnode) vnode._parent = newVNode;
152
- });
153
- if (c._renderCallbacks.length) {
154
- commitQueue.push(c);
155
- }
156
-
157
- break outer;
158
- }
159
-
160
- if (c.componentWillUpdate != null) {
161
- c.componentWillUpdate(newProps, c._nextState, componentContext);
162
- }
163
-
164
- if (c.componentDidUpdate != null) {
165
- c._renderCallbacks.push(() => {
166
- c.componentDidUpdate(oldProps, oldState, snapshot);
167
- });
168
- }
169
- }
170
-
171
- c.context = componentContext;
172
- c.props = newProps;
173
- c.state = c._nextState;
174
-
175
- if ((tmp = options._render)) tmp(newVNode);
176
-
177
- c._dirty = false;
178
- c._vnode = newVNode;
179
- c._parentDom = parentDom;
180
-
181
- tmp = c.render(c.props, c.state, c.context);
182
-
183
- // Handle setState called in render, see #2553
184
- c.state = c._nextState;
185
-
186
- if (c.getChildContext != null) {
187
- globalContext = assign(assign({}, globalContext), c.getChildContext());
188
- }
189
-
190
- if (!isNew && c.getSnapshotBeforeUpdate != null) {
191
- snapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);
192
- }
193
-
194
- let isTopLevelFragment =
195
- tmp != null && tmp.type === Fragment && tmp.key == null;
196
- let renderResult = isTopLevelFragment ? tmp.props.children : tmp;
197
-
198
- diffChildren(
199
- parentDom,
200
- Array.isArray(renderResult) ? renderResult : [renderResult],
201
- newVNode,
202
- oldVNode,
203
- globalContext,
204
- isSvg,
205
- excessDomChildren,
206
- commitQueue,
207
- oldDom,
208
- isHydrating
209
- );
210
-
211
- c.base = newVNode._dom;
212
-
213
- // We successfully rendered this VNode, unset any stored hydration/bailout state:
214
- newVNode._hydrating = null;
215
-
216
- if (c._renderCallbacks.length) {
217
- commitQueue.push(c);
218
- }
219
-
220
- if (clearProcessingException) {
221
- c._pendingError = c._processingException = null;
222
- }
223
-
224
- c._force = false;
225
- } else if (
226
- excessDomChildren == null &&
227
- newVNode._original === oldVNode._original
228
- ) {
229
- newVNode._children = oldVNode._children;
230
- newVNode._dom = oldVNode._dom;
231
- } else {
232
- newVNode._dom = diffElementNodes(
233
- oldVNode._dom,
234
- newVNode,
235
- oldVNode,
236
- globalContext,
237
- isSvg,
238
- excessDomChildren,
239
- commitQueue,
240
- isHydrating
241
- );
242
- }
243
-
244
- if ((tmp = options.diffed)) tmp(newVNode);
245
- } catch (e) {
246
- newVNode._original = null;
247
- // if hydrating or creating initial tree, bailout preserves DOM:
248
- if (isHydrating || excessDomChildren != null) {
249
- newVNode._dom = oldDom;
250
- newVNode._hydrating = !!isHydrating;
251
- excessDomChildren[excessDomChildren.indexOf(oldDom)] = null;
252
- // ^ could possibly be simplified to:
253
- // excessDomChildren.length = 0;
254
- }
255
- options._catchError(e, newVNode, oldVNode);
256
- }
257
- }
258
-
259
- /**
260
- * @param {Array<import('../internal').Component>} commitQueue List of components
261
- * which have callbacks to invoke in commitRoot
262
- * @param {import('../internal').VNode} root
263
- */
264
- export function commitRoot(commitQueue, root) {
265
- if (options._commit) options._commit(root, commitQueue);
266
-
267
- commitQueue.some(c => {
268
- try {
269
- // @ts-ignore Reuse the commitQueue variable here so the type changes
270
- commitQueue = c._renderCallbacks;
271
- c._renderCallbacks = [];
272
- commitQueue.some(cb => {
273
- // @ts-ignore See above ts-ignore on commitQueue
274
- cb.call(c);
275
- });
276
- } catch (e) {
277
- options._catchError(e, c._vnode);
278
- }
279
- });
280
- }
281
-
282
- /**
283
- * Diff two virtual nodes representing DOM element
284
- * @param {import('../internal').PreactElement} dom The DOM element representing
285
- * the virtual nodes being diffed
286
- * @param {import('../internal').VNode} newVNode The new virtual node
287
- * @param {import('../internal').VNode} oldVNode The old virtual node
288
- * @param {object} globalContext The current context object
289
- * @param {boolean} isSvg Whether or not this DOM node is an SVG node
290
- * @param {*} excessDomChildren
291
- * @param {Array<import('../internal').Component>} commitQueue List of components
292
- * which have callbacks to invoke in commitRoot
293
- * @param {boolean} isHydrating Whether or not we are in hydration
294
- * @returns {import('../internal').PreactElement}
295
- */
296
- function diffElementNodes(
297
- dom,
298
- newVNode,
299
- oldVNode,
300
- globalContext,
301
- isSvg,
302
- excessDomChildren,
303
- commitQueue,
304
- isHydrating
305
- ) {
306
- let oldProps = oldVNode.props;
307
- let newProps = newVNode.props;
308
- let nodeType = newVNode.type;
309
- let i = 0;
310
-
311
- // Tracks entering and exiting SVG namespace when descending through the tree.
312
- if (nodeType === 'svg') isSvg = true;
313
-
314
- if (excessDomChildren != null) {
315
- for (; i < excessDomChildren.length; i++) {
316
- const child = excessDomChildren[i];
317
-
318
- // if newVNode matches an element in excessDomChildren or the `dom`
319
- // argument matches an element in excessDomChildren, remove it from
320
- // excessDomChildren so it isn't later removed in diffChildren
321
- if (
322
- child &&
323
- 'setAttribute' in child === !!nodeType &&
324
- (nodeType ? child.localName === nodeType : child.nodeType === 3)
325
- ) {
326
- dom = child;
327
- excessDomChildren[i] = null;
328
- break;
329
- }
330
- }
331
- }
332
-
333
- if (dom == null) {
334
- if (nodeType === null) {
335
- // @ts-ignore createTextNode returns Text, we expect PreactElement
336
- return document.createTextNode(newProps);
337
- }
338
-
339
- if (isSvg) {
340
- dom = document.createElementNS(
341
- 'http://www.w3.org/2000/svg',
342
- // @ts-ignore We know `newVNode.type` is a string
343
- nodeType
344
- );
345
- } else {
346
- dom = document.createElement(
347
- // @ts-ignore We know `newVNode.type` is a string
348
- nodeType,
349
- newProps.is && newProps
350
- );
351
- }
352
-
353
- // we created a new parent, so none of the previously attached children can be reused:
354
- excessDomChildren = null;
355
- // we are creating a new node, so we can assume this is a new subtree (in case we are hydrating), this deopts the hydrate
356
- isHydrating = false;
357
- }
358
-
359
- if (nodeType === null) {
360
- // During hydration, we still have to split merged text from SSR'd HTML.
361
- if (oldProps !== newProps && (!isHydrating || dom.data !== newProps)) {
362
- dom.data = newProps;
363
- }
364
- } else {
365
- // If excessDomChildren was not null, repopulate it with the current element's children:
366
- excessDomChildren = excessDomChildren && slice.call(dom.childNodes);
367
-
368
- oldProps = oldVNode.props || EMPTY_OBJ;
369
-
370
- let oldHtml = oldProps.dangerouslySetInnerHTML;
371
- let newHtml = newProps.dangerouslySetInnerHTML;
372
-
373
- // During hydration, props are not diffed at all (including dangerouslySetInnerHTML)
374
- // @TODO we should warn in debug mode when props don't match here.
375
- if (!isHydrating) {
376
- // But, if we are in a situation where we are using existing DOM (e.g. replaceNode)
377
- // we should read the existing DOM attributes to diff them
378
- if (excessDomChildren != null) {
379
- oldProps = {};
380
- for (i = 0; i < dom.attributes.length; i++) {
381
- oldProps[dom.attributes[i].name] = dom.attributes[i].value;
382
- }
383
- }
384
-
385
- if (newHtml || oldHtml) {
386
- // Avoid re-applying the same '__html' if it did not changed between re-render
387
- if (
388
- !newHtml ||
389
- ((!oldHtml || newHtml.__html != oldHtml.__html) &&
390
- newHtml.__html !== dom.innerHTML)
391
- ) {
392
- dom.innerHTML = (newHtml && newHtml.__html) || '';
393
- }
394
- }
395
- }
396
-
397
- diffProps(dom, newProps, oldProps, isSvg, isHydrating);
398
-
399
- // If the new vnode didn't have dangerouslySetInnerHTML, diff its children
400
- if (newHtml) {
401
- newVNode._children = [];
402
- } else {
403
- i = newVNode.props.children;
404
- diffChildren(
405
- dom,
406
- Array.isArray(i) ? i : [i],
407
- newVNode,
408
- oldVNode,
409
- globalContext,
410
- isSvg && nodeType !== 'foreignObject',
411
- excessDomChildren,
412
- commitQueue,
413
- excessDomChildren
414
- ? excessDomChildren[0]
415
- : oldVNode._children && getDomSibling(oldVNode, 0),
416
- isHydrating
417
- );
418
-
419
- // Remove children that are not part of any vnode.
420
- if (excessDomChildren != null) {
421
- for (i = excessDomChildren.length; i--; ) {
422
- if (excessDomChildren[i] != null) removeNode(excessDomChildren[i]);
423
- }
424
- }
425
- }
426
-
427
- // (as above, don't diff props during hydration)
428
- if (!isHydrating) {
429
- if (
430
- 'value' in newProps &&
431
- (i = newProps.value) !== undefined &&
432
- // #2756 For the <progress>-element the initial value is 0,
433
- // despite the attribute not being present. When the attribute
434
- // is missing the progress bar is treated as indeterminate.
435
- // To fix that we'll always update it when it is 0 for progress elements
436
- (i !== oldProps.value ||
437
- i !== dom.value ||
438
- (nodeType === 'progress' && !i))
439
- ) {
440
- setProperty(dom, 'value', i, oldProps.value, false);
441
- }
442
- if (
443
- 'checked' in newProps &&
444
- (i = newProps.checked) !== undefined &&
445
- i !== dom.checked
446
- ) {
447
- setProperty(dom, 'checked', i, oldProps.checked, false);
448
- }
449
- }
450
- }
451
-
452
- return dom;
453
- }
454
-
455
- /**
456
- * Invoke or update a ref, depending on whether it is a function or object ref.
457
- * @param {object|function} ref
458
- * @param {any} value
459
- * @param {import('../internal').VNode} vnode
460
- */
461
- export function applyRef(ref, value, vnode) {
462
- try {
463
- if (typeof ref == 'function') ref(value);
464
- else ref.current = value;
465
- } catch (e) {
466
- options._catchError(e, vnode);
467
- }
468
- }
469
-
470
- /**
471
- * Unmount a virtual node from the tree and apply DOM changes
472
- * @param {import('../internal').VNode} vnode The virtual node to unmount
473
- * @param {import('../internal').VNode} parentVNode The parent of the VNode that
474
- * initiated the unmount
475
- * @param {boolean} [skipRemove] Flag that indicates that a parent node of the
476
- * current element is already detached from the DOM.
477
- */
478
- export function unmount(vnode, parentVNode, skipRemove) {
479
- let r;
480
- if (options.unmount) options.unmount(vnode);
481
-
482
- if ((r = vnode.ref)) {
483
- if (!r.current || r.current === vnode._dom) applyRef(r, null, parentVNode);
484
- }
485
-
486
- if ((r = vnode._component) != null) {
487
- if (r.componentWillUnmount) {
488
- try {
489
- r.componentWillUnmount();
490
- } catch (e) {
491
- options._catchError(e, parentVNode);
492
- }
493
- }
494
-
495
- r.base = r._parentDom = null;
496
- }
497
-
498
- if ((r = vnode._children)) {
499
- for (let i = 0; i < r.length; i++) {
500
- if (r[i]) {
501
- unmount(r[i], parentVNode, typeof vnode.type != 'function');
502
- }
503
- }
504
- }
505
-
506
- if (!skipRemove && vnode._dom != null) removeNode(vnode._dom);
507
-
508
- // Must be set to `undefined` to properly clean up `_nextDom`
509
- // for which `null` is a valid value. See comment in `create-element.js`
510
- vnode._dom = vnode._nextDom = undefined;
511
- }
512
-
513
- /** The `.render()` method for a PFC backing instance. */
514
- function doRender(props, state, context) {
515
- return this.constructor(props, context);
516
- }
1
+ import { EMPTY_OBJ } from '../constants';
2
+ import { Component, getDomSibling } from '../component';
3
+ import { Fragment } from '../create-element';
4
+ import { diffChildren } from './children';
5
+ import { diffProps, setProperty } from './props';
6
+ import { assign, removeNode, slice } from '../util';
7
+ import options from '../options';
8
+
9
+ /**
10
+ * Diff two virtual nodes and apply proper changes to the DOM
11
+ * @param {import('../internal').PreactElement} parentDom The parent of the DOM element
12
+ * @param {import('../internal').VNode} newVNode The new virtual node
13
+ * @param {import('../internal').VNode} oldVNode The old virtual node
14
+ * @param {object} globalContext The current context object. Modified by getChildContext
15
+ * @param {boolean} isSvg Whether or not this element is an SVG node
16
+ * @param {Array<import('../internal').PreactElement>} excessDomChildren
17
+ * @param {Array<import('../internal').Component>} commitQueue List of components
18
+ * which have callbacks to invoke in commitRoot
19
+ * @param {import('../internal').PreactElement} oldDom The current attached DOM
20
+ * element any new dom elements should be placed around. Likely `null` on first
21
+ * render (except when hydrating). Can be a sibling DOM element when diffing
22
+ * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.
23
+ * @param {boolean} [isHydrating] Whether or not we are in hydration
24
+ */
25
+ export function diff(
26
+ parentDom,
27
+ newVNode,
28
+ oldVNode,
29
+ globalContext,
30
+ isSvg,
31
+ excessDomChildren,
32
+ commitQueue,
33
+ oldDom,
34
+ isHydrating
35
+ ) {
36
+ let tmp,
37
+ newType = newVNode.type;
38
+
39
+ // When passing through createElement it assigns the object
40
+ // constructor as undefined. This to prevent JSON-injection.
41
+ if (newVNode.constructor !== undefined) return null;
42
+
43
+ // If the previous diff bailed out, resume creating/hydrating.
44
+ if (oldVNode._hydrating != null) {
45
+ isHydrating = oldVNode._hydrating;
46
+ oldDom = newVNode._dom = oldVNode._dom;
47
+ // if we resume, we want the tree to be "unlocked"
48
+ newVNode._hydrating = null;
49
+ excessDomChildren = [oldDom];
50
+ }
51
+
52
+ if ((tmp = options._diff)) tmp(newVNode);
53
+
54
+ try {
55
+ outer: if (typeof newType == 'function') {
56
+ let c, isNew, oldProps, oldState, snapshot, clearProcessingException;
57
+ let newProps = newVNode.props;
58
+
59
+ // Necessary for createContext api. Setting this property will pass
60
+ // the context value as `this.context` just for this component.
61
+ tmp = newType.contextType;
62
+ let provider = tmp && globalContext[tmp._id];
63
+ let componentContext = tmp
64
+ ? provider
65
+ ? provider.props.value
66
+ : tmp._defaultValue
67
+ : globalContext;
68
+
69
+ // Get component and set it to `c`
70
+ if (oldVNode._component) {
71
+ c = newVNode._component = oldVNode._component;
72
+ clearProcessingException = c._processingException = c._pendingError;
73
+ } else {
74
+ // Instantiate the new component
75
+ if ('prototype' in newType && newType.prototype.render) {
76
+ // @ts-ignore The check above verifies that newType is suppose to be constructed
77
+ newVNode._component = c = new newType(newProps, componentContext); // eslint-disable-line new-cap
78
+ } else {
79
+ // @ts-ignore Trust me, Component implements the interface we want
80
+ newVNode._component = c = new Component(newProps, componentContext);
81
+ c.constructor = newType;
82
+ c.render = doRender;
83
+ }
84
+ if (provider) provider.sub(c);
85
+
86
+ c.props = newProps;
87
+ if (!c.state) c.state = {};
88
+ c.context = componentContext;
89
+ c._globalContext = globalContext;
90
+ isNew = c._dirty = true;
91
+ c._renderCallbacks = [];
92
+ }
93
+
94
+ // Invoke getDerivedStateFromProps
95
+ if (c._nextState == null) {
96
+ c._nextState = c.state;
97
+ }
98
+ if (newType.getDerivedStateFromProps != null) {
99
+ if (c._nextState == c.state) {
100
+ c._nextState = assign({}, c._nextState);
101
+ }
102
+
103
+ assign(
104
+ c._nextState,
105
+ newType.getDerivedStateFromProps(newProps, c._nextState)
106
+ );
107
+ }
108
+
109
+ oldProps = c.props;
110
+ oldState = c.state;
111
+
112
+ // Invoke pre-render lifecycle methods
113
+ if (isNew) {
114
+ if (
115
+ newType.getDerivedStateFromProps == null &&
116
+ c.componentWillMount != null
117
+ ) {
118
+ c.componentWillMount();
119
+ }
120
+
121
+ if (c.componentDidMount != null) {
122
+ c._renderCallbacks.push(c.componentDidMount);
123
+ }
124
+ } else {
125
+ if (
126
+ newType.getDerivedStateFromProps == null &&
127
+ newProps !== oldProps &&
128
+ c.componentWillReceiveProps != null
129
+ ) {
130
+ c.componentWillReceiveProps(newProps, componentContext);
131
+ }
132
+
133
+ if (
134
+ (!c._force &&
135
+ c.shouldComponentUpdate != null &&
136
+ c.shouldComponentUpdate(
137
+ newProps,
138
+ c._nextState,
139
+ componentContext
140
+ ) === false) ||
141
+ newVNode._original === oldVNode._original
142
+ ) {
143
+ c.props = newProps;
144
+ c.state = c._nextState;
145
+ // More info about this here: https://gist.github.com/JoviDeCroock/bec5f2ce93544d2e6070ef8e0036e4e8
146
+ if (newVNode._original !== oldVNode._original) c._dirty = false;
147
+ c._vnode = newVNode;
148
+ newVNode._dom = oldVNode._dom;
149
+ newVNode._children = oldVNode._children;
150
+ newVNode._children.forEach(vnode => {
151
+ if (vnode) vnode._parent = newVNode;
152
+ });
153
+ if (c._renderCallbacks.length) {
154
+ commitQueue.push(c);
155
+ }
156
+
157
+ break outer;
158
+ }
159
+
160
+ if (c.componentWillUpdate != null) {
161
+ c.componentWillUpdate(newProps, c._nextState, componentContext);
162
+ }
163
+
164
+ if (c.componentDidUpdate != null) {
165
+ c._renderCallbacks.push(() => {
166
+ c.componentDidUpdate(oldProps, oldState, snapshot);
167
+ });
168
+ }
169
+ }
170
+
171
+ c.context = componentContext;
172
+ c.props = newProps;
173
+ c.state = c._nextState;
174
+
175
+ if ((tmp = options._render)) tmp(newVNode);
176
+
177
+ c._dirty = false;
178
+ c._vnode = newVNode;
179
+ c._parentDom = parentDom;
180
+
181
+ tmp = c.render(c.props, c.state, c.context);
182
+
183
+ // Handle setState called in render, see #2553
184
+ c.state = c._nextState;
185
+
186
+ if (c.getChildContext != null) {
187
+ globalContext = assign(assign({}, globalContext), c.getChildContext());
188
+ }
189
+
190
+ if (!isNew && c.getSnapshotBeforeUpdate != null) {
191
+ snapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);
192
+ }
193
+
194
+ let isTopLevelFragment =
195
+ tmp != null && tmp.type === Fragment && tmp.key == null;
196
+ let renderResult = isTopLevelFragment ? tmp.props.children : tmp;
197
+
198
+ diffChildren(
199
+ parentDom,
200
+ Array.isArray(renderResult) ? renderResult : [renderResult],
201
+ newVNode,
202
+ oldVNode,
203
+ globalContext,
204
+ isSvg,
205
+ excessDomChildren,
206
+ commitQueue,
207
+ oldDom,
208
+ isHydrating
209
+ );
210
+
211
+ c.base = newVNode._dom;
212
+
213
+ // We successfully rendered this VNode, unset any stored hydration/bailout state:
214
+ newVNode._hydrating = null;
215
+
216
+ if (c._renderCallbacks.length) {
217
+ commitQueue.push(c);
218
+ }
219
+
220
+ if (clearProcessingException) {
221
+ c._pendingError = c._processingException = null;
222
+ }
223
+
224
+ c._force = false;
225
+ } else if (
226
+ excessDomChildren == null &&
227
+ newVNode._original === oldVNode._original
228
+ ) {
229
+ newVNode._children = oldVNode._children;
230
+ newVNode._dom = oldVNode._dom;
231
+ } else {
232
+ newVNode._dom = diffElementNodes(
233
+ oldVNode._dom,
234
+ newVNode,
235
+ oldVNode,
236
+ globalContext,
237
+ isSvg,
238
+ excessDomChildren,
239
+ commitQueue,
240
+ isHydrating
241
+ );
242
+ }
243
+
244
+ if ((tmp = options.diffed)) tmp(newVNode);
245
+ } catch (e) {
246
+ newVNode._original = null;
247
+ // if hydrating or creating initial tree, bailout preserves DOM:
248
+ if (isHydrating || excessDomChildren != null) {
249
+ newVNode._dom = oldDom;
250
+ newVNode._hydrating = !!isHydrating;
251
+ excessDomChildren[excessDomChildren.indexOf(oldDom)] = null;
252
+ // ^ could possibly be simplified to:
253
+ // excessDomChildren.length = 0;
254
+ }
255
+ options._catchError(e, newVNode, oldVNode);
256
+ }
257
+ }
258
+
259
+ /**
260
+ * @param {Array<import('../internal').Component>} commitQueue List of components
261
+ * which have callbacks to invoke in commitRoot
262
+ * @param {import('../internal').VNode} root
263
+ */
264
+ export function commitRoot(commitQueue, root) {
265
+ if (options._commit) options._commit(root, commitQueue);
266
+
267
+ commitQueue.some(c => {
268
+ try {
269
+ // @ts-ignore Reuse the commitQueue variable here so the type changes
270
+ commitQueue = c._renderCallbacks;
271
+ c._renderCallbacks = [];
272
+ commitQueue.some(cb => {
273
+ // @ts-ignore See above ts-ignore on commitQueue
274
+ cb.call(c);
275
+ });
276
+ } catch (e) {
277
+ options._catchError(e, c._vnode);
278
+ }
279
+ });
280
+ }
281
+
282
+ /**
283
+ * Diff two virtual nodes representing DOM element
284
+ * @param {import('../internal').PreactElement} dom The DOM element representing
285
+ * the virtual nodes being diffed
286
+ * @param {import('../internal').VNode} newVNode The new virtual node
287
+ * @param {import('../internal').VNode} oldVNode The old virtual node
288
+ * @param {object} globalContext The current context object
289
+ * @param {boolean} isSvg Whether or not this DOM node is an SVG node
290
+ * @param {*} excessDomChildren
291
+ * @param {Array<import('../internal').Component>} commitQueue List of components
292
+ * which have callbacks to invoke in commitRoot
293
+ * @param {boolean} isHydrating Whether or not we are in hydration
294
+ * @returns {import('../internal').PreactElement}
295
+ */
296
+ function diffElementNodes(
297
+ dom,
298
+ newVNode,
299
+ oldVNode,
300
+ globalContext,
301
+ isSvg,
302
+ excessDomChildren,
303
+ commitQueue,
304
+ isHydrating
305
+ ) {
306
+ let oldProps = oldVNode.props;
307
+ let newProps = newVNode.props;
308
+ let nodeType = newVNode.type;
309
+ let i = 0;
310
+
311
+ // Tracks entering and exiting SVG namespace when descending through the tree.
312
+ if (nodeType === 'svg') isSvg = true;
313
+
314
+ if (excessDomChildren != null) {
315
+ for (; i < excessDomChildren.length; i++) {
316
+ const child = excessDomChildren[i];
317
+
318
+ // if newVNode matches an element in excessDomChildren or the `dom`
319
+ // argument matches an element in excessDomChildren, remove it from
320
+ // excessDomChildren so it isn't later removed in diffChildren
321
+ if (
322
+ child &&
323
+ 'setAttribute' in child === !!nodeType &&
324
+ (nodeType ? child.localName === nodeType : child.nodeType === 3)
325
+ ) {
326
+ dom = child;
327
+ excessDomChildren[i] = null;
328
+ break;
329
+ }
330
+ }
331
+ }
332
+
333
+ if (dom == null) {
334
+ if (nodeType === null) {
335
+ // @ts-ignore createTextNode returns Text, we expect PreactElement
336
+ return document.createTextNode(newProps);
337
+ }
338
+
339
+ if (isSvg) {
340
+ dom = document.createElementNS(
341
+ 'http://www.w3.org/2000/svg',
342
+ // @ts-ignore We know `newVNode.type` is a string
343
+ nodeType
344
+ );
345
+ } else {
346
+ dom = document.createElement(
347
+ // @ts-ignore We know `newVNode.type` is a string
348
+ nodeType,
349
+ newProps.is && newProps
350
+ );
351
+ }
352
+
353
+ // we created a new parent, so none of the previously attached children can be reused:
354
+ excessDomChildren = null;
355
+ // we are creating a new node, so we can assume this is a new subtree (in case we are hydrating), this deopts the hydrate
356
+ isHydrating = false;
357
+ }
358
+
359
+ if (nodeType === null) {
360
+ // During hydration, we still have to split merged text from SSR'd HTML.
361
+ if (oldProps !== newProps && (!isHydrating || dom.data !== newProps)) {
362
+ dom.data = newProps;
363
+ }
364
+ } else {
365
+ // If excessDomChildren was not null, repopulate it with the current element's children:
366
+ excessDomChildren = excessDomChildren && slice.call(dom.childNodes);
367
+
368
+ oldProps = oldVNode.props || EMPTY_OBJ;
369
+
370
+ let oldHtml = oldProps.dangerouslySetInnerHTML;
371
+ let newHtml = newProps.dangerouslySetInnerHTML;
372
+
373
+ // During hydration, props are not diffed at all (including dangerouslySetInnerHTML)
374
+ // @TODO we should warn in debug mode when props don't match here.
375
+ if (!isHydrating) {
376
+ // But, if we are in a situation where we are using existing DOM (e.g. replaceNode)
377
+ // we should read the existing DOM attributes to diff them
378
+ if (excessDomChildren != null) {
379
+ oldProps = {};
380
+ for (i = 0; i < dom.attributes.length; i++) {
381
+ oldProps[dom.attributes[i].name] = dom.attributes[i].value;
382
+ }
383
+ }
384
+
385
+ if (newHtml || oldHtml) {
386
+ // Avoid re-applying the same '__html' if it did not changed between re-render
387
+ if (
388
+ !newHtml ||
389
+ ((!oldHtml || newHtml.__html != oldHtml.__html) &&
390
+ newHtml.__html !== dom.innerHTML)
391
+ ) {
392
+ dom.innerHTML = (newHtml && newHtml.__html) || '';
393
+ }
394
+ }
395
+ }
396
+
397
+ diffProps(dom, newProps, oldProps, isSvg, isHydrating);
398
+
399
+ // If the new vnode didn't have dangerouslySetInnerHTML, diff its children
400
+ if (newHtml) {
401
+ newVNode._children = [];
402
+ } else {
403
+ i = newVNode.props.children;
404
+ diffChildren(
405
+ dom,
406
+ Array.isArray(i) ? i : [i],
407
+ newVNode,
408
+ oldVNode,
409
+ globalContext,
410
+ isSvg && nodeType !== 'foreignObject',
411
+ excessDomChildren,
412
+ commitQueue,
413
+ excessDomChildren
414
+ ? excessDomChildren[0]
415
+ : oldVNode._children && getDomSibling(oldVNode, 0),
416
+ isHydrating
417
+ );
418
+
419
+ // Remove children that are not part of any vnode.
420
+ if (excessDomChildren != null) {
421
+ for (i = excessDomChildren.length; i--; ) {
422
+ if (excessDomChildren[i] != null) removeNode(excessDomChildren[i]);
423
+ }
424
+ }
425
+ }
426
+
427
+ // (as above, don't diff props during hydration)
428
+ if (!isHydrating) {
429
+ if (
430
+ 'value' in newProps &&
431
+ (i = newProps.value) !== undefined &&
432
+ // #2756 For the <progress>-element the initial value is 0,
433
+ // despite the attribute not being present. When the attribute
434
+ // is missing the progress bar is treated as indeterminate.
435
+ // To fix that we'll always update it when it is 0 for progress elements
436
+ (i !== oldProps.value ||
437
+ i !== dom.value ||
438
+ (nodeType === 'progress' && !i))
439
+ ) {
440
+ setProperty(dom, 'value', i, oldProps.value, false);
441
+ }
442
+ if (
443
+ 'checked' in newProps &&
444
+ (i = newProps.checked) !== undefined &&
445
+ i !== dom.checked
446
+ ) {
447
+ setProperty(dom, 'checked', i, oldProps.checked, false);
448
+ }
449
+ }
450
+ }
451
+
452
+ return dom;
453
+ }
454
+
455
+ /**
456
+ * Invoke or update a ref, depending on whether it is a function or object ref.
457
+ * @param {object|function} ref
458
+ * @param {any} value
459
+ * @param {import('../internal').VNode} vnode
460
+ */
461
+ export function applyRef(ref, value, vnode) {
462
+ try {
463
+ if (typeof ref == 'function') ref(value);
464
+ else ref.current = value;
465
+ } catch (e) {
466
+ options._catchError(e, vnode);
467
+ }
468
+ }
469
+
470
+ /**
471
+ * Unmount a virtual node from the tree and apply DOM changes
472
+ * @param {import('../internal').VNode} vnode The virtual node to unmount
473
+ * @param {import('../internal').VNode} parentVNode The parent of the VNode that
474
+ * initiated the unmount
475
+ * @param {boolean} [skipRemove] Flag that indicates that a parent node of the
476
+ * current element is already detached from the DOM.
477
+ */
478
+ export function unmount(vnode, parentVNode, skipRemove) {
479
+ let r;
480
+ if (options.unmount) options.unmount(vnode);
481
+
482
+ if ((r = vnode.ref)) {
483
+ if (!r.current || r.current === vnode._dom) applyRef(r, null, parentVNode);
484
+ }
485
+
486
+ if ((r = vnode._component) != null) {
487
+ if (r.componentWillUnmount) {
488
+ try {
489
+ r.componentWillUnmount();
490
+ } catch (e) {
491
+ options._catchError(e, parentVNode);
492
+ }
493
+ }
494
+
495
+ r.base = r._parentDom = null;
496
+ }
497
+
498
+ if ((r = vnode._children)) {
499
+ for (let i = 0; i < r.length; i++) {
500
+ if (r[i]) {
501
+ unmount(r[i], parentVNode, typeof vnode.type != 'function');
502
+ }
503
+ }
504
+ }
505
+
506
+ if (!skipRemove && vnode._dom != null) removeNode(vnode._dom);
507
+
508
+ // Must be set to `undefined` to properly clean up `_nextDom`
509
+ // for which `null` is a valid value. See comment in `create-element.js`
510
+ vnode._dom = vnode._nextDom = undefined;
511
+ }
512
+
513
+ /** The `.render()` method for a PFC backing instance. */
514
+ function doRender(props, state, context) {
515
+ return this.constructor(props, context);
516
+ }