diff --git a/src/models/node.js b/src/models/node.js index 7a7bf00a1..56af09654 100644 --- a/src/models/node.js +++ b/src/models/node.js @@ -524,14 +524,13 @@ const Node = { */ getFurthest(key, iterator) { - let node = this.assertDescendant(key) - let furthest = null - - while (node = this.getClosest(node, iterator)) { - furthest = node + let ancestors = this.getAncestors(key) + if (!ancestors) { + throw new Error(`Could not find a descendant node with key "${key}".`) } - return furthest + // Exclude this node itself + return ancestors.rest().find(iterator) }, /** @@ -1291,19 +1290,7 @@ const Node = { } else { return result } - }, - - /** - * Validate the node against a `schema`. - * - * @param {Schema} schema - * @return {Object || Void} - */ - - validate(schema) { - return schema.__validate(this) } - } /** @@ -1313,10 +1300,6 @@ const Node = { memoize(Node, [ 'assertChild', 'assertDescendant', - 'filterDescendants', - 'filterDescendantsDeep', - 'findDescendant', - 'findDescendantDeep', 'getAncestors', 'getBlocks', 'getBlocksAtRange', @@ -1328,17 +1311,16 @@ memoize(Node, [ 'getChildrenBeforeIncluding', 'getChildrenBetween', 'getChildrenBetweenIncluding', - 'getClosest', 'getClosestBlock', 'getClosestInline', 'getComponent', 'getDecorators', 'getDepth', 'getDescendant', + 'getDescendantAtPath', 'getDescendantDecorators', 'getFirstText', 'getFragmentAtRange', - 'getFurthest', 'getFurthestBlock', 'getFurthestInline', 'getHighestChild', @@ -1362,8 +1344,7 @@ memoize(Node, [ 'hasChild', 'hasDescendant', 'hasVoidParent', - 'isInlineSplitAtRange', - 'validate' + 'isInlineSplitAtRange' ]) /** diff --git a/src/models/text.js b/src/models/text.js index dd3bca369..343e24a9a 100644 --- a/src/models/text.js +++ b/src/models/text.js @@ -328,18 +328,6 @@ class Text extends new Record(DEFAULTS) { return this.merge({ characters }) } - - /** - * Validate the node against a `schema`. - * - * @param {Schema} schema - * @return {Object || Void} - */ - - validate(schema) { - return schema.__validate(this) - } - } /** @@ -349,8 +337,7 @@ class Text extends new Record(DEFAULTS) { memoize(Text.prototype, [ 'getDecorations', 'getDecorators', - 'getRanges', - 'validate', + 'getRanges' ]) /** diff --git a/src/transforms/normalize.js b/src/transforms/normalize.js index a9b6f633c..8e6e786fc 100644 --- a/src/transforms/normalize.js +++ b/src/transforms/normalize.js @@ -105,11 +105,19 @@ export function normalizeNodeWith(transform, schema, node, prevNode) { return transform } + // For performance considerations, we will check if the transform was changed + const opCount = transform.operations.length + // Iterate over its children transform = _normalizeChildrenWith(transform, schema, node, prevNode) - // Refresh the node reference, and normalize it - node = _refreshNode(transform, node) + const hasChanged = transform.operations.length != opCount + if (hasChanged) { + // Refresh the node reference + node = _refreshNode(transform, node) + } + + // Now normalize the node itself if it still exist if (node) { transform = _normalizeNodeWith(transform, schema, node) } @@ -160,8 +168,8 @@ export function normalizeWith(transform, schema, prevDocument) { const { state } = transform const { document } = state - // Schema was not rule to edit the document if (!schema.isNormalization) { + // Schema has no normalization rules return transform } diff --git a/src/utils/memoize.js b/src/utils/memoize.js index 059cc4e0f..47f1f63bd 100644 --- a/src/utils/memoize.js +++ b/src/utils/memoize.js @@ -11,6 +11,13 @@ import { Map } from 'immutable' const LEAF = {} +/** + * An unique value used to detect cache misses + * + * @type {Object} + */ +const NO_SET = {} + /** * Memoize all of the `properties` on a `object`. * @@ -31,7 +38,10 @@ function memoize(object, properties) { const keys = [property, ...args, LEAF] const cache = this.__cache = this.__cache || new Map() - if (cache.hasIn(keys)) return cache.getIn(keys) + const cachedValue = cache.getIn(keys, NO_SET) + if (cachedValue !== NO_SET) { + return cachedValue + } const value = original.apply(this, args) this.__cache = cache.setIn(keys, value)