From e0d993617d99b6efa465d23312dbdb6e1e462a5e Mon Sep 17 00:00:00 2001 From: jacobbloomCDD Date: Tue, 8 Aug 2017 11:13:11 -0700 Subject: [PATCH] Speed up getting blocks at a range Old implementation was far too slow if a selection included many nodes. The performance hit occurred when converting each and every text node into a block. This is now avoided by using the same logic as getTextsAtRangeAsArray for getBlocksAtRangeAsArray, but using blocks directly. --- src/models/node.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/models/node.js b/src/models/node.js index b93efac1c..d9a515f41 100644 --- a/src/models/node.js +++ b/src/models/node.js @@ -254,9 +254,19 @@ const Node = { */ getBlocksAtRangeAsArray(range) { - return this - .getTextsAtRangeAsArray(range) - .map(text => this.getClosestBlock(text.key)) + range = range.normalize(this) + const { startKey, endKey } = range + const startBlock = this.getClosestBlock(startKey) + + // PERF: the most common case is when the range is in a single block node, + // where we can avoid a lot of iterating of the tree. + if (startKey == endKey) return [startBlock] + + const endBlock = this.getClosestBlock(endKey) + const blocks = this.getBlocksAsArray() + const start = blocks.indexOf(startBlock) + const end = blocks.indexOf(endBlock) + return blocks.slice(start, end + 1) }, /**