mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-30 10:29:48 +02:00
Perhaps faster normalization: Never visit a descendant twice in normalizaton (#1661)
* Perhaps faster normalization: Never visit a descendant twice in normalizaton * Change getFirstInvalidaDescendantKey to getFirstInvalidaDescendant * Add from-JSON-big in benchmark * Better annotation * Remove un-used test change
This commit is contained in:
committed by
Ian Storm Taylor
parent
6ad3aada5b
commit
c569569729
66
packages/slate/benchmark/models/from-json-big.js
Normal file
66
packages/slate/benchmark/models/from-json-big.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/* eslint-disable react/jsx-key */
|
||||
|
||||
import { Value } from '../..'
|
||||
|
||||
export default function(json) {
|
||||
Value.fromJSON(json)
|
||||
}
|
||||
|
||||
export const input = {
|
||||
document: {
|
||||
nodes: Array.from(Array(100)).map(() => ({
|
||||
type: 'list',
|
||||
object: 'block',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: Array.from(Array(10)).map(() => ({
|
||||
type: 'list-item',
|
||||
object: 'block',
|
||||
isVoid: false,
|
||||
data: {},
|
||||
nodes: [
|
||||
{
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
marks: [],
|
||||
text: '',
|
||||
},
|
||||
],
|
||||
object: 'text',
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
object: 'inline',
|
||||
isVoid: false,
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
marks: [],
|
||||
text: 'Some text for a link',
|
||||
},
|
||||
],
|
||||
object: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
leaves: [
|
||||
{
|
||||
object: 'leaf',
|
||||
marks: [],
|
||||
text: '',
|
||||
},
|
||||
],
|
||||
object: 'text',
|
||||
},
|
||||
],
|
||||
})),
|
||||
})),
|
||||
},
|
||||
}
|
@@ -65,32 +65,17 @@ function normalizeNodeAndChildren(change, node, schema) {
|
||||
return
|
||||
}
|
||||
|
||||
const normalizedKeys = []
|
||||
let child = node.nodes.first()
|
||||
let child = node.getFirstInvalidDescendant(schema)
|
||||
let path = change.value.document.getPath(node.key)
|
||||
|
||||
// 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
|
||||
// have to normalize one at a time, and check for new children along the way.
|
||||
while (node && child) {
|
||||
const lastSize = change.operations.size
|
||||
normalizeNodeAndChildren(change, child, schema)
|
||||
normalizedKeys.push(child.key)
|
||||
|
||||
// PERF: if size is unchanged, then no operation happens
|
||||
// Therefore we can simply normalize the next child
|
||||
if (lastSize === change.operations.size) {
|
||||
const nextIndex = node.nodes.indexOf(child) + 1
|
||||
child = node.nodes.get(nextIndex)
|
||||
node = change.value.document.refindNode(path, node.key)
|
||||
if (!node) {
|
||||
path = []
|
||||
child = null
|
||||
} else {
|
||||
node = change.value.document.refindNode(path, node.key)
|
||||
if (!node) {
|
||||
path = []
|
||||
child = null
|
||||
} else {
|
||||
path = change.value.document.refindPath(path, node.key)
|
||||
child = node.nodes.find(c => !normalizedKeys.includes(c.key))
|
||||
}
|
||||
path = change.value.document.refindPath(path, node.key)
|
||||
child = node.getFirstInvalidDescendant(schema)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1987,6 +1987,22 @@ class Node {
|
||||
validate(schema) {
|
||||
return schema.validateNode(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first invalid descendant
|
||||
*
|
||||
* @param {Schema} schema
|
||||
* @return {Node|Text|Null}
|
||||
*/
|
||||
|
||||
getFirstInvalidDescendant(schema) {
|
||||
let result = null
|
||||
this.nodes.find(n => {
|
||||
result = n.validate(schema) ? n : n.getFirstInvalidDescendant(schema)
|
||||
return result
|
||||
})
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2072,6 +2088,7 @@ memoize(
|
||||
'getTextAtOffset',
|
||||
'getTextsAtRangeAsArray',
|
||||
'validate',
|
||||
'getFirstInvalidDescendant',
|
||||
],
|
||||
{
|
||||
takesArguments: true,
|
||||
|
@@ -495,6 +495,18 @@ class Text extends Record(DEFAULTS) {
|
||||
validate(schema) {
|
||||
return schema.validateNode(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first invalid descendant
|
||||
* PREF: Do not cache this method; because it can cause cycle reference
|
||||
*
|
||||
* @param {Schema} schema
|
||||
* @returns {Text|Null}
|
||||
*/
|
||||
|
||||
getFirstInvalidDescendant(schema) {
|
||||
return this.validate(schema) ? this : null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user