mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-17 20:51:20 +02:00
Continue normalize next child when and only when the node exists still (#1538)
* Continue normalize next child when and only when the node exists still * use the refindNode and refindPath provided * Use Array.includes instead of Array.indexOf
This commit is contained in:
committed by
Ian Storm Taylor
parent
28450334a7
commit
b1e5330ad5
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
import { Set } from 'immutable'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes.
|
* Changes.
|
||||||
@@ -68,41 +67,32 @@ function normalizeNodeAndChildren(change, node, schema) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const normalizedKeys = []
|
||||||
|
let child = node.nodes.first()
|
||||||
|
let path = change.value.document.getPath(node.key)
|
||||||
|
|
||||||
// We can't just loop the children and normalize them, because in the process
|
// We can't just loop the children and normalize them, because in the process
|
||||||
// of normalizing one child, we might end up creating another. Instead, we
|
// of normalizing one child, we might end up creating another. Instead, we
|
||||||
// have to normalize one at a time, and check for new children along the way.
|
// have to normalize one at a time, and check for new children along the way.
|
||||||
// PERF: use a mutable array here instead of an immutable stack.
|
while (node && child) {
|
||||||
const keys = node.nodes.toArray().map(n => n.key)
|
const lastSize = change.operations.size
|
||||||
|
normalizeNodeAndChildren(change, child, schema)
|
||||||
|
normalizedKeys.push(child.key)
|
||||||
|
|
||||||
// While there is still a child key that hasn't been normalized yet...
|
// PERF: if size is unchanged, then no operation happens
|
||||||
while (keys.length) {
|
// Therefore we can simply normalize the next child
|
||||||
const { size } = change.operations
|
if (lastSize === change.operations.size) {
|
||||||
let key
|
const nextIndex = node.nodes.indexOf(child) + 1
|
||||||
|
child = node.nodes.get(nextIndex)
|
||||||
// PERF: use a mutable set here since we'll be add to it a lot.
|
} else {
|
||||||
let set = new Set().asMutable()
|
node = change.value.document.refindNode(path, node.key)
|
||||||
|
if (!node) {
|
||||||
// Unwind the stack, normalizing every child and adding it to the set.
|
path = []
|
||||||
while (key = keys[0]) {
|
child = null
|
||||||
const child = node.getChild(key)
|
} else {
|
||||||
normalizeNodeAndChildren(change, child, schema)
|
path = change.value.document.refindPath(path, node.key)
|
||||||
set.add(key)
|
child = node.nodes.find(c => !normalizedKeys.includes(c.key))
|
||||||
keys.shift()
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Turn the set immutable to be able to compare against it.
|
|
||||||
set = set.asImmutable()
|
|
||||||
|
|
||||||
// PERF: Only re-find the node and re-normalize any new children if
|
|
||||||
// operations occured that might have changed it.
|
|
||||||
if (change.operations.size > size) {
|
|
||||||
node = refindNode(change, node)
|
|
||||||
|
|
||||||
// Add any new children back onto the stack.
|
|
||||||
node.nodes.forEach((n) => {
|
|
||||||
if (set.has(n.key)) return
|
|
||||||
keys.unshift(n.key)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,23 +102,6 @@ function normalizeNodeAndChildren(change, node, schema) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-find a reference to a node that may have been modified or removed
|
|
||||||
* entirely by a change.
|
|
||||||
*
|
|
||||||
* @param {Change} change
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Node}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function refindNode(change, node) {
|
|
||||||
const { value } = change
|
|
||||||
const { document } = value
|
|
||||||
return node.object == 'document'
|
|
||||||
? document
|
|
||||||
: document.getDescendant(node.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a `node` with a `schema`, but not its children.
|
* Normalize a `node` with a `schema`, but not its children.
|
||||||
*
|
*
|
||||||
@@ -146,13 +119,16 @@ function normalizeNode(change, node, schema) {
|
|||||||
if (!normalize) return
|
if (!normalize) return
|
||||||
|
|
||||||
// Run the `normalize` function to fix the node.
|
// Run the `normalize` function to fix the node.
|
||||||
|
let path = c.value.document.getPath(n.key)
|
||||||
normalize(c)
|
normalize(c)
|
||||||
|
|
||||||
// Re-find the node reference, in case it was updated. If the node no longer
|
// Re-find the node reference, in case it was updated. If the node no longer
|
||||||
// exists, we're done for this branch.
|
// exists, we're done for this branch.
|
||||||
n = refindNode(c, n)
|
n = c.value.document.refindNode(path, n.key)
|
||||||
if (!n) return
|
if (!n) return
|
||||||
|
|
||||||
|
path = c.value.document.refindPath(path, n.key)
|
||||||
|
|
||||||
// Increment the iterations counter, and check to make sure that we haven't
|
// Increment the iterations counter, and check to make sure that we haven't
|
||||||
// exceeded the max. Without this check, it's easy for the `validate` or
|
// exceeded the max. Without this check, it's easy for the `validate` or
|
||||||
// `normalize` function of a schema rule to be written incorrectly and for
|
// `normalize` function of a schema rule to be written incorrectly and for
|
||||||
|
Reference in New Issue
Block a user