@@ -218,7 +218,7 @@ export default class Position {
218
218
* @type {module:engine/model/text~Text|null }
219
219
*/
220
220
get textNode ( ) {
221
- return getTextNode ( this , this . parent ) ;
221
+ return getTextNodeAtPosition ( this , this . parent ) ;
222
222
}
223
223
224
224
/**
@@ -228,16 +228,10 @@ export default class Position {
228
228
* @type {module:engine/model/node~Node|null }
229
229
*/
230
230
get nodeAfter ( ) {
231
- // Cache parent and reuse for performance reasons. This also means that we cannot use the #index property.
232
- // See #6579.
231
+ // Cache the parent and reuse for performance reasons. See #6579 and #6582.
233
232
const parent = this . parent ;
234
- const textNode = getTextNode ( this , parent ) ;
235
233
236
- if ( textNode !== null ) {
237
- return null ;
238
- }
239
-
240
- return parent . getChild ( parent . offsetToIndex ( this . offset ) ) ;
234
+ return getNodeAfterPosition ( this , parent , getTextNodeAtPosition ( this , parent ) ) ;
241
235
}
242
236
243
237
/**
@@ -247,16 +241,10 @@ export default class Position {
247
241
* @type {module:engine/model/node~Node|null }
248
242
*/
249
243
get nodeBefore ( ) {
250
- // Cache parent and reuse for performance reasons. This also means that we cannot use the #index property.
251
- // See #6579.
244
+ // Cache the parent and reuse for performance reasons. See #6579 and #6582.
252
245
const parent = this . parent ;
253
- const textNode = getTextNode ( this , parent ) ;
254
246
255
- if ( textNode !== null ) {
256
- return null ;
257
- }
258
-
259
- return parent . getChild ( parent . offsetToIndex ( this . offset ) - 1 ) ;
247
+ return getNodeBeforePosition ( this , parent , getTextNodeAtPosition ( this , parent ) ) ;
260
248
}
261
249
262
250
/**
@@ -1078,10 +1066,28 @@ export default class Position {
1078
1066
* @typedef {String } module:engine/model/position~PositionStickiness
1079
1067
*/
1080
1068
1081
- // Helper function used to inline text node access by using a cached parent.
1082
- // Reduces the access to the Position#parent property 3 times (in total, when taken into account what #nodeAfter and #nodeBefore do).
1083
- // See #6579.
1084
- function getTextNode ( position , positionParent ) {
1069
+ /**
1070
+ * Returns a text node at the given position.
1071
+ *
1072
+ * This is a helper function optimized to reuse the position parent instance for performance reasons.
1073
+ *
1074
+ * Normally, you should use {@link module:engine/model/position~Position#textNode `Position#textNode`}.
1075
+ * If you start hitting performance issues with {@link module:engine/model/position~Position#parent `Position#parent`}
1076
+ * check if your algorithm does not access it multiple times (which can happen directly or indirectly via other position properties).
1077
+ *
1078
+ * See https://github.com/ckeditor/ckeditor5/issues/6579.
1079
+ *
1080
+ * See also:
1081
+ *
1082
+ * * {@link module:engine/model/position~getNodeAfterPosition}
1083
+ * * {@link module:engine/model/position~getNodeBeforePosition}
1084
+ *
1085
+ * @param {module:engine/model/position~Position } position
1086
+ * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment } positionParent The parent of the
1087
+ * given position.
1088
+ * @returns {module:engine/model/text~Text|null }
1089
+ */
1090
+ export function getTextNodeAtPosition ( position , positionParent ) {
1085
1091
const node = positionParent . getChild ( positionParent . offsetToIndex ( position . offset ) ) ;
1086
1092
1087
1093
if ( node && node . is ( 'text' ) && node . startOffset < position . offset ) {
@@ -1090,3 +1096,60 @@ function getTextNode( position, positionParent ) {
1090
1096
1091
1097
return null ;
1092
1098
}
1099
+
1100
+ /**
1101
+ * Returns the node after the given position.
1102
+ *
1103
+ * This is a helper function optimized to reuse the position parent instance and the calculation of the text node at the
1104
+ * specific position for performance reasons.
1105
+ *
1106
+ * Normally, you should use {@link module:engine/model/position~Position#nodeAfter `Position#nodeAfter`}.
1107
+ * If you start hitting performance issues with {@link module:engine/model/position~Position#parent `Position#parent`} and/or
1108
+ * {@link module:engine/model/position~Position#textNode `Position#textNode`}
1109
+ * check if your algorithm does not access those properties multiple times
1110
+ * (which can happen directly or indirectly via other position properties).
1111
+ *
1112
+ * See https://github.com/ckeditor/ckeditor5/issues/6579 and https://github.com/ckeditor/ckeditor5/issues/6582.
1113
+ *
1114
+ * See also:
1115
+ *
1116
+ * * {@link module:engine/model/position~getTextNodeAtPosition}
1117
+ * * {@link module:engine/model/position~getNodeBeforePosition}
1118
+ *
1119
+ * @param {module:engine/model/position~Position } position
1120
+ * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment } positionParent The parent of the
1121
+ * given position.
1122
+ * @param {module:engine/model/text~Text|null } textNode Text node at the given position.
1123
+ * @returns {module:engine/model/node~Node|null }
1124
+ */
1125
+ export function getNodeAfterPosition ( position , positionParent , textNode ) {
1126
+ if ( textNode !== null ) {
1127
+ return null ;
1128
+ }
1129
+
1130
+ return positionParent . getChild ( positionParent . offsetToIndex ( position . offset ) ) ;
1131
+ }
1132
+
1133
+ /**
1134
+ * Returns the node before the given position.
1135
+ *
1136
+ * Refer to {@link module:engine/model/position~getNodeBeforePosition} for documentation on when to use this util method.
1137
+ *
1138
+ * See also:
1139
+ *
1140
+ * * {@link module:engine/model/position~getTextNodeAtPosition}
1141
+ * * {@link module:engine/model/position~getNodeAfterPosition}
1142
+ *
1143
+ * @param {module:engine/model/position~Position } position
1144
+ * @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment } positionParent The parent of the
1145
+ * given position.
1146
+ * @param {module:engine/model/text~Text|null } textNode Text node at the given position.
1147
+ * @returns {module:engine/model/node~Node|null }
1148
+ */
1149
+ export function getNodeBeforePosition ( position , positionParent , textNode ) {
1150
+ if ( textNode !== null ) {
1151
+ return null ;
1152
+ }
1153
+
1154
+ return positionParent . getChild ( positionParent . offsetToIndex ( position . offset ) - 1 ) ;
1155
+ }
0 commit comments