function getSelectionDirection(s, leftNode, rightNode) {
   if (s.type !== 'Range') {
     return undefined; // no direction
   }
 
   const measure = () => s.toString().length;
 
   const initialSize = measure();
 
   if (initialSize === 1 && wasCaret && leftNode === rightNode) {
     // nb. We need to reset a single selection as Safari _always_ tells us the cursor was dragged
     // left to right (maybe RTL on those devices).
     // To be fair, Chrome has the same bug.
     s.extend(leftNode, 0);
     s.collapseToEnd();
     return undefined;
   }
 
   let updatedSize; // Try extending forward and seeing what happens.
 
   s.modify('extend', 'forward', 'character');
   updatedSize = measure();
 
   if (updatedSize > initialSize || containsNextElement(s, rightNode, true)) {
     s.modify('extend', 'backward', 'character');
     return true;
   }
 
   if (updatedSize < initialSize || !s.containsNode(leftNode)) {
     s.modify('extend', 'backward', 'character');
     return false;
   } // Maybe we were at the end of something. Extend backwards.
   // TODO(samthor): We seem to be able to get away without the 'backwards' case.
 
 
   s.modify('extend', 'backward', 'character');
   updatedSize = measure();
 
   if (updatedSize > initialSize || containsNextElement(s, leftNode, false)) {
     s.modify('extend', 'forward', 'character');
     return false;
   }
 
   if (updatedSize < initialSize || !s.containsNode(rightNode)) {
     s.modify('extend', 'forward', 'character');
     return true;
   } // This is likely a select-all.
 
 
   return undefined;
 }
@param {!Selection} s the window selection to use
@param {!Node} leftNode the left node
@param {!Node} rightNode the right node
@return {boolean|undefined} whether this has natural direction