closures 0.7.1 → 0.7.2
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/README.md +41 -1
- package/dist/closures.cjs +445 -614
- package/dist/closures.js +443 -611
- package/dist/closures.min.js +1 -1
- package/package.json +1 -1
package/dist/closures.js
CHANGED
@@ -1,759 +1,591 @@
|
|
1
|
-
let
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
1
|
+
let NIL = void 0,
|
2
|
+
noop = _ => {},
|
3
|
+
propDirective = prop => ({
|
4
|
+
mount(el, value) {
|
5
|
+
el[prop] = value;
|
6
|
+
},
|
7
|
+
patch(el, newValue, oldValue) {
|
8
|
+
if (newValue !== oldValue) el[prop] = newValue;
|
9
|
+
},
|
10
|
+
unmount(el) {
|
11
|
+
el[prop] = NIL;
|
12
|
+
}
|
13
|
+
}),
|
12
14
|
DEFAULT_ENV = {
|
13
|
-
|
14
|
-
|
15
|
+
isSVG: false,
|
16
|
+
redraw: noop,
|
17
|
+
directives: {
|
18
|
+
selected: propDirective('selected'),
|
19
|
+
checked: propDirective('checked'),
|
20
|
+
value: propDirective('value'),
|
21
|
+
innerHTML: propDirective('innerHTML')
|
22
|
+
}
|
15
23
|
},
|
16
24
|
ON_REMOVES = [],
|
17
|
-
|
18
|
-
|
19
|
-
NS_ATTRS = { show: XLINK_NS, actuate: XLINK_NS, href: XLINK_NS },
|
25
|
+
CLOSURE_TO_FN = new WeakMap(),
|
26
|
+
ON_CREATE_KEY = 'oncreate',
|
20
27
|
NUM = 1,
|
28
|
+
PARENT_DOM_KEY = '$$PETIT_DOM_REF',
|
29
|
+
EMPTY_OBJECT = {},
|
30
|
+
SVG_NS = 'http://www.w3.org/2000/svg',
|
31
|
+
XLINK_NS = 'http://www.w3.org/1999/xlink',
|
32
|
+
NS_ATTRS = { show: XLINK_NS, actuate: XLINK_NS, href: XLINK_NS },
|
33
|
+
REF_SINGLE = 1, // ref with single dom node
|
21
34
|
VTYPE_ELEMENT = 1,
|
35
|
+
REF_ARRAY = 4, // ref with array of nodes
|
36
|
+
REF_PARENT = 8, // ref with a child ref
|
22
37
|
VTYPE_FUNCTION = 2,
|
23
|
-
|
24
|
-
|
25
|
-
CMP_TO_CLOSURE = new WeakMap(),
|
26
|
-
CHILDS = new WeakMap(),
|
27
|
-
ID = _ => (NUM++).toString(),
|
28
|
-
noop = _ => {},
|
38
|
+
RETAIN_KEY = '=',
|
39
|
+
generateClosureId = _ => NUM++,
|
29
40
|
isFn = x => typeof x === 'function',
|
30
41
|
isStr = x => typeof x === 'string',
|
31
42
|
isObj = x => x !== null && typeof x === 'object',
|
32
43
|
isArr = x => Array.isArray(x),
|
33
|
-
|
44
|
+
toJson = v => JSON.stringify(v),
|
45
|
+
isEmpty = c => c === null || c === false || c === NIL || (isArr(c) && c.length === 0) || (c && c._t === RETAIN_KEY),
|
34
46
|
isNonEmptyArray = c => isArr(c) && c.length > 0,
|
35
|
-
isLeaf = c => isStr(c) || typeof c ===
|
47
|
+
isLeaf = c => isStr(c) || typeof c === 'number',
|
36
48
|
isElement = c => c && c.vtype === VTYPE_ELEMENT,
|
37
|
-
isRenderFunction = c => c && c.vtype === VTYPE_FUNCTION
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
49
|
+
isRenderFunction = c => c && c.vtype === VTYPE_FUNCTION;
|
50
|
+
|
51
|
+
let getDomNode = (ref) => {
|
52
|
+
let type = ref.type;
|
53
|
+
if (type === REF_SINGLE) return ref.node;
|
54
|
+
if (type === REF_PARENT) return getDomNode(ref.childRef);
|
55
|
+
if (type === REF_ARRAY) return getDomNode(ref.children[0]);
|
56
|
+
throw Error('Unknown ref type ' + toJson(ref));
|
57
|
+
};
|
58
|
+
|
59
|
+
let getNextSibling = ref => {
|
60
|
+
let type = ref.type;
|
61
|
+
if (type === REF_SINGLE) return ref.node.nextSibling;
|
62
|
+
if (type === REF_PARENT) return getNextSibling(ref.childRef);
|
63
|
+
if (type === REF_ARRAY) return getNextSibling(ref.children[ref.children.length - 1]);
|
64
|
+
throw Error('Unknown ref type ' + toJson(ref));
|
65
|
+
};
|
66
|
+
|
67
|
+
let insertDom = (parent, ref, nextSibling) => {
|
68
|
+
let type = ref.type;
|
69
|
+
if (type === REF_SINGLE) parent.insertBefore(ref.node, nextSibling);
|
70
|
+
else if (type === REF_PARENT) insertDom(parent, ref.childRef, nextSibling);
|
71
|
+
else if (type === REF_ARRAY)
|
72
|
+
for (let i = 0; i < ref.children.length; i++)
|
73
|
+
insertDom(parent, ref.children[i], nextSibling);
|
74
|
+
else throw Error('Unknown ref type ' + toJson(ref));
|
75
|
+
};
|
76
|
+
|
77
|
+
let removeDom = (parent, ref) => {
|
78
|
+
let type = ref.type;
|
79
|
+
if (type === REF_SINGLE) parent.removeChild(ref.node);
|
80
|
+
else if (type === REF_PARENT) removeDom(parent, ref.childRef);
|
81
|
+
else if (type === REF_ARRAY)
|
82
|
+
for (let i = 0; i < ref.children.length; i++)
|
83
|
+
removeDom(parent, ref.children[i]);
|
84
|
+
else throw Error('Unknown ref type ' + toJson(ref));
|
85
|
+
};
|
86
|
+
|
87
|
+
let replaceDom = (parent, newRef, oldRef) => {
|
88
|
+
insertDom(parent, newRef, getDomNode(oldRef));
|
89
|
+
removeDom(parent, oldRef);
|
90
|
+
};
|
42
91
|
|
43
|
-
|
92
|
+
let setDomAttribute = (el, attr, value, isSVG) => {
|
93
|
+
if (value === true) el.setAttribute(attr, '');
|
94
|
+
else if (value === false) el.removeAttribute(attr);
|
95
|
+
else (isSVG && NS_ATTRS[attr])
|
96
|
+
? el.setAttributeNS(NS_ATTRS[attr], attr, value)
|
97
|
+
: el.setAttribute(attr, value);
|
98
|
+
};
|
44
99
|
|
45
|
-
|
46
|
-
let props
|
47
|
-
|
48
|
-
|
49
|
-
|
100
|
+
let mountAttributes = (el, props, env) => {
|
101
|
+
for (let key in props) {
|
102
|
+
if (key === 'key' || key === 'children' || key === ON_CREATE_KEY || key in env.directives) continue;
|
103
|
+
else if (key.startsWith('on'))
|
104
|
+
el[key.toLowerCase()] = ev => { props[key](ev); !env.manualRedraw && env.redraw(); };
|
105
|
+
else setDomAttribute(el, key, props[key], env.isSVG);
|
106
|
+
}
|
107
|
+
};
|
50
108
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
: props;
|
109
|
+
let patchAttributes = (el, newProps, oldProps, env) => {
|
110
|
+
let key;
|
111
|
+
for (key in newProps) {
|
112
|
+
if (key === 'key' || key === 'children' || key === ON_CREATE_KEY || key in env.directives)
|
113
|
+
continue;
|
57
114
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
if (
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
}
|
66
|
-
__tag = __tag ?? 'div';
|
115
|
+
let oldValue = oldProps[key],
|
116
|
+
newValue = newProps[key];
|
117
|
+
|
118
|
+
if (oldValue !== newValue)
|
119
|
+
key.startsWith('on')
|
120
|
+
? el[key.toLowerCase()] = ev => { newValue(ev); !env.manualRedraw && env.redraw(); }
|
121
|
+
: setDomAttribute(el, key, newValue, env.isSVG);
|
67
122
|
}
|
68
123
|
|
69
|
-
|
70
|
-
|
124
|
+
for (key in oldProps) {
|
125
|
+
if (key === 'key' || key === 'children' || key in newProps || key in env.directives)
|
126
|
+
continue;
|
71
127
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
key
|
87
|
-
|
88
|
-
|
89
|
-
|
128
|
+
if (key.startsWith('on')) el[key.toLowerCase()] = NIL;
|
129
|
+
else el.removeAttribute(key);
|
130
|
+
}
|
131
|
+
};
|
132
|
+
|
133
|
+
let mountDirectives = (el, props, env) => {
|
134
|
+
for (let key in props)
|
135
|
+
if (key in env.directives)
|
136
|
+
env.directives[key].mount(el, props[key]);
|
137
|
+
};
|
138
|
+
|
139
|
+
let patchDirectives = (el, newProps, oldProps, env) => {
|
140
|
+
let key;
|
141
|
+
for (key in newProps)
|
142
|
+
if (key in env.directives)
|
143
|
+
env.directives[key].patch(el, newProps[key], oldProps[key]);
|
144
|
+
|
145
|
+
for (key in oldProps)
|
146
|
+
if (key in env.directives && !(key in newProps))
|
147
|
+
env.directives[key].unmount(el, oldProps[key]);
|
148
|
+
};
|
90
149
|
|
91
|
-
|
150
|
+
let unmountDirectives = (el, props, env) => {
|
151
|
+
for (let key in props)
|
152
|
+
if (key in env.directives)
|
153
|
+
env.directives[key].unmount(el, props[key]);
|
154
|
+
};
|
92
155
|
|
93
|
-
|
94
|
-
let
|
95
|
-
let env = Object.assign({}, DEFAULT_ENV);
|
96
|
-
Object.assign(env.directives, options.directives);
|
97
|
-
if (rootRef == null) {
|
98
|
-
let ref = mount(vnode, env);
|
99
|
-
parentDomNode.$$PETIT_DOM_REF = { ref, vnode };
|
100
|
-
parentDomNode.textContent = "";
|
101
|
-
insertDom(parentDomNode, ref, null);
|
102
|
-
} else {
|
103
|
-
rootRef.ref = patchInPlace(
|
104
|
-
parentDomNode,
|
105
|
-
vnode,
|
106
|
-
rootRef.vnode,
|
107
|
-
rootRef.ref,
|
108
|
-
env
|
109
|
-
);
|
110
|
-
rootRef.vnode = vnode;
|
111
|
-
}
|
112
|
-
}
|
156
|
+
let mount = (vnode, env, closureId, closure, onRemove = noop) => {
|
157
|
+
let baseRef = { closureId, closure, onRemove };
|
113
158
|
|
114
|
-
|
115
|
-
|
116
|
-
constructor(props, env) {
|
117
|
-
this.props = props;
|
118
|
-
this._STATE_ = {
|
119
|
-
env,
|
120
|
-
vnode: null,
|
121
|
-
parentDomNode: null,
|
122
|
-
ref: mount(null)
|
123
|
-
};
|
124
|
-
this.render = this.render.bind(this);
|
125
|
-
}
|
159
|
+
if (isEmpty(vnode))
|
160
|
+
return { ...baseRef, type: REF_SINGLE, node: document.createComment('NULL') };
|
126
161
|
|
127
|
-
|
128
|
-
|
129
|
-
this.props = props;
|
130
|
-
}
|
162
|
+
if (isLeaf(vnode))
|
163
|
+
return { ...baseRef, type: REF_SINGLE, node: document.createTextNode(vnode) };
|
131
164
|
|
132
|
-
|
133
|
-
let
|
134
|
-
|
135
|
-
state.vnode = vnode;
|
136
|
-
if (state.parentDomNode === null) {
|
137
|
-
let parentNode = getParentNode(state.ref);
|
138
|
-
if (parentNode === null) {
|
139
|
-
state.ref = mount(vnode, state.env);
|
140
|
-
return;
|
141
|
-
} else {
|
142
|
-
state.parentDomNode = parentNode;
|
143
|
-
}
|
144
|
-
}
|
145
|
-
// here we are sure state.parentDOMNode is defined
|
146
|
-
state.ref = patchInPlace(
|
147
|
-
state.parentDomNode,
|
148
|
-
vnode,
|
149
|
-
oldVNode,
|
150
|
-
state.ref,
|
151
|
-
state.env
|
152
|
-
);
|
153
|
-
}
|
154
|
-
}
|
165
|
+
if (isElement(vnode)) {
|
166
|
+
let node,
|
167
|
+
{ _t, props } = vnode;
|
155
168
|
|
156
|
-
|
157
|
-
|
158
|
-
return {
|
159
|
-
type: REF_SINGLE,
|
160
|
-
node: document.createComment("NULL"),
|
161
|
-
};
|
162
|
-
} else if (isLeaf(vnode)) {
|
163
|
-
return {
|
164
|
-
type: REF_SINGLE,
|
165
|
-
node: document.createTextNode(vnode),
|
166
|
-
};
|
167
|
-
} else if (isElement(vnode)) {
|
168
|
-
let node;
|
169
|
-
let { __tag, props } = vnode;
|
170
|
-
if (__tag === "svg" && !env.isSvg) {
|
171
|
-
env = Object.assign({}, env, { isSVG: true });
|
172
|
-
}
|
173
|
-
// TODO : {is} for custom elements
|
174
|
-
if (!env.isSVG) {
|
175
|
-
node = document.createElement(__tag);
|
176
|
-
} else {
|
177
|
-
node = document.createElementNS(SVG_NS, __tag);
|
178
|
-
}
|
169
|
+
if (_t === 'svg' && !env.isSVG)
|
170
|
+
env = { ...env, isSVG: true };
|
179
171
|
|
180
|
-
|
181
|
-
|
172
|
+
if (!env.isSVG) node = document.createElement(_t);
|
173
|
+
else node = document.createElementNS(SVG_NS, _t);
|
174
|
+
|
175
|
+
isFn(props[ON_CREATE_KEY]) && props[ON_CREATE_KEY](node);
|
182
176
|
|
183
177
|
mountAttributes(node, props, env);
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
if (childrenRef != null) insertDom(node, childrenRef);
|
178
|
+
|
179
|
+
let children = props.children === NIL
|
180
|
+
? props.children
|
181
|
+
: mount(props.children, env);
|
182
|
+
|
183
|
+
if (children !== NIL) insertDom(node, children);
|
191
184
|
mountDirectives(node, props, env);
|
185
|
+
|
192
186
|
return {
|
187
|
+
...baseRef,
|
193
188
|
type: REF_SINGLE,
|
194
189
|
node,
|
195
|
-
children
|
196
|
-
}
|
197
|
-
}
|
190
|
+
children
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
if (isNonEmptyArray(vnode)) {
|
195
|
+
let i = 0, children = [];
|
196
|
+
for (; i < vnode.length; i++)
|
197
|
+
children.push(mount(vnode[i], env));
|
198
|
+
|
198
199
|
return {
|
200
|
+
...baseRef,
|
199
201
|
type: REF_ARRAY,
|
200
|
-
children
|
202
|
+
children
|
201
203
|
};
|
202
|
-
}
|
203
|
-
let childVNode = vnode.__tag(vnode.props);
|
204
|
+
}
|
204
205
|
|
205
|
-
|
206
|
-
|
207
|
-
view = childVNode,
|
208
|
-
id = ID(),
|
209
|
-
cmps = CLOSURE_TO_CMP.get(vnode.__tag) ?? {};
|
210
|
-
|
211
|
-
vnode.id = id;
|
212
|
-
cmp = toClosureCmp(vnode, view)
|
213
|
-
|
214
|
-
cmps[id] = cmp;
|
215
|
-
CLOSURE_TO_CMP.set(vnode.__tag, cmps);
|
216
|
-
CMP_TO_CLOSURE.set(cmp, vnode.__tag);
|
217
|
-
return mount(cmp);
|
218
|
-
}
|
206
|
+
if (isRenderFunction(vnode)) {
|
207
|
+
let childVnode = vnode._t(vnode.props); // if this is a closure component, this will be "oninit"
|
219
208
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
childs = CHILDS.get(parentCmp) || [],
|
233
|
-
idx = childs.length;
|
234
|
-
|
235
|
-
// attach method to remove self from parent
|
236
|
-
vnode.__tag.removeFromParent = _ => childs.splice(idx, 1);
|
237
|
-
|
238
|
-
childs.push({
|
239
|
-
id: vnode.id,
|
240
|
-
vtype: VTYPE_FUNCTION,
|
241
|
-
__tag: child_closure
|
242
|
-
});
|
243
|
-
|
244
|
-
CHILDS.set(parentCmp, childs);
|
209
|
+
if (isFn(childVnode)) {
|
210
|
+
// closure component
|
211
|
+
let id = generateClosureId(),
|
212
|
+
fnMap = CLOSURE_TO_FN.get(vnode._t) || new Map(),
|
213
|
+
onRemove = ON_REMOVES.pop() || noop;
|
214
|
+
|
215
|
+
fnMap.set(id, childVnode); // save renderFn
|
216
|
+
CLOSURE_TO_FN.set(vnode._t, fnMap); // closure -> Map(id -> renderFn)
|
217
|
+
|
218
|
+
let closure = vnode._t;
|
219
|
+
vnode._t = childVnode;
|
220
|
+
return mount(vnode, env, id, closure, onRemove);
|
245
221
|
}
|
246
222
|
|
247
|
-
vnode.__tag.mount(renderer);
|
248
223
|
return {
|
224
|
+
...baseRef,
|
249
225
|
type: REF_PARENT,
|
250
|
-
childRef:
|
251
|
-
childState:
|
226
|
+
childRef: mount(childVnode, env),
|
227
|
+
childState: childVnode
|
252
228
|
};
|
253
|
-
} else if (vnode instanceof Node) {
|
254
|
-
return {
|
255
|
-
type: REF_SINGLE,
|
256
|
-
node: vnode,
|
257
|
-
};
|
258
|
-
}
|
259
|
-
if (vnode === undefined) {
|
260
|
-
throw new Error("mount: vnode is undefined!");
|
261
229
|
}
|
262
230
|
|
263
|
-
|
264
|
-
}
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
newVNode,
|
269
|
-
oldVNode,
|
270
|
-
ref,
|
271
|
-
env = DEFAULT_ENV
|
272
|
-
) {
|
273
|
-
if (isObj(oldVNode) && isObj(newVNode))
|
274
|
-
newVNode.id = oldVNode.id;
|
275
|
-
|
276
|
-
if (oldVNode === newVNode) {
|
277
|
-
return ref;
|
278
|
-
} else if (isEmpty(newVNode) && isEmpty(oldVNode)) {
|
279
|
-
return ref;
|
280
|
-
} else if (isLeaf(newVNode) && isLeaf(oldVNode)) {
|
281
|
-
ref.node.nodeValue = newVNode;
|
282
|
-
return ref;
|
283
|
-
} else if (
|
284
|
-
isElement(newVNode) &&
|
285
|
-
isElement(oldVNode) &&
|
286
|
-
newVNode.__tag === oldVNode.__tag
|
287
|
-
) {
|
288
|
-
if (newVNode.__tag === "svg" && !env.isSvg) {
|
289
|
-
env = Object.assign({}, env, { isSVG: true });
|
290
|
-
}
|
291
|
-
patchAttributes(ref.node, newVNode.props, oldVNode.props, env);
|
292
|
-
let oldChildren = oldVNode.props.children;
|
293
|
-
let newChildren = newVNode.props.children;
|
294
|
-
if (oldChildren == null) {
|
295
|
-
if (newChildren != null) {
|
296
|
-
ref.children = mount(newChildren, env);
|
297
|
-
insertDom(ref.node, ref.children);
|
298
|
-
}
|
299
|
-
} else {
|
300
|
-
if (newChildren == null) {
|
301
|
-
ref.node.textContent = "";
|
302
|
-
unmount(oldChildren, ref.children, env);
|
303
|
-
ref.children = null;
|
304
|
-
} else {
|
305
|
-
ref.children = patchInPlace(
|
306
|
-
ref.node,
|
307
|
-
newChildren,
|
308
|
-
oldChildren,
|
309
|
-
ref.children,
|
310
|
-
env
|
311
|
-
);
|
312
|
-
}
|
313
|
-
}
|
314
|
-
patchDirectives(ref.node, newVNode.props, oldVNode.props, env);
|
315
|
-
return ref;
|
316
|
-
} else if (isNonEmptyArray(newVNode) && isNonEmptyArray(oldVNode)) {
|
317
|
-
patchChildren(parentDomNode, newVNode, oldVNode, ref, env);
|
318
|
-
return ref;
|
319
|
-
} else if (
|
320
|
-
isRenderFunction(newVNode) &&
|
321
|
-
isRenderFunction(oldVNode) &&
|
322
|
-
newVNode.__tag === oldVNode.__tag
|
323
|
-
) {
|
324
|
-
let renderFn = newVNode.__tag;
|
325
|
-
let shouldUpdate =
|
326
|
-
renderFn.shouldUpdate != null
|
327
|
-
? renderFn.shouldUpdate(oldVNode.props, newVNode.props)
|
328
|
-
: defaultShouldUpdate(oldVNode.props, newVNode.props);
|
329
|
-
if (shouldUpdate) {
|
330
|
-
let cmp,
|
331
|
-
id = oldVNode.id,
|
332
|
-
cmps = CLOSURE_TO_CMP.get(renderFn);
|
333
|
-
|
334
|
-
if (cmps && id && (cmp = cmps[id])) {
|
335
|
-
return patch(
|
336
|
-
parentDomNode,
|
337
|
-
{ ...cmp, props: newVNode.props },
|
338
|
-
cmp,
|
339
|
-
ref
|
340
|
-
);
|
341
|
-
}
|
231
|
+
if (vnode instanceof Node)
|
232
|
+
return { ...baseRef, type: REF_SINGLE, node: vnode };
|
233
|
+
|
234
|
+
if (vnode === NIL)
|
235
|
+
throw Error('mount: vnode is undefined');
|
342
236
|
|
343
|
-
|
344
|
-
|
345
|
-
parentDomNode,
|
346
|
-
childVNode,
|
347
|
-
ref.childState,
|
348
|
-
ref.childRef,
|
349
|
-
env
|
350
|
-
);
|
351
|
-
// We need to return a new ref in order for parent patches to
|
352
|
-
// properly replace changing DOM nodes
|
353
|
-
if (childRef !== ref.childRef) {
|
354
|
-
return {
|
355
|
-
type: REF_PARENT,
|
356
|
-
childRef,
|
357
|
-
childState: childVNode,
|
358
|
-
};
|
359
|
-
} else {
|
360
|
-
ref.childState = childVNode;
|
361
|
-
return ref;
|
362
|
-
}
|
363
|
-
} else {
|
364
|
-
return ref;
|
365
|
-
}
|
366
|
-
} else if (
|
367
|
-
isComponent(newVNode) &&
|
368
|
-
isComponent(oldVNode) &&
|
369
|
-
newVNode.__tag === oldVNode.__tag
|
370
|
-
) {
|
371
|
-
let renderer = ref.childState;
|
372
|
-
let state = renderer._STATE_;
|
373
|
-
state.env = env;
|
374
|
-
state.parentNode = parentDomNode;
|
375
|
-
renderer.setProps(newVNode.props);
|
376
|
-
newVNode.__tag.patch(renderer);
|
377
|
-
if (ref.childRef !== state.ref) {
|
378
|
-
return {
|
379
|
-
type: REF_PARENT,
|
380
|
-
childRef: state.ref,
|
381
|
-
childState: renderer,
|
382
|
-
};
|
383
|
-
} else {
|
384
|
-
return ref;
|
385
|
-
}
|
386
|
-
} else if (newVNode instanceof Node && oldVNode instanceof Node) {
|
387
|
-
ref.node = newVNode;
|
388
|
-
return ref;
|
389
|
-
} else {
|
390
|
-
return mount(newVNode, env);
|
391
|
-
}
|
392
|
-
}
|
237
|
+
throw Error('mount: Invalid vnode');
|
238
|
+
};
|
393
239
|
|
394
|
-
|
395
|
-
* Execute any compoenent specific unmount code
|
396
|
-
*/
|
397
|
-
function unmount(vnode, ref, env) {
|
398
|
-
// if (vnode instanceof Node || isEmpty(vnode) || isLeaf(vnode)) return;
|
240
|
+
let unmount = (vnode, ref, env) => {
|
399
241
|
if (isElement(vnode)) {
|
400
242
|
unmountDirectives(ref.node, vnode.props, env);
|
401
|
-
if (vnode.props.children
|
243
|
+
if (vnode.props.children !== NIL)
|
402
244
|
unmount(vnode.props.children, ref.children, env);
|
403
245
|
} else if (isNonEmptyArray(vnode)) {
|
404
|
-
vnode.
|
405
|
-
unmount(
|
406
|
-
);
|
246
|
+
for (let i = 0; i < vnode.length; i++)
|
247
|
+
unmount(vnode[i], ref.children[i], env);
|
407
248
|
} else if (isRenderFunction(vnode)) {
|
408
|
-
let
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
249
|
+
let closure = ref.closure,
|
250
|
+
closureId = ref.closureId,
|
251
|
+
onRemove = ref.onRemove,
|
252
|
+
fns = CLOSURE_TO_FN.get(closure);
|
253
|
+
|
254
|
+
if (fns && closureId && fns.get(closureId)) {
|
255
|
+
fns.delete(closureId);
|
256
|
+
!fns.size && CLOSURE_TO_FN.delete(closure);
|
257
|
+
onRemove();
|
413
258
|
}
|
414
259
|
|
415
260
|
unmount(ref.childState, ref.childRef, env);
|
416
|
-
} else if (isComponent(vnode)) {
|
417
|
-
vnode.__tag.unmount(ref.childState);
|
418
261
|
}
|
419
|
-
}
|
262
|
+
};
|
263
|
+
|
264
|
+
let patchInPlace = (parentDomNode, newVnode, oldVnode, ref, env) => {
|
265
|
+
let newRef = patch(parentDomNode, newVnode, oldVnode, ref, env);
|
420
266
|
|
421
|
-
function patchInPlace(parentDomNode, newVNode, oldVNode, ref, env) {
|
422
|
-
let newRef = patch(parentDomNode, newVNode, oldVNode, ref, env);
|
423
267
|
if (newRef !== ref) {
|
424
268
|
replaceDom(parentDomNode, newRef, ref);
|
425
|
-
unmount(
|
269
|
+
unmount(oldVnode, ref, env);
|
426
270
|
}
|
271
|
+
|
427
272
|
return newRef;
|
428
|
-
}
|
429
|
-
|
430
|
-
|
431
|
-
//
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
273
|
+
};
|
274
|
+
|
275
|
+
let patchChildren = (parentDomNode, newChildren, oldChildren, ref, env) => {
|
276
|
+
// we need to retrieve the next sibling before the old children get removed from the DOM
|
277
|
+
let i, idx, oldVnode, newVnode, oldRef, newRef, refMap, beforeNode,
|
278
|
+
nextNode = getNextSibling(ref),
|
279
|
+
children = Array(newChildren.length),
|
280
|
+
refChildren = ref.children,
|
281
|
+
newStart = 0,
|
437
282
|
oldStart = 0,
|
438
283
|
newEnd = newChildren.length - 1,
|
439
|
-
oldEnd =
|
440
|
-
|
441
|
-
|
284
|
+
oldEnd = oldChildren.length - 1;
|
285
|
+
|
442
286
|
while (newStart <= newEnd && oldStart <= oldEnd) {
|
443
|
-
if (refChildren[oldStart] ===
|
287
|
+
if (refChildren[oldStart] === NIL) {
|
444
288
|
oldStart++;
|
445
289
|
continue;
|
446
290
|
}
|
447
|
-
|
291
|
+
|
292
|
+
if (refChildren[oldEnd] === NIL) {
|
448
293
|
oldEnd--;
|
449
294
|
continue;
|
450
295
|
}
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
296
|
+
|
297
|
+
oldVnode = oldChildren[oldStart];
|
298
|
+
newVnode = newChildren[newStart];
|
299
|
+
|
300
|
+
if (oldVnode && newVnode && newVnode.key === oldVnode.key) {
|
455
301
|
oldRef = refChildren[oldStart];
|
456
302
|
newRef = children[newStart] = patchInPlace(
|
457
303
|
parentDomNode,
|
458
|
-
|
459
|
-
|
304
|
+
newVnode,
|
305
|
+
oldVnode,
|
460
306
|
oldRef,
|
461
307
|
env
|
462
308
|
);
|
309
|
+
|
463
310
|
newStart++;
|
464
311
|
oldStart++;
|
465
312
|
continue;
|
466
313
|
}
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
314
|
+
|
315
|
+
oldVnode = oldChildren[oldEnd];
|
316
|
+
newVnode = newChildren[newEnd];
|
317
|
+
|
318
|
+
if (oldVnode && newVnode && newVnode.key === oldVnode.key) {
|
471
319
|
oldRef = refChildren[oldEnd];
|
472
320
|
newRef = children[newEnd] = patchInPlace(
|
473
321
|
parentDomNode,
|
474
|
-
|
475
|
-
|
322
|
+
newVnode,
|
323
|
+
oldVnode,
|
476
324
|
oldRef,
|
477
325
|
env
|
478
326
|
);
|
327
|
+
|
479
328
|
newEnd--;
|
480
329
|
oldEnd--;
|
481
330
|
continue;
|
482
331
|
}
|
483
|
-
|
484
|
-
if (refMap
|
485
|
-
refMap = {};
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
refMap[oldVNode.key] = i;
|
490
|
-
}
|
332
|
+
|
333
|
+
if (refMap === NIL)
|
334
|
+
for (i = oldStart, refMap = {}; i <= oldEnd; i++) {
|
335
|
+
oldVnode = oldChildren[i];
|
336
|
+
if (oldVnode && oldVnode.key !== NIL)
|
337
|
+
refMap[oldVnode.key] = i;
|
491
338
|
}
|
492
|
-
|
339
|
+
|
340
|
+
newVnode = newChildren[newStart];
|
341
|
+
idx = newVnode && newVnode.key !== NIL ? refMap[newVnode.key] : NIL;
|
493
342
|
|
494
|
-
|
495
|
-
|
496
|
-
if (idx != null) {
|
497
|
-
oldVNode = oldchildren[idx];
|
343
|
+
if (idx !== NIL) {
|
344
|
+
oldVnode = oldChildren[idx];
|
498
345
|
oldRef = refChildren[idx];
|
499
346
|
newRef = children[newStart] = patch(
|
500
347
|
parentDomNode,
|
501
|
-
|
502
|
-
|
348
|
+
newVnode,
|
349
|
+
oldVnode,
|
503
350
|
oldRef,
|
504
351
|
env
|
505
352
|
);
|
353
|
+
|
506
354
|
insertDom(parentDomNode, newRef, getDomNode(refChildren[oldStart]));
|
355
|
+
|
507
356
|
if (newRef !== oldRef) {
|
508
357
|
removeDom(parentDomNode, oldRef);
|
509
|
-
unmount(
|
358
|
+
unmount(oldVnode, oldRef, env);
|
510
359
|
}
|
511
|
-
|
360
|
+
|
361
|
+
refChildren[idx] = NIL;
|
512
362
|
} else {
|
513
|
-
newRef = children[newStart] = mount(
|
363
|
+
newRef = children[newStart] = mount(newVnode, env);
|
514
364
|
insertDom(parentDomNode, newRef, getDomNode(refChildren[oldStart]));
|
515
365
|
}
|
366
|
+
|
516
367
|
newStart++;
|
517
368
|
}
|
518
|
-
|
519
|
-
|
520
|
-
newEnd
|
521
|
-
|
522
|
-
|
369
|
+
|
370
|
+
beforeNode = newEnd < newChildren.length - 1
|
371
|
+
? getDomNode(children[newEnd + 1])
|
372
|
+
: nextNode;
|
373
|
+
|
523
374
|
while (newStart <= newEnd) {
|
524
|
-
|
375
|
+
newRef = mount(newChildren[newStart], env);
|
525
376
|
children[newStart] = newRef;
|
526
377
|
insertDom(parentDomNode, newRef, beforeNode);
|
527
378
|
newStart++;
|
528
379
|
}
|
380
|
+
|
529
381
|
while (oldStart <= oldEnd) {
|
530
382
|
oldRef = refChildren[oldStart];
|
531
|
-
|
383
|
+
|
384
|
+
if (oldRef !== NIL) {
|
532
385
|
removeDom(parentDomNode, oldRef);
|
533
|
-
unmount(
|
386
|
+
unmount(oldChildren[oldStart], oldRef, env);
|
534
387
|
}
|
388
|
+
|
535
389
|
oldStart++;
|
536
390
|
}
|
391
|
+
|
537
392
|
ref.children = children;
|
538
|
-
}
|
393
|
+
};
|
539
394
|
|
540
|
-
|
541
|
-
if (
|
542
|
-
for (let key in p2) {
|
543
|
-
if (p1[key] !== p2[key]) return true;
|
544
|
-
}
|
545
|
-
return false;
|
546
|
-
}
|
395
|
+
let patch = (parentDomNode, newVnode, oldVnode, ref, env = { ...DEFAULT_ENV }) => {
|
396
|
+
if (newVnode && newVnode._t === RETAIN_KEY) return ref;
|
547
397
|
|
548
|
-
|
549
|
-
return {
|
550
|
-
mount(element, value) {``
|
551
|
-
element[prop] = value;
|
552
|
-
},
|
553
|
-
patch(element, newValue, oldValue) {
|
554
|
-
if (newValue !== oldValue) {
|
555
|
-
element[prop] = newValue;
|
556
|
-
}
|
557
|
-
},
|
558
|
-
unmount(element, _) {
|
559
|
-
element[prop] = null;
|
560
|
-
},
|
561
|
-
};
|
562
|
-
}
|
398
|
+
let closure, closureId;
|
563
399
|
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
} else if (ref.type === REF_ARRAY) {
|
568
|
-
return getDomNode(ref.children[0]);
|
569
|
-
} else if (ref.type === REF_PARENT) {
|
570
|
-
return getDomNode(ref.childRef);
|
400
|
+
if (isObj(ref)) {
|
401
|
+
closure = ref.closure;
|
402
|
+
closureId = ref.closureId;
|
571
403
|
}
|
572
|
-
throw new Error("Unkown ref type " + JSON.stringify(ref));
|
573
|
-
}
|
574
404
|
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
} else if (ref.type === REF_PARENT) {
|
581
|
-
return getParentNode(ref.childRef);
|
582
|
-
}
|
583
|
-
throw new Error("Unkown ref type " + ref);
|
584
|
-
}
|
405
|
+
if (isRenderFunction(newVnode) && isRenderFunction(oldVnode) && (newVnode._t === oldVnode._t || (closure && closureId))) {
|
406
|
+
// x is either a renderFn or a closure
|
407
|
+
let x = newVnode._t,
|
408
|
+
fn,
|
409
|
+
fns = CLOSURE_TO_FN.get(closure);
|
585
410
|
|
586
|
-
|
587
|
-
|
588
|
-
return ref.node.nextSibling;
|
589
|
-
} else if (ref.type === REF_ARRAY) {
|
590
|
-
return getNextSibling(ref.children[ref.children.length - 1]);
|
591
|
-
} else if (ref.type === REF_PARENT) {
|
592
|
-
return getNextSibling(ref.childRef);
|
593
|
-
}
|
594
|
-
throw new Error("Unkown ref type " + JSON.stringify(ref));
|
595
|
-
}
|
411
|
+
if (fns && closureId && (fn = fns.get(closureId)))
|
412
|
+
x = fn;
|
596
413
|
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
insertDom(parent, ref.childRef, nextSibling);
|
606
|
-
} else {
|
607
|
-
throw new Error("Unkown ref type " + JSON.stringify(ref));
|
608
|
-
}
|
609
|
-
}
|
414
|
+
let childVnode = x(newVnode.props),
|
415
|
+
childRef = patch(
|
416
|
+
parentDomNode,
|
417
|
+
childVnode,
|
418
|
+
ref.childState,
|
419
|
+
ref.childRef,
|
420
|
+
env
|
421
|
+
);
|
610
422
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
423
|
+
// we need to return a new ref in order for parent patches to properly replace changing DOM nodes
|
424
|
+
if (childRef !== ref.childRef)
|
425
|
+
return {
|
426
|
+
type: REF_PARENT,
|
427
|
+
childRef,
|
428
|
+
childState: childVnode
|
429
|
+
};
|
430
|
+
else {
|
431
|
+
ref.childState = childVnode;
|
432
|
+
return ref;
|
433
|
+
}
|
622
434
|
}
|
623
|
-
}
|
624
435
|
|
625
|
-
|
626
|
-
|
627
|
-
removeDom(parent, oldRef);
|
628
|
-
}
|
436
|
+
if (oldVnode === newVnode || (isEmpty(newVnode) && isEmpty(oldVnode)))
|
437
|
+
return ref;
|
629
438
|
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
}
|
439
|
+
if (isLeaf(newVnode) && isLeaf(oldVnode)) {
|
440
|
+
// leafs just need to have node value updated
|
441
|
+
ref.node.nodeValue = newVnode;
|
442
|
+
return ref;
|
635
443
|
}
|
636
|
-
}
|
637
444
|
|
638
|
-
|
639
|
-
|
640
|
-
if (
|
641
|
-
env
|
642
|
-
}
|
643
|
-
}
|
644
|
-
for (let key in oldProps) {
|
645
|
-
if (key in env.directives && !(key in newProps)) {
|
646
|
-
env.directives[key].unmount(domElement, oldProps[key]);
|
647
|
-
}
|
648
|
-
}
|
649
|
-
}
|
445
|
+
if (isElement(newVnode) && isElement(oldVnode) && newVnode._t === oldVnode._t) {
|
446
|
+
// make sure env has isSVG flag set to true
|
447
|
+
if (newVnode._t === 'svg' && !env.isSVG)
|
448
|
+
env = { ...env, isSVG: true };
|
650
449
|
|
651
|
-
|
652
|
-
|
653
|
-
if (key in env.directives) {
|
654
|
-
env.directives[key].unmount(domElement, props[key]);
|
655
|
-
}
|
656
|
-
}
|
657
|
-
}
|
450
|
+
// update the node DOM attributes with the new props
|
451
|
+
patchAttributes(ref.node, newVnode.props, oldVnode.props, env);
|
658
452
|
|
659
|
-
|
660
|
-
|
661
|
-
if (key === "key" || key === "children" || key in env.directives) continue;
|
662
|
-
if (key.startsWith("on")) {
|
663
|
-
let cmp = MOUNTING[MOUNTING.length - 1];
|
664
|
-
domElement[key.toLowerCase()] = cmp ? cmp.__tag.event(props[key]) : props[key];
|
665
|
-
} else {
|
666
|
-
setDOMAttribute(domElement, key, props[key], env.isSVG);
|
667
|
-
}
|
668
|
-
}
|
669
|
-
}
|
453
|
+
let oldChildren = oldVnode.props.children,
|
454
|
+
newChildren = newVnode.props.children;
|
670
455
|
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
if (
|
678
|
-
|
679
|
-
|
456
|
+
if (oldChildren === NIL) {
|
457
|
+
if (newChildren !== NIL) {
|
458
|
+
ref.children = mount(newChildren, env);
|
459
|
+
insertDom(ref.node, ref.children);
|
460
|
+
}
|
461
|
+
} else {
|
462
|
+
if (newChildren === NIL) {
|
463
|
+
ref.node.textContent = '';
|
464
|
+
unmount(oldChildren, ref.children, env);
|
465
|
+
ref.children = NIL;
|
680
466
|
} else {
|
681
|
-
|
467
|
+
ref.children = patchInPlace(
|
468
|
+
ref.node,
|
469
|
+
newChildren,
|
470
|
+
oldChildren,
|
471
|
+
ref.children,
|
472
|
+
env
|
473
|
+
);
|
682
474
|
}
|
683
475
|
}
|
476
|
+
|
477
|
+
patchDirectives(ref.node, newVnode.props, oldVnode.props, env);
|
478
|
+
return ref;
|
684
479
|
}
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
480
|
+
|
481
|
+
if (isNonEmptyArray(newVnode) && isNonEmptyArray(oldVnode)) {
|
482
|
+
patchChildren(parentDomNode, newVnode, oldVnode, ref, env);
|
483
|
+
return ref;
|
484
|
+
}
|
485
|
+
|
486
|
+
if (newVnode instanceof Node && oldVnode instanceof Node) {
|
487
|
+
ref.node = newVnode;
|
488
|
+
return ref;
|
489
|
+
}
|
490
|
+
|
491
|
+
return mount(newVnode, env);
|
492
|
+
};
|
493
|
+
|
494
|
+
export function h(_t, ...children) {
|
495
|
+
let props = children[0];
|
496
|
+
if (props && isObj(props) && !isArr(props) && !(props._t || props.props))
|
497
|
+
children.shift();
|
498
|
+
else props = EMPTY_OBJECT;
|
499
|
+
|
500
|
+
props =
|
501
|
+
children.length > 1
|
502
|
+
? { ...props, children }
|
503
|
+
: children.length === 1
|
504
|
+
? { ...props, children: children[0] }
|
505
|
+
: props;
|
506
|
+
|
507
|
+
// parse tag
|
508
|
+
if (isStr(_t)) {
|
509
|
+
let idx = _t.indexOf('.');
|
510
|
+
if (~idx) {
|
511
|
+
let className = _t.slice(idx + 1).replace(/\./g, ' ')
|
512
|
+
props.class = props.class ? className + ' ' + String(props.class) : className;
|
513
|
+
_t = _t.slice(0, idx);
|
697
514
|
}
|
515
|
+
_t = _t || 'div';
|
698
516
|
}
|
517
|
+
|
518
|
+
if (props.key !== props.key) throw new Error("Invalid NaN key");
|
519
|
+
|
520
|
+
let vtype =
|
521
|
+
isStr(_t)
|
522
|
+
? VTYPE_ELEMENT
|
523
|
+
: _t && isFn(_t.mount)
|
524
|
+
? VTYPE_COMPONENT
|
525
|
+
: isFn(_t)
|
526
|
+
? VTYPE_FUNCTION
|
527
|
+
: NIL;
|
528
|
+
|
529
|
+
if (vtype === NIL) throw new Error("Invalid VNode type");
|
530
|
+
|
531
|
+
// returns a vnode
|
532
|
+
return {
|
533
|
+
vtype, // (number) VTYPE_ELEMENT | VTYPE_COMPONENT | VTYPE_FUNCTION
|
534
|
+
_t, // (string | object | function)
|
535
|
+
key: props.key, // string
|
536
|
+
props // object
|
537
|
+
};
|
699
538
|
}
|
700
539
|
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
540
|
+
h.retain = _ => h(RETAIN_KEY);
|
541
|
+
|
542
|
+
export const m = h;
|
543
|
+
|
544
|
+
export const Fragment = props => props.children;
|
545
|
+
|
546
|
+
export const onRemove = fn => ON_REMOVES.push(fn);
|
547
|
+
|
548
|
+
export function render(vnode, parentDomNode) {
|
549
|
+
let ref,
|
550
|
+
env = { ...DEFAULT_ENV, manualRedraw: 1 },
|
551
|
+
rootRef = parentDomNode[PARENT_DOM_KEY];
|
552
|
+
if (rootRef === NIL) {
|
553
|
+
ref = mount(vnode, env);
|
554
|
+
parentDomNode[PARENT_DOM_KEY] = { ref, vnode };
|
555
|
+
parentDomNode.textContent = '';
|
556
|
+
insertDom(parentDomNode, ref, NIL);
|
706
557
|
} else {
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
558
|
+
rootRef.ref = patchInPlace(
|
559
|
+
parentDomNode,
|
560
|
+
vnode,
|
561
|
+
rootRef.vnode,
|
562
|
+
rootRef.ref,
|
563
|
+
env
|
564
|
+
);
|
565
|
+
rootRef.vnode = vnode;
|
713
566
|
}
|
714
567
|
}
|
715
568
|
|
716
|
-
function
|
717
|
-
let
|
718
|
-
|
719
|
-
|
720
|
-
id: vnode.id,
|
721
|
-
vtype: VTYPE_COMPONENT,
|
722
|
-
props: vnode.props || {},
|
723
|
-
__tag: {
|
724
|
-
view,
|
725
|
-
removeFromParent: noop,
|
726
|
-
event: noop,
|
727
|
-
mount: render,
|
728
|
-
patch: render,
|
729
|
-
unmount: _ => {
|
730
|
-
onRemove();
|
731
|
-
let childs;
|
732
|
-
if (childs = CHILDS.get(cmp)) {
|
733
|
-
for (let i = 0; i < childs.length; i++) {
|
734
|
-
unmount(childs[i], EMPTY_OBJECT);
|
735
|
-
}
|
736
|
-
|
737
|
-
CHILDS.delete(cmp);
|
738
|
-
}
|
739
|
-
|
740
|
-
cmp.__tag.removeFromParent();
|
741
|
-
}
|
742
|
-
}
|
743
|
-
};
|
744
|
-
|
745
|
-
function render(ctx) {
|
746
|
-
cmp.__tag.event = fn => ev => {
|
747
|
-
fn(ev);
|
748
|
-
MOUNTING.push(cmp);
|
749
|
-
ctx.render(view({ ...ctx.props }));
|
750
|
-
MOUNTING.pop();
|
751
|
-
};
|
569
|
+
export function run(vnode, parentDomNode, opts = {}) {
|
570
|
+
let ref,
|
571
|
+
env = { ...DEFAULT_ENV, ...opts },
|
572
|
+
rootRef = parentDomNode[PARENT_DOM_KEY];
|
752
573
|
|
753
|
-
|
754
|
-
|
755
|
-
MOUNTING.pop();
|
756
|
-
}
|
574
|
+
if (rootRef !== NIL)
|
575
|
+
throw Error('App already mounted on this node');
|
757
576
|
|
758
|
-
|
759
|
-
}
|
577
|
+
ref = mount(vnode, env);
|
578
|
+
rootRef = parentDomNode[PARENT_DOM_KEY] = { ref, vnode };
|
579
|
+
parentDomNode.textContent = '';
|
580
|
+
insertDom(parentDomNode, ref, NIL);
|
581
|
+
|
582
|
+
return env.redraw = _ => {
|
583
|
+
rootRef.ref = patchInPlace(
|
584
|
+
parentDomNode,
|
585
|
+
vnode,
|
586
|
+
rootRef.vnode,
|
587
|
+
rootRef.ref,
|
588
|
+
env
|
589
|
+
);
|
590
|
+
};
|
591
|
+
}
|