10
10
import TreeWalker from './treewalker' ;
11
11
import compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays' ;
12
12
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror' ;
13
- import Text from './text' ;
14
13
import { last } from 'lodash-es' ;
15
14
16
15
// To check if component is loaded more than once.
@@ -216,9 +215,7 @@ export default class Position {
216
215
* @type {module:engine/model/text~Text|null }
217
216
*/
218
217
get textNode ( ) {
219
- const node = this . parent . getChild ( this . index ) ;
220
-
221
- return ( node instanceof Text && node . startOffset < this . offset ) ? node : null ;
218
+ return getTextNode ( this , this . parent ) ;
222
219
}
223
220
224
221
/**
@@ -228,17 +225,35 @@ export default class Position {
228
225
* @type {module:engine/model/node~Node|null }
229
226
*/
230
227
get nodeAfter ( ) {
231
- return this . textNode === null ? this . parent . getChild ( this . index ) : null ;
228
+ // Cache parent and reuse for performance reasons. This also means that we cannot use the #index property.
229
+ // See #6579.
230
+ const parent = this . parent ;
231
+ const textNode = getTextNode ( this , parent ) ;
232
+
233
+ if ( textNode !== null ) {
234
+ return null ;
235
+ }
236
+
237
+ return parent . getChild ( parent . offsetToIndex ( this . offset ) ) ;
232
238
}
233
239
234
240
/**
235
241
* Node directly before this position or `null` if this position is in text node.
236
242
*
237
243
* @readonly
238
- * @type {Node }
244
+ * @type {module:engine/model/node~ Node|null }
239
245
*/
240
246
get nodeBefore ( ) {
241
- return this . textNode === null ? this . parent . getChild ( this . index - 1 ) : null ;
247
+ // Cache parent and reuse for performance reasons. This also means that we cannot use the #index property.
248
+ // See #6579.
249
+ const parent = this . parent ;
250
+ const textNode = getTextNode ( this , parent ) ;
251
+
252
+ if ( textNode !== null ) {
253
+ return null ;
254
+ }
255
+
256
+ return parent . getChild ( parent . offsetToIndex ( this . offset ) - 1 ) ;
242
257
}
243
258
244
259
/**
@@ -339,10 +354,12 @@ export default class Position {
339
354
* @returns {Array.<module:engine/model/item~Item> } Array with ancestors.
340
355
*/
341
356
getAncestors ( ) {
342
- if ( this . parent . is ( 'documentFragment' ) ) {
343
- return [ this . parent ] ;
357
+ const parent = this . parent ;
358
+
359
+ if ( parent . is ( 'documentFragment' ) ) {
360
+ return [ parent ] ;
344
361
} else {
345
- return this . parent . getAncestors ( { includeSelf : true } ) ;
362
+ return parent . getAncestors ( { includeSelf : true } ) ;
346
363
}
347
364
}
348
365
@@ -1057,3 +1074,16 @@ export default class Position {
1057
1074
*
1058
1075
* @typedef {String } module:engine/model/position~PositionStickiness
1059
1076
*/
1077
+
1078
+ // Helper function used to inline text node access by using a cached parent.
1079
+ // Reduces the access to the Position#parent property 3 times (in total, when taken into account what #nodeAfter and #nodeBefore do).
1080
+ // See #6579.
1081
+ function getTextNode ( position , positionParent ) {
1082
+ const node = positionParent . getChild ( positionParent . offsetToIndex ( position . offset ) ) ;
1083
+
1084
+ if ( node && node . is ( 'text' ) && node . startOffset < position . offset ) {
1085
+ return node ;
1086
+ }
1087
+
1088
+ return null ;
1089
+ }
0 commit comments