Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
c636c2f
Enable ES2015 lint and minifier code gen support
dead-claudia Sep 26, 2024
3e97cc9
Optimize generated IIFE slightly
dead-claudia Sep 26, 2024
f07feb9
Add keyed perf tests, assert no duplicates in keyed fragments
dead-claudia Sep 26, 2024
f291d28
Add duplicate key check, deduplicate code, use ES6
dead-claudia Sep 26, 2024
0106367
Normalize xlink, simplify attrs update a bit
dead-claudia Sep 26, 2024
c3e90f5
Drop `m.trust` support
dead-claudia Sep 26, 2024
ca65f7a
Drop object component support
dead-claudia Sep 27, 2024
e9fad45
`key` attr -> `m.key(...)`, drop `domSize`, remove redundancy
dead-claudia Oct 2, 2024
2707de3
Use the `.state` property for keys
dead-claudia Oct 2, 2024
ae28e2a
Move the DOM event listener to `vnode.instance`
dead-claudia Oct 2, 2024
7aca843
Move state object creation to hyperscript
dead-claudia Oct 2, 2024
b724902
Move `m.render` out of initialization closure
dead-claudia Oct 2, 2024
3ade35c
Drop `m.request`
dead-claudia Oct 3, 2024
a452105
Migrate `m.buildPathname` to `m.p` and remove the path params argumen…
dead-claudia Oct 3, 2024
8c619c3
Add a `m.withProgress` to replace `onprogress` with `fetch`.
dead-claudia Oct 3, 2024
1b0818e
Have `m.mount` mount a view function rather than a full component
dead-claudia Oct 3, 2024
6caacf2
Drop a couple forgotten tests
dead-claudia Oct 3, 2024
57edf21
Add lazy loader
dead-claudia Oct 3, 2024
6b3c7b3
Toss the "route" part of the router
dead-claudia Oct 3, 2024
ccea9a1
Merge `Vnode` with the hyperscript module
dead-claudia Oct 3, 2024
dae2208
Rename and move lone remaining `pathname` submodule to make more sense
dead-claudia Oct 3, 2024
3668dc7
Drop remaining reference to `assign`
dead-claudia Oct 3, 2024
03fd640
Merge query string building into `m.p`, drop unused query string parser
dead-claudia Oct 3, 2024
eb0031c
Normalize the callback style in `test-p.js`.
dead-claudia Oct 3, 2024
b04519d
Make the event dictionary a proper class
dead-claudia Oct 3, 2024
8fbc46a
Finish ES6ifying hyperscript factories
dead-claudia Oct 3, 2024
1418bd3
Drop stale recycling tests
dead-claudia Oct 3, 2024
13c2e63
Add `m.tracked` utility for tracking delayed removals
dead-claudia Oct 3, 2024
cd20a00
Make `m.lazy` not a higher-order factory - it doesn't need to be one
dead-claudia Oct 3, 2024
454f8e7
Drop `onbeforeremove`
dead-claudia Oct 3, 2024
60de2e1
`onbeforeremove` -> `m.retain()`
dead-claudia Oct 4, 2024
1efdb78
Re-duplicate children
dead-claudia Oct 4, 2024
537f828
Drop `handleEvent` method support, wait for promises in event listeners
dead-claudia Oct 4, 2024
9070429
Revise a comment
dead-claudia Oct 4, 2024
5c2bf31
Drop `oninit`, replace all remaining lifecycle methods with `m.layout`
dead-claudia Oct 4, 2024
2942ea5
Drop old vnode state stuff except for components
dead-claudia Oct 4, 2024
168b403
Add `m.init` and `m.use` convenience utilities, simplify fragments, f…
dead-claudia Oct 4, 2024
b168f74
Migrate components to simple functions and closures
dead-claudia Oct 4, 2024
d652f98
Drop `m.fragment`, try to create attrs object less in hyperscript fac…
dead-claudia Oct 4, 2024
bd09d8a
Stop propagating hooks, correct the circular rendering check
dead-claudia Oct 4, 2024
933d4b5
Improve perf tests
dead-claudia Oct 5, 2024
d7d8bef
Simplify the keyed diff fuzzer
dead-claudia Oct 5, 2024
67a30f4
Simplify the renderer, strip outdated and redundant tests, reject reu…
dead-claudia Oct 5, 2024
84b0950
Split code + tests, move source into dedicated directory
dead-claudia Oct 5, 2024
49ec364
Redo build and pack system, simplify a few remaining bits
dead-claudia Oct 5, 2024
55a8071
Knock out all the intermediate closures, do a better job cleaning up,…
dead-claudia Oct 6, 2024
c0821cb
Try to get a better profile view
dead-claudia Oct 6, 2024
210d997
Improve bundle size, move to type masks to boost performance
dead-claudia Oct 11, 2024
044d1b8
Switch from `m.layout` signal out `m.remove`, merge create/update cal…
dead-claudia Oct 11, 2024
8ddc288
Add context, migrate router to use it
dead-claudia Oct 11, 2024
21085ce
Rearrange tests to mirror source
dead-claudia Oct 11, 2024
beaad3b
Optimize stream, remove deprecated bit, simplify `combine`
dead-claudia Oct 11, 2024
84472c4
Move `redraw` to an options bag
dead-claudia Oct 11, 2024
70cc05b
Move router functions to arrow functions to save a little space
dead-claudia Oct 11, 2024
1cf9de3
`undefined` -> `null` to save a few bytes
dead-claudia Oct 12, 2024
455765a
Add bi-edge debouncing + throttling rate limiters
dead-claudia Oct 12, 2024
118d748
Stub out error handling
dead-claudia Oct 12, 2024
4137f97
Fix stray outdated benchmark reference
dead-claudia Oct 12, 2024
313d004
Add ops per sec counter
dead-claudia Oct 12, 2024
726e79f
Optimize error handling
dead-claudia Oct 12, 2024
2a60973
Ensure `is` is always set in custom elements
dead-claudia Oct 12, 2024
f48beca
Normalize the render vnode input to a single unitary vnode, not an array
dead-claudia Oct 12, 2024
b889448
Clean up the router on remove, remove unneeded hashchange event
dead-claudia Oct 12, 2024
3b7788b
Remove the no-longer-necessary options parameter to `{add,remove}Even…
dead-claudia Oct 12, 2024
95897a3
Diff final URL before redrawing, to prevent unnecessary redraws
dead-claudia Oct 12, 2024
966d1c0
Allow building query strings independently of paths (again)
dead-claudia Oct 12, 2024
30e5ed1
Restore current size
dead-claudia Oct 12, 2024
86b3c31
Update the copy a bit, drop official IE support
dead-claudia Oct 12, 2024
2872ca2
Stop displaying size in the README
dead-claudia Oct 12, 2024
9099bcc
Forgot to port the actual key assignment over in the benchmark
dead-claudia Oct 12, 2024
1fb5104
Unrestrict a bunch of actually valid syntax
dead-claudia Oct 20, 2024
c5c4b2f
Add `m.match`, optimize `m.p` a ton
dead-claudia Oct 20, 2024
fa39b98
Remove some useless `Object.assign`s
dead-claudia Oct 20, 2024
310a32b
Remove unnecessary `finally` block
dead-claudia Oct 20, 2024
b33349a
Improve post-perf UI a little
dead-claudia Oct 20, 2024
3da7a1d
Pre-render tree in benchmark so it's only checking update in `render …
dead-claudia Oct 20, 2024
01fc41e
ES6ify an event handler (and fix its name)
dead-claudia Oct 20, 2024
9dd8d17
Improve benchmark more
dead-claudia Oct 21, 2024
fee0cca
Boost `m.p` performance by a lot
dead-claudia Oct 21, 2024
451aa18
Tolerate absence of `/dist`
dead-claudia Oct 21, 2024
36d4cb3
Resolve remaining issues with benchmarks, explain with a lengthy just…
dead-claudia Oct 29, 2024
2e75897
Address some feedback around naming and (indirectly) `m.key`, optimiz…
dead-claudia Oct 30, 2024
5018ad0
Move context to `this` argument
dead-claudia Oct 30, 2024
5d79b07
Make routed links more concise, stop throwing when retaining nothing,…
dead-claudia Oct 30, 2024
f99850e
Further simplify routing
dead-claudia Oct 30, 2024
0c99734
Use `queueMicrotask` to avoid some awkward `await 0`s.
dead-claudia Oct 30, 2024
814261f
Add more type checks, unify auto-redraw logic, optimize element creat…
dead-claudia Oct 30, 2024
cd26097
Revise an outdated comment, cheat a little bit on redraw context
dead-claudia Oct 30, 2024
8cafcfe
Fix a type comment, make things use a shared noop where helpful
dead-claudia Oct 30, 2024
953665e
Add a single-value tracker, optimize tracked handle.
dead-claudia Oct 31, 2024
3220a25
Bring back `m.request` - it's too useful.
dead-claudia Oct 31, 2024
76389d4
Avoid splicing samples
dead-claudia Nov 4, 2024
17e89ea
Add Node.js types for a better autocomplete experience in scripts
dead-claudia Nov 4, 2024
584069f
Optimize the style property update flow and reduce its overhead
dead-claudia Nov 6, 2024
7c5d9b7
Revise some test names
dead-claudia Nov 7, 2024
77e7ea7
Update core.js
dead-claudia Mar 26, 2025
8bfbe6b
Update core.js
dead-claudia Mar 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Drop onbeforeremove
It's now been made redundant with `m.tracked`.
  • Loading branch information
dead-claudia committed Oct 3, 2024
commit 454f8e7d087fc0b86eefd9af8aca3c480438ce36
217 changes: 52 additions & 165 deletions render/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ var nameSpace = {
math: "http://www.w3.org/1998/Math/MathML"
}

// The vnode path is needed for proper removal unblocking. It's not retained past a given
// render and is overwritten on every vnode visit, so callers wanting to retain it should
// always clone the part they're interested in.
var vnodePath
var blockedRemovalRefCount = /*@__PURE__*/new WeakMap()
var removalRequested = /*@__PURE__*/new WeakSet()
var currentRedraw

function getDocument(dom) {
Expand Down Expand Up @@ -231,18 +225,18 @@ function createComponent(parent, vnode, hooks, ns, nextSibling) {
// the old DOM nodes before updateNode runs because it enables us to use the cached `nextSibling`
// variable rather than fetching it using `getNextSibling()`.

function updateNodes(parent, old, vnodes, hooks, nextSibling, ns, pathDepth) {
function updateNodes(parent, old, vnodes, hooks, nextSibling, ns) {
if (old === vnodes || old == null && vnodes == null) return
else if (old == null || old.length === 0) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns)
else if (vnodes == null || vnodes.length === 0) removeNodes(parent, old, 0, old.length, pathDepth, false)
else if (vnodes == null || vnodes.length === 0) removeNodes(parent, old, 0, old.length)
else {
var isOldKeyed = old[0] != null && old[0].tag === "="
var isKeyed = vnodes[0] != null && vnodes[0].tag === "="
var start = 0, oldStart = 0
if (!isOldKeyed) while (oldStart < old.length && old[oldStart] == null) oldStart++
if (!isKeyed) while (start < vnodes.length && vnodes[start] == null) start++
if (isOldKeyed !== isKeyed) {
removeNodes(parent, old, oldStart, old.length, pathDepth, false)
removeNodes(parent, old, oldStart, old.length)
createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns)
} else if (!isKeyed) {
// Don't index past the end of either list (causes deopts).
Expand All @@ -256,10 +250,10 @@ function updateNodes(parent, old, vnodes, hooks, nextSibling, ns, pathDepth) {
v = vnodes[start]
if (o === v || o == null && v == null) continue
else if (o == null) createNode(parent, v, hooks, ns, getNextSibling(old, start + 1, nextSibling))
else if (v == null) removeNode(parent, o, pathDepth, false)
else updateNode(parent, o, v, hooks, getNextSibling(old, start + 1, nextSibling), ns, pathDepth)
else if (v == null) removeNode(parent, o)
else updateNode(parent, o, v, hooks, getNextSibling(old, start + 1, nextSibling), ns)
}
if (old.length > commonLength) removeNodes(parent, old, start, old.length, pathDepth, false)
if (old.length > commonLength) removeNodes(parent, old, start, old.length)
if (vnodes.length > commonLength) createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns)
} else {
// keyed diff
Expand All @@ -270,7 +264,7 @@ function updateNodes(parent, old, vnodes, hooks, nextSibling, ns, pathDepth) {
oe = old[oldEnd]
ve = vnodes[end]
if (oe.state !== ve.state) break
if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns, pathDepth)
if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns)
if (ve.dom != null) nextSibling = ve.dom
oldEnd--, end--
}
Expand All @@ -280,17 +274,17 @@ function updateNodes(parent, old, vnodes, hooks, nextSibling, ns, pathDepth) {
v = vnodes[start]
if (o.state !== v.state) break
oldStart++, start++
if (o !== v) updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), ns, pathDepth)
if (o !== v) updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), ns)
}
// swaps and list reversals
while (oldEnd >= oldStart && end >= start) {
if (start === end) break
if (o.state !== ve.state || oe.state !== v.state) break
topSibling = getNextSibling(old, oldStart, nextSibling)
moveDOM(parent, oe, topSibling)
if (oe !== v) updateNode(parent, oe, v, hooks, topSibling, ns, pathDepth)
if (oe !== v) updateNode(parent, oe, v, hooks, topSibling, ns)
if (++start <= --end) moveDOM(parent, o, nextSibling)
if (o !== ve) updateNode(parent, o, ve, hooks, nextSibling, ns, pathDepth)
if (o !== ve) updateNode(parent, o, ve, hooks, nextSibling, ns)
if (ve.dom != null) nextSibling = ve.dom
oldStart++; oldEnd--
oe = old[oldEnd]
Expand All @@ -301,13 +295,13 @@ function updateNodes(parent, old, vnodes, hooks, nextSibling, ns, pathDepth) {
// bottom up once again
while (oldEnd >= oldStart && end >= start) {
if (oe.state !== ve.state) break
if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns, pathDepth)
if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns)
if (ve.dom != null) nextSibling = ve.dom
oldEnd--, end--
oe = old[oldEnd]
ve = vnodes[end]
}
if (start > end) removeNodes(parent, old, oldStart, oldEnd + 1, pathDepth, false)
if (start > end) removeNodes(parent, old, oldStart, oldEnd + 1)
else if (oldStart > oldEnd) createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns)
else {
// inspired by ivi https://github.com/ivijs/ivi/ by Boris Kaul
Expand All @@ -322,13 +316,13 @@ function updateNodes(parent, old, vnodes, hooks, nextSibling, ns, pathDepth) {
oldIndices[i-start] = oldIndex
oe = old[oldIndex]
old[oldIndex] = null
if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns, pathDepth)
if (oe !== ve) updateNode(parent, oe, ve, hooks, nextSibling, ns)
if (ve.dom != null) nextSibling = ve.dom
matched++
}
}
nextSibling = originalNextSibling
if (matched !== oldEnd - oldStart + 1) removeNodes(parent, old, oldStart, oldEnd + 1, pathDepth, false)
if (matched !== oldEnd - oldStart + 1) removeNodes(parent, old, oldStart, oldEnd + 1)
if (matched === 0) createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns)
else {
if (pos === -1) {
Expand Down Expand Up @@ -357,29 +351,27 @@ function updateNodes(parent, old, vnodes, hooks, nextSibling, ns, pathDepth) {
}
}
}
function updateNode(parent, old, vnode, hooks, nextSibling, ns, pathDepth) {
function updateNode(parent, old, vnode, hooks, nextSibling, ns) {
var oldTag = old.tag, tag = vnode.tag
if (oldTag === tag) {
vnode.state = old.state
vnode.instance = old.instance
if (shouldNotUpdate(vnode, old)) return
vnodePath[pathDepth++] = parent
vnodePath[pathDepth++] = vnode
if (typeof oldTag === "string") {
if (vnode.attrs != null) {
updateLifecycle(vnode.attrs, vnode, hooks)
}
switch (oldTag) {
case "#": updateText(old, vnode); break
case "=":
case "[": updateFragment(parent, old, vnode, hooks, nextSibling, ns, pathDepth); break
default: updateElement(old, vnode, hooks, ns, pathDepth)
case "[": updateFragment(parent, old, vnode, hooks, nextSibling, ns); break
default: updateElement(old, vnode, hooks, ns)
}
}
else updateComponent(parent, old, vnode, hooks, nextSibling, ns, pathDepth)
else updateComponent(parent, old, vnode, hooks, nextSibling, ns)
}
else {
removeNode(parent, old, pathDepth, false)
removeNode(parent, old)
createNode(parent, vnode, hooks, ns, nextSibling)
}
}
Expand All @@ -389,8 +381,8 @@ function updateText(old, vnode) {
}
vnode.dom = old.dom
}
function updateFragment(parent, old, vnode, hooks, nextSibling, ns, pathDepth) {
updateNodes(parent, old.children, vnode.children, hooks, nextSibling, ns, pathDepth)
function updateFragment(parent, old, vnode, hooks, nextSibling, ns) {
updateNodes(parent, old.children, vnode.children, hooks, nextSibling, ns)
vnode.dom = null
if (vnode.children != null) {
for (var child of vnode.children) {
Expand All @@ -400,27 +392,27 @@ function updateFragment(parent, old, vnode, hooks, nextSibling, ns, pathDepth) {
}
}
}
function updateElement(old, vnode, hooks, ns, pathDepth) {
function updateElement(old, vnode, hooks, ns) {
var element = vnode.dom = old.dom
ns = getNameSpace(vnode) || ns

updateAttrs(vnode, old.attrs, vnode.attrs, ns)
if (!maybeSetContentEditable(vnode)) {
updateNodes(element, old.children, vnode.children, hooks, null, ns, pathDepth)
updateNodes(element, old.children, vnode.children, hooks, null, ns)
}
}
function updateComponent(parent, old, vnode, hooks, nextSibling, ns, pathDepth) {
function updateComponent(parent, old, vnode, hooks, nextSibling, ns) {
vnode.instance = hyperscript.normalize(callHook.call(vnode.state.view, vnode))
if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument")
updateLifecycle(vnode.state, vnode, hooks)
if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks)
if (vnode.instance != null) {
if (old.instance == null) createNode(parent, vnode.instance, hooks, ns, nextSibling)
else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, ns, pathDepth)
else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, ns)
vnode.dom = vnode.instance.dom
}
else if (old.instance != null) {
removeNode(parent, old.instance, pathDepth, false)
removeNode(parent, old.instance, false)
vnode.dom = undefined
}
else {
Expand Down Expand Up @@ -491,7 +483,7 @@ function getNextSibling(vnodes, i, nextSibling) {
return nextSibling
}

// This handles fragments with zombie children (removed from vdom, but persisted in DOM through onbeforeremove)
// This moves only the nodes tracked by Mithril
function moveDOM(parent, vnode, nextSibling) {
if (typeof vnode.tag === "function") {
return moveDOM(parent, vnode.instance, nextSibling)
Expand Down Expand Up @@ -524,142 +516,40 @@ function maybeSetContentEditable(vnode) {
}

//remove
function invokeBeforeRemove(vnode, host) {
try {
if (typeof host.onbeforeremove === "function") {
var result = callHook.call(host.onbeforeremove, vnode)
if (result != null && typeof result.then === "function") return Promise.resolve(result)
}
} catch (e) {
// Errors during removal aren't fatal. Just log them.
console.error(e)
}
function removeNodes(parent, vnodes, start, end) {
for (var i = start; i < end; i++) removeNode(parent, vnodes[i])
}
function tryProcessRemoval(parent, vnode) {
// eslint-disable-next-line no-bitwise
var refCount = blockedRemovalRefCount.get(vnode) | 0
if (refCount > 1) {
blockedRemovalRefCount.set(vnode, refCount - 1)
return false
}

if (typeof vnode.tag !== "function" && vnode.tag !== "[" && vnode.tag !== "=") {
parent.removeChild(vnode.dom)
}

try {
if (typeof vnode.tag !== "string" && typeof vnode.state.onremove === "function") {
callHook.call(vnode.state.onremove, vnode)
}
} catch (e) {
console.error(e)
}

try {
if (vnode.attrs && typeof vnode.attrs.onremove === "function") {
callHook.call(vnode.attrs.onremove, vnode)
function removeNode(parent, vnode) {
if (vnode != null) {
if (typeof vnode.tag === "function") {
if (vnode.instance != null) removeNode(parent, vnode.instance)
} else if (vnode.tag !== "#") {
removeNodes(
vnode.tag !== "[" && vnode.tag !== "=" ? vnode.dom : parent,
vnode.children, 0, vnode.children.length
)
}
} catch (e) {
console.error(e)
}

return true
}
function removeNodeAsyncRecurse(parent, vnode) {
while (vnode != null) {
// Delay the actual subtree removal if there's still pending `onbeforeremove` hooks on
// this node or a child node.
if (!tryProcessRemoval(parent, vnode)) return false
if (typeof vnode.tag !== "function") {
if (vnode.tag === "#") break
if (vnode.tag !== "[" && vnode.tag !== "=") parent = vnode.dom
// Using bitwise ops and `Array.prototype.reduce` to reduce code size. It's not
// called nearly enough to merit further optimization.
// eslint-disable-next-line no-bitwise
return vnode.children.reduce((fail, child) => fail & removeNodeAsyncRecurse(parent, child), 1)
if (typeof vnode.tag !== "function" && vnode.tag !== "[" && vnode.tag !== "=") {
parent.removeChild(vnode.dom)
}
vnode = vnode.instance
}

return true
}
function removeNodes(parent, vnodes, start, end, pathDepth, isDelayed) {
// Using bitwise ops to reduce code size.
var fail = 0
// eslint-disable-next-line no-bitwise
for (var i = start; i < end; i++) fail |= !removeNode(parent, vnodes[i], pathDepth, isDelayed)
return !fail
}
function removeNode(parent, vnode, pathDepth, isDelayed) {
if (vnode != null) {
delayed: {
var attrsResult, stateResult

// Block removes, but do call nested `onbeforeremove`.
if (typeof vnode.tag !== "string") attrsResult = invokeBeforeRemove(vnode, vnode.state)
if (vnode.attrs != null) stateResult = invokeBeforeRemove(vnode, vnode.attrs)

vnodePath[pathDepth++] = parent
vnodePath[pathDepth++] = vnode

if (attrsResult || stateResult) {
var path = vnodePath.slice(0, pathDepth)
var settle = () => {

// Remove the innermost node recursively and try to remove the parents
// non-recursively.
// If it's still delayed, skip. If this node is delayed, all its ancestors are
// also necessarily delayed, and so they should be skipped.
var i = path.length - 2
if (removeNodeAsyncRecurse(path[i], path[i + 1])) {
while ((i -= 2) >= 0 && removalRequested.has(path[i + 1])) {
tryProcessRemoval(path[i], path[i + 1])
}
}
}
var increment = 0

if (attrsResult) {
attrsResult.catch(console.error)
attrsResult.then(settle, settle)
increment++
}

if (stateResult) {
stateResult.catch(console.error)
stateResult.then(settle, settle)
increment++
}

isDelayed = true

for (var i = 1; i < pathDepth; i += 2) {
// eslint-disable-next-line no-bitwise
blockedRemovalRefCount.set(vnodePath[i], (blockedRemovalRefCount.get(vnodePath[i]) | 0) + increment)
}
try {
if (typeof vnode.tag !== "string" && typeof vnode.state.onremove === "function") {
callHook.call(vnode.state.onremove, vnode)
}
} catch (e) {
console.error(e)
}

if (typeof vnode.tag === "function") {
if (vnode.instance != null && !removeNode(parent, vnode.instance, pathDepth, isDelayed)) break delayed
} else if (vnode.tag !== "#") {
if (!removeNodes(
vnode.tag !== "[" && vnode.tag !== "=" ? vnode.dom : parent,
vnode.children, 0, vnode.children.length, pathDepth, isDelayed
)) break delayed
try {
if (vnode.attrs && typeof vnode.attrs.onremove === "function") {
callHook.call(vnode.attrs.onremove, vnode)
}

// Don't call removal hooks if removal is delayed.
// Delay the actual subtree removal if there's still pending `onbeforeremove` hooks on
// this node or a child node.
if (isDelayed || tryProcessRemoval(parent, vnode)) break delayed

return false
} catch (e) {
console.error(e)
}

removalRequested.add(vnode)
}

return true
}

//attrs
Expand Down Expand Up @@ -763,7 +653,7 @@ function updateAttrs(vnode, old, attrs, ns) {
}
}
var isAlwaysFormAttribute = new Set(["value", "checked", "selected", "selectedIndex"])
var isSpecialAttribute = new Set(["key", "is", "oninit", "oncreate", "onupdate", "onremove", "onbeforeupdate", "onbeforeremove"])
var isSpecialAttribute = new Set(["key", "is", "oninit", "oncreate", "onupdate", "onremove", "onbeforeupdate"])
// Try to avoid a few browser bugs on normal elements.
// var propertyMayBeBugged = new Set(["href", "list", "form", "width", "height", "type"])
var propertyMayBeBugged = new Set(["href", "list", "form", "width", "height"])
Expand Down Expand Up @@ -919,11 +809,9 @@ module.exports = function(dom, vnodes, redraw) {
var hooks = []
var active = activeElement(dom)
var namespace = dom.namespaceURI
var prevPath = vnodePath

currentDOM = dom
currentRedraw = typeof redraw === "function" ? redraw : undefined
vnodePath = []
try {
// First time rendering into a node clears it out
if (dom.vnodes == null) dom.textContent = ""
Expand All @@ -936,6 +824,5 @@ module.exports = function(dom, vnodes, redraw) {
} finally {
currentRedraw = prevRedraw
currentDOM = prevDOM
vnodePath = prevPath
}
}
Loading