onejs-core 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -0
- package/.github/workflows/jsr.yml +19 -0
- package/.prettierrc +5 -0
- package/3rdparty/preact/LICENSE +21 -0
- package/3rdparty/preact/clone-element.ts +45 -0
- package/3rdparty/preact/compat/Children.ts +21 -0
- package/3rdparty/preact/compat/forwardRef.ts +49 -0
- package/3rdparty/preact/compat/index.ts +3 -0
- package/3rdparty/preact/compat/memo.ts +34 -0
- package/3rdparty/preact/compat/util.ts +38 -0
- package/3rdparty/preact/component.ts +235 -0
- package/3rdparty/preact/constants.ts +3 -0
- package/3rdparty/preact/create-context.ts +71 -0
- package/3rdparty/preact/create-element.ts +98 -0
- package/3rdparty/preact/diff/catch-error.ts +40 -0
- package/3rdparty/preact/diff/children.ts +355 -0
- package/3rdparty/preact/diff/index.ts +563 -0
- package/3rdparty/preact/diff/props.ts +174 -0
- package/3rdparty/preact/hooks/index.ts +536 -0
- package/3rdparty/preact/hooks/internal.d.ts +85 -0
- package/3rdparty/preact/hooks.d.ts +145 -0
- package/3rdparty/preact/index.ts +13 -0
- package/3rdparty/preact/internal.d.ts +155 -0
- package/3rdparty/preact/jsx-runtime/index.ts +80 -0
- package/3rdparty/preact/jsx.d.ts +1008 -0
- package/3rdparty/preact/options.ts +16 -0
- package/3rdparty/preact/preact.d.ts +317 -0
- package/3rdparty/preact/render.ts +76 -0
- package/3rdparty/preact/signals/index.ts +443 -0
- package/3rdparty/preact/signals/internal.d.ts +36 -0
- package/3rdparty/preact/signals-core/index.ts +663 -0
- package/3rdparty/preact/style.d.ts +205 -0
- package/3rdparty/preact/util.ts +29 -0
- package/@DO_NOT_CHANGE.txt +3 -0
- package/README.md +33 -0
- package/definitions/app.d.ts +52048 -0
- package/definitions/augments.d.ts +16 -0
- package/definitions/globals.d.ts +34 -0
- package/definitions/index.d.ts +9 -0
- package/definitions/jsx.d.ts +517 -0
- package/definitions/modules.d.ts +29 -0
- package/definitions/onejs.d.ts +164 -0
- package/definitions/preact.jsx.d.ts +7 -0
- package/definitions/proto-overrides.d.ts +13 -0
- package/definitions/puerts.d.ts +31 -0
- package/definitions/unity-engine.d.ts +23 -0
- package/hooks/eventful.ts +56 -0
- package/import-transform.mjs +42 -0
- package/index.ts +44 -0
- package/jsr.json +10 -0
- package/onejs-tw-config.cjs +188 -0
- package/package.json +9 -0
- package/preloads/inject.ts +44 -0
- package/styling/index.tsx +80 -0
- package/styling/utils/generateAlphabeticName.ts +21 -0
- package/styling/utils/generateComponentId.ts +6 -0
- package/styling/utils/hash.ts +46 -0
- package/switch.cjs +185 -0
- package/uss-transform-plugin.cjs +83 -0
- package/utils/color-palettes.ts +3 -0
- package/utils/color-parser.ts +249 -0
- package/utils/float-parser.ts +31 -0
- package/utils/index.ts +12 -0
|
@@ -0,0 +1,563 @@
|
|
|
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, isArray, 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
|
+
c._stateCallbacks = [];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Invoke getDerivedStateFromProps
|
|
96
|
+
if (c._nextState == null) {
|
|
97
|
+
c._nextState = c.state;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (newType.getDerivedStateFromProps != null) {
|
|
101
|
+
if (c._nextState == c.state) {
|
|
102
|
+
c._nextState = assign({}, c._nextState);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
assign(
|
|
106
|
+
c._nextState,
|
|
107
|
+
newType.getDerivedStateFromProps(newProps, c._nextState)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
oldProps = c.props;
|
|
112
|
+
oldState = c.state;
|
|
113
|
+
c._vnode = newVNode;
|
|
114
|
+
|
|
115
|
+
// Invoke pre-render lifecycle methods
|
|
116
|
+
if (isNew) {
|
|
117
|
+
if (
|
|
118
|
+
newType.getDerivedStateFromProps == null &&
|
|
119
|
+
c.componentWillMount != null
|
|
120
|
+
) {
|
|
121
|
+
c.componentWillMount();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (c.componentDidMount != null) {
|
|
125
|
+
c._renderCallbacks.push(c.componentDidMount);
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
if (
|
|
129
|
+
newType.getDerivedStateFromProps == null &&
|
|
130
|
+
newProps !== oldProps &&
|
|
131
|
+
c.componentWillReceiveProps != null
|
|
132
|
+
) {
|
|
133
|
+
c.componentWillReceiveProps(newProps, componentContext);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (
|
|
137
|
+
(!c._force &&
|
|
138
|
+
c.shouldComponentUpdate != null &&
|
|
139
|
+
c.shouldComponentUpdate(
|
|
140
|
+
newProps,
|
|
141
|
+
c._nextState,
|
|
142
|
+
componentContext
|
|
143
|
+
) === false) ||
|
|
144
|
+
newVNode._original === oldVNode._original
|
|
145
|
+
) {
|
|
146
|
+
// More info about this here: https://gist.github.com/JoviDeCroock/bec5f2ce93544d2e6070ef8e0036e4e8
|
|
147
|
+
if (newVNode._original !== oldVNode._original) {
|
|
148
|
+
// When we are dealing with a bail because of sCU we have to update
|
|
149
|
+
// the props, state and dirty-state.
|
|
150
|
+
// when we are dealing with strict-equality we don't as the child could still
|
|
151
|
+
// be dirtied see #3883
|
|
152
|
+
c.props = newProps;
|
|
153
|
+
c.state = c._nextState;
|
|
154
|
+
c._dirty = false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// In cases of bailing due to strict-equality we have to reset force as well
|
|
158
|
+
c._force = false;
|
|
159
|
+
newVNode._dom = oldVNode._dom;
|
|
160
|
+
newVNode._children = oldVNode._children;
|
|
161
|
+
newVNode._children.forEach(vnode => {
|
|
162
|
+
if (vnode) vnode._parent = newVNode;
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
for (let i = 0; i < c._stateCallbacks.length; i++) {
|
|
166
|
+
c._renderCallbacks.push(c._stateCallbacks[i]);
|
|
167
|
+
}
|
|
168
|
+
c._stateCallbacks = [];
|
|
169
|
+
|
|
170
|
+
if (c._renderCallbacks.length) {
|
|
171
|
+
commitQueue.push(c);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
break outer;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (c.componentWillUpdate != null) {
|
|
178
|
+
c.componentWillUpdate(newProps, c._nextState, componentContext);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (c.componentDidUpdate != null) {
|
|
182
|
+
c._renderCallbacks.push(() => {
|
|
183
|
+
c.componentDidUpdate(oldProps, oldState, snapshot);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
c.context = componentContext;
|
|
189
|
+
c.props = newProps;
|
|
190
|
+
c._parentDom = parentDom;
|
|
191
|
+
|
|
192
|
+
let renderHook = options._render,
|
|
193
|
+
count = 0;
|
|
194
|
+
if ('prototype' in newType && newType.prototype.render) {
|
|
195
|
+
c.state = c._nextState;
|
|
196
|
+
c._dirty = false;
|
|
197
|
+
|
|
198
|
+
if (renderHook) renderHook(newVNode);
|
|
199
|
+
|
|
200
|
+
tmp = c.render(c.props, c.state, c.context);
|
|
201
|
+
|
|
202
|
+
for (let i = 0; i < c._stateCallbacks.length; i++) {
|
|
203
|
+
c._renderCallbacks.push(c._stateCallbacks[i]);
|
|
204
|
+
}
|
|
205
|
+
c._stateCallbacks = [];
|
|
206
|
+
} else {
|
|
207
|
+
do {
|
|
208
|
+
c._dirty = false;
|
|
209
|
+
if (renderHook) renderHook(newVNode);
|
|
210
|
+
|
|
211
|
+
tmp = c.render(c.props, c.state, c.context);
|
|
212
|
+
|
|
213
|
+
// Handle setState called in render, see #2553
|
|
214
|
+
c.state = c._nextState;
|
|
215
|
+
} while (c._dirty && ++count < 25);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Handle setState called in render, see #2553
|
|
219
|
+
c.state = c._nextState;
|
|
220
|
+
|
|
221
|
+
if (c.getChildContext != null) {
|
|
222
|
+
globalContext = assign(assign({}, globalContext), c.getChildContext());
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!isNew && c.getSnapshotBeforeUpdate != null) {
|
|
226
|
+
snapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let isTopLevelFragment =
|
|
230
|
+
tmp !== null && typeof tmp != "undefined" && tmp.type === Fragment && tmp.key == null; // MODDED
|
|
231
|
+
let renderResult = isTopLevelFragment ? tmp.props.children : tmp;
|
|
232
|
+
|
|
233
|
+
diffChildren(
|
|
234
|
+
parentDom,
|
|
235
|
+
isArray(renderResult) ? renderResult : [renderResult],
|
|
236
|
+
newVNode,
|
|
237
|
+
oldVNode,
|
|
238
|
+
globalContext,
|
|
239
|
+
isSvg,
|
|
240
|
+
excessDomChildren,
|
|
241
|
+
commitQueue,
|
|
242
|
+
oldDom,
|
|
243
|
+
isHydrating
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
c.base = newVNode._dom;
|
|
247
|
+
|
|
248
|
+
// We successfully rendered this VNode, unset any stored hydration/bailout state:
|
|
249
|
+
newVNode._hydrating = null;
|
|
250
|
+
|
|
251
|
+
if (c._renderCallbacks.length) {
|
|
252
|
+
commitQueue.push(c);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (clearProcessingException) {
|
|
256
|
+
c._pendingError = c._processingException = null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
c._force = false;
|
|
260
|
+
} else if (
|
|
261
|
+
excessDomChildren == null &&
|
|
262
|
+
newVNode._original === oldVNode._original
|
|
263
|
+
) {
|
|
264
|
+
newVNode._children = oldVNode._children;
|
|
265
|
+
newVNode._dom = oldVNode._dom;
|
|
266
|
+
} else {
|
|
267
|
+
newVNode._dom = diffElementNodes(
|
|
268
|
+
oldVNode._dom,
|
|
269
|
+
newVNode,
|
|
270
|
+
oldVNode,
|
|
271
|
+
globalContext,
|
|
272
|
+
isSvg,
|
|
273
|
+
excessDomChildren,
|
|
274
|
+
commitQueue,
|
|
275
|
+
isHydrating
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if ((tmp = options.diffed)) tmp(newVNode);
|
|
280
|
+
} catch (e) {
|
|
281
|
+
newVNode._original = null;
|
|
282
|
+
// if hydrating or creating initial tree, bailout preserves DOM:
|
|
283
|
+
if (isHydrating || excessDomChildren != null) {
|
|
284
|
+
newVNode._dom = oldDom;
|
|
285
|
+
newVNode._hydrating = !!isHydrating;
|
|
286
|
+
excessDomChildren[excessDomChildren.indexOf(oldDom)] = null;
|
|
287
|
+
// ^ could possibly be simplified to:
|
|
288
|
+
// excessDomChildren.length = 0;
|
|
289
|
+
}
|
|
290
|
+
options._catchError(e, newVNode, oldVNode);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* @param {Array<import('../internal').Component>} commitQueue List of components
|
|
296
|
+
* which have callbacks to invoke in commitRoot
|
|
297
|
+
* @param {import('../internal').VNode} root
|
|
298
|
+
*/
|
|
299
|
+
export function commitRoot(commitQueue, root) {
|
|
300
|
+
if (options._commit) options._commit(root, commitQueue);
|
|
301
|
+
|
|
302
|
+
commitQueue.some(c => {
|
|
303
|
+
try {
|
|
304
|
+
// @ts-ignore Reuse the commitQueue variable here so the type changes
|
|
305
|
+
commitQueue = c._renderCallbacks;
|
|
306
|
+
c._renderCallbacks = [];
|
|
307
|
+
commitQueue.some(cb => {
|
|
308
|
+
// @ts-ignore See above ts-ignore on commitQueue
|
|
309
|
+
cb.call(c);
|
|
310
|
+
});
|
|
311
|
+
} catch (e) {
|
|
312
|
+
options._catchError(e, c._vnode);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Diff two virtual nodes representing DOM element
|
|
319
|
+
* @param {import('../internal').PreactElement} dom The DOM element representing
|
|
320
|
+
* the virtual nodes being diffed
|
|
321
|
+
* @param {import('../internal').VNode} newVNode The new virtual node
|
|
322
|
+
* @param {import('../internal').VNode} oldVNode The old virtual node
|
|
323
|
+
* @param {object} globalContext The current context object
|
|
324
|
+
* @param {boolean} isSvg Whether or not this DOM node is an SVG node
|
|
325
|
+
* @param {*} excessDomChildren
|
|
326
|
+
* @param {Array<import('../internal').Component>} commitQueue List of components
|
|
327
|
+
* which have callbacks to invoke in commitRoot
|
|
328
|
+
* @param {boolean} isHydrating Whether or not we are in hydration
|
|
329
|
+
* @returns {import('../internal').PreactElement}
|
|
330
|
+
*/
|
|
331
|
+
function diffElementNodes(
|
|
332
|
+
dom,
|
|
333
|
+
newVNode,
|
|
334
|
+
oldVNode,
|
|
335
|
+
globalContext,
|
|
336
|
+
isSvg,
|
|
337
|
+
excessDomChildren,
|
|
338
|
+
commitQueue,
|
|
339
|
+
isHydrating
|
|
340
|
+
) {
|
|
341
|
+
let oldProps = oldVNode.props;
|
|
342
|
+
let newProps = newVNode.props;
|
|
343
|
+
let nodeType = newVNode.type;
|
|
344
|
+
let i = 0;
|
|
345
|
+
|
|
346
|
+
// Tracks entering and exiting SVG namespace when descending through the tree.
|
|
347
|
+
if (nodeType === 'svg') isSvg = true;
|
|
348
|
+
|
|
349
|
+
if (excessDomChildren != null) {
|
|
350
|
+
for (; i < excessDomChildren.length; i++) {
|
|
351
|
+
const child = excessDomChildren[i];
|
|
352
|
+
|
|
353
|
+
// if newVNode matches an element in excessDomChildren or the `dom`
|
|
354
|
+
// argument matches an element in excessDomChildren, remove it from
|
|
355
|
+
// excessDomChildren so it isn't later removed in diffChildren
|
|
356
|
+
if (
|
|
357
|
+
child &&
|
|
358
|
+
'setAttribute' in child === !!nodeType &&
|
|
359
|
+
(nodeType ? child.localName === nodeType : child.nodeType === 3)
|
|
360
|
+
) {
|
|
361
|
+
dom = child;
|
|
362
|
+
excessDomChildren[i] = null;
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (dom == null) {
|
|
369
|
+
if (nodeType === null) {
|
|
370
|
+
// @ts-ignore createTextNode returns Text, we expect PreactElement
|
|
371
|
+
return document.createTextNode(newProps);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (isSvg) {
|
|
375
|
+
// dom = document.createElementNS(
|
|
376
|
+
// 'http://www.w3.org/2000/svg',
|
|
377
|
+
// // @ts-ignore We know `newVNode.type` is a string
|
|
378
|
+
// nodeType
|
|
379
|
+
// );
|
|
380
|
+
} else {
|
|
381
|
+
dom = document.createElement(
|
|
382
|
+
// @ts-ignore We know `newVNode.type` is a string
|
|
383
|
+
nodeType,
|
|
384
|
+
newProps.is && newProps
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// we created a new parent, so none of the previously attached children can be reused:
|
|
389
|
+
excessDomChildren = null;
|
|
390
|
+
// we are creating a new node, so we can assume this is a new subtree (in case we are hydrating), this deopts the hydrate
|
|
391
|
+
isHydrating = false;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (nodeType === null) {
|
|
395
|
+
// During hydration, we still have to split merged text from SSR'd HTML.
|
|
396
|
+
if (oldProps !== newProps && (!isHydrating || dom.data !== newProps)) {
|
|
397
|
+
dom.data = newProps;
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
// If excessDomChildren was not null, repopulate it with the current element's children:
|
|
401
|
+
excessDomChildren = excessDomChildren && slice.call(dom.childNodes);
|
|
402
|
+
|
|
403
|
+
oldProps = oldVNode.props || EMPTY_OBJ;
|
|
404
|
+
|
|
405
|
+
let oldHtml = oldProps.dangerouslySetInnerHTML;
|
|
406
|
+
let newHtml = newProps.dangerouslySetInnerHTML;
|
|
407
|
+
|
|
408
|
+
// During hydration, props are not diffed at all (including dangerouslySetInnerHTML)
|
|
409
|
+
// @TODO we should warn in debug mode when props don't match here.
|
|
410
|
+
if (!isHydrating) {
|
|
411
|
+
// But, if we are in a situation where we are using existing DOM (e.g. replaceNode)
|
|
412
|
+
// we should read the existing DOM attributes to diff them
|
|
413
|
+
if (excessDomChildren != null) {
|
|
414
|
+
oldProps = {};
|
|
415
|
+
for (i = 0; i < dom.attributes.length; i++) {
|
|
416
|
+
oldProps[dom.attributes[i].name] = dom.attributes[i].value;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (newHtml || oldHtml) {
|
|
421
|
+
// Avoid re-applying the same '__html' if it did not changed between re-render
|
|
422
|
+
if (
|
|
423
|
+
!newHtml ||
|
|
424
|
+
((!oldHtml || newHtml.__html != oldHtml.__html) &&
|
|
425
|
+
newHtml.__html !== dom.innerHTML)
|
|
426
|
+
) {
|
|
427
|
+
dom.innerHTML = (newHtml && newHtml.__html) || '';
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
diffProps(dom, newProps, oldProps, isSvg, isHydrating);
|
|
433
|
+
|
|
434
|
+
// If the new vnode didn't have dangerouslySetInnerHTML, diff its children
|
|
435
|
+
if (newHtml) {
|
|
436
|
+
newVNode._children = [];
|
|
437
|
+
} else {
|
|
438
|
+
i = newVNode.props.children;
|
|
439
|
+
diffChildren(
|
|
440
|
+
dom,
|
|
441
|
+
isArray(i) ? i : [i],
|
|
442
|
+
newVNode,
|
|
443
|
+
oldVNode,
|
|
444
|
+
globalContext,
|
|
445
|
+
isSvg && nodeType !== 'foreignObject',
|
|
446
|
+
excessDomChildren,
|
|
447
|
+
commitQueue,
|
|
448
|
+
excessDomChildren
|
|
449
|
+
? excessDomChildren[0]
|
|
450
|
+
: oldVNode._children && getDomSibling(oldVNode, 0),
|
|
451
|
+
isHydrating
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
// Remove children that are not part of any vnode.
|
|
455
|
+
if (excessDomChildren != null) {
|
|
456
|
+
for (i = excessDomChildren.length; i--;) {
|
|
457
|
+
if (excessDomChildren[i] != null) removeNode(excessDomChildren[i]);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// (as above, don't diff props during hydration)
|
|
463
|
+
if (!isHydrating) {
|
|
464
|
+
if (
|
|
465
|
+
'value' in newProps &&
|
|
466
|
+
(i = newProps.value) !== undefined &&
|
|
467
|
+
// #2756 For the <progress>-element the initial value is 0,
|
|
468
|
+
// despite the attribute not being present. When the attribute
|
|
469
|
+
// is missing the progress bar is treated as indeterminate.
|
|
470
|
+
// To fix that we'll always update it when it is 0 for progress elements
|
|
471
|
+
(i !== dom.value ||
|
|
472
|
+
(nodeType === 'progress' && !i) ||
|
|
473
|
+
// This is only for IE 11 to fix <select> value not being updated.
|
|
474
|
+
// To avoid a stale select value we need to set the option.value
|
|
475
|
+
// again, which triggers IE11 to re-evaluate the select value
|
|
476
|
+
(nodeType === 'option' && i !== oldProps.value))
|
|
477
|
+
) {
|
|
478
|
+
setProperty(dom, 'value', i, oldProps.value, false);
|
|
479
|
+
}
|
|
480
|
+
if (
|
|
481
|
+
'checked' in newProps &&
|
|
482
|
+
(i = newProps.checked) !== undefined &&
|
|
483
|
+
i !== dom.checked
|
|
484
|
+
) {
|
|
485
|
+
setProperty(dom, 'checked', i, oldProps.checked, false);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return dom;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Invoke or update a ref, depending on whether it is a function or object ref.
|
|
495
|
+
* @param {object|function} ref
|
|
496
|
+
* @param {any} value
|
|
497
|
+
* @param {import('../internal').VNode} vnode
|
|
498
|
+
*/
|
|
499
|
+
export function applyRef(ref, value, vnode) {
|
|
500
|
+
try {
|
|
501
|
+
if (typeof ref == 'function') ref(value);
|
|
502
|
+
else ref.current = value;
|
|
503
|
+
} catch (e) {
|
|
504
|
+
options._catchError(e, vnode);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Unmount a virtual node from the tree and apply DOM changes
|
|
510
|
+
* @param {import('../internal').VNode} vnode The virtual node to unmount
|
|
511
|
+
* @param {import('../internal').VNode} parentVNode The parent of the VNode that
|
|
512
|
+
* initiated the unmount
|
|
513
|
+
* @param {boolean} [skipRemove] Flag that indicates that a parent node of the
|
|
514
|
+
* current element is already detached from the DOM.
|
|
515
|
+
*/
|
|
516
|
+
export function unmount(vnode, parentVNode, skipRemove = false) {
|
|
517
|
+
let r;
|
|
518
|
+
if (options.unmount) options.unmount(vnode);
|
|
519
|
+
|
|
520
|
+
if ((r = vnode.ref)) {
|
|
521
|
+
if (r.current !== null || r.current === vnode._dom) { // MODDED: s/!r.current/r.current !== null/
|
|
522
|
+
applyRef(r, null, parentVNode);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if ((r = vnode._component) !== null) { // MODDED
|
|
527
|
+
if (r.componentWillUnmount) {
|
|
528
|
+
try {
|
|
529
|
+
r.componentWillUnmount();
|
|
530
|
+
} catch (e) {
|
|
531
|
+
options._catchError(e, parentVNode);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
r.base = r._parentDom = null;
|
|
536
|
+
vnode._component = undefined;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if ((r = vnode._children)) {
|
|
540
|
+
for (let i = 0; i < r.length; i++) {
|
|
541
|
+
if (r[i]) {
|
|
542
|
+
unmount(
|
|
543
|
+
r[i],
|
|
544
|
+
parentVNode,
|
|
545
|
+
skipRemove || typeof vnode.type !== 'function'
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (!skipRemove && vnode._dom != null) {
|
|
552
|
+
removeNode(vnode._dom);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Must be set to `undefined` to properly clean up `_nextDom`
|
|
556
|
+
// for which `null` is a valid value. See comment in `create-element.js`
|
|
557
|
+
vnode._parent = vnode._dom = vnode._nextDom = undefined;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/** The `.render()` method for a PFC backing instance. */
|
|
561
|
+
function doRender(props, state, context) {
|
|
562
|
+
return this.constructor(props, context);
|
|
563
|
+
}
|