atom / find-and-replace

Find and replace in a single buffer and in the project
MIT License
242 stars 196 forks source link

Uncaught TypeError: Cannot read property 'length' of undefined in BufferSearch #1113

Open stvcisco opened 4 years ago

stvcisco commented 4 years ago

[Enter steps to reproduce:]

Not sure how to reproduce consistently but should be easy to fix. I get this occasionally when opening a file and something is already typed in the Find input field in Atom.

Atom: 1.45.0 x64 Electron: 4.2.7 OS: Mac OS X 10.15.3 Thrown From: Atom Core

Stack Trace

Uncaught TypeError: Cannot read property 'length' of undefined

At /Applications/Atom.app/Contents/Resources/app/static/<embedded>:11

TypeError: Cannot read property 'length' of undefined
    at selectionsEqual (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:748768)
    at BufferSearch.search (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:748853)
    at FindView.search (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:768763)
    at FindView.findAndSelectResult (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:769122)
    at FindView.findNext (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:768897)
    at HTMLElement.find-and-replace:find-next (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:764679)
    at CommandRegistry.handleCommandEvent (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:349290)
    at KeymapManager.dispatchCommandEvent (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:1254747)
    at KeymapManager.handleKeyboardEvent (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:1250881)
    at WindowEventHandler.handleDocumentKeyEvent (/Applications/Atom.app/Contents/Resources/app/static/<embedded>:11:284496)

Commands

     -3:12.7.0 find-and-replace:show (input.hidden-input)
     -3:10.6.0 editor:consolidate-selections (input.hidden-input)
     -3:10.6.0 core:cancel (input.hidden-input)
     -2:47.7.0 tree-view:reveal-active-file (input.hidden-input)
     -2:43.4.0 fuzzy-finder:toggle-file-finder (input.hidden-input)
     -2:38.5.0 core:backspace (input.hidden-input)
     -2:36.7.0 core:confirm (input.hidden-input)
     -2:32.2.0 find-and-replace:find-next (input.hidden-input)
  3x -2:28 core:undo (input.hidden-input)
     -2:26.6.0 find-and-replace:show (input.hidden-input)
  4x -2:23 core:confirm (input.hidden-input)

Non-Core Packages

atom-beautify 0.33.4 
atom-material-syntax 1.0.8 
atom-material-ui 2.1.3 
atom-runner 2.7.1 
auto-semicolon 1.1.0 
auto-update-packages 1.0.1 
autocomplete-paths 2.12.2 
block-comment 0.4.3 
busy-signal 2.0.1 
coffee-refactor 0.7.0 
column-select 1.0.1 
compare-files 0.8.1 
console-log 1.10.0 
copy-as-rtf 0.9.3 
declarations 1.1.3 
declarations-js 1.0.2 
emmet 2.4.3 
file-icons 2.1.39 
fonts 3.10.0 
git-blame 1.8.0 
git-plus 8.7.1 
git-time-machine 2.1.0 
goto-definition 1.3.4 
highlight-selected 0.17.0 
hyperclick 0.1.5 
intentions 1.1.5 
js-hyperclick 1.13.3 
js-refactor 0.8.1 
jshint 1.8.6 
linter 2.3.1 
linter-eslint 8.5.5 
linter-stylelint 4.5.0 
linter-ui-default 1.8.1 
minimap 4.29.9 
minimap-find-and-replace 4.5.2 
minimap-hide 0.3.0 
minimap-highlight-selected 4.6.1 
minimap-linter 2.2.1 
minimap-split-diff 0.3.7 
monokai 0.24.0 
one-liner 0.1.3 
open-recent 5.0.0 
pigments 0.40.2 
platformio-ide-terminal 2.10.0 
prettier-atom 0.58.2 
rainbow-delimiters 2.1.2 
react 0.18.0 
refactor 0.11.5 
sort-lines 0.19.0 
split-diff 1.6.1 
Sublime-Style-Column-Selection 1.7.5 
theme-switcher 1.1.0 
todo-show 2.3.2 

Looking at this source file: /lib/buffer-search.js I see this function:

function selectionsEqual(selectionsA, selectionsB) {
  if (selectionsA.length === selectionsB.length) {
    for (let i = 0; i < selectionsA.length; i++) {
      if (!selectionsA[i].isEqual(selectionsB[i])) {
        return false
      }
    }
    return true
  } else {
    return false
  }
}

Seems it could be avoided like this:

function selectionsEqual(selectionsA, selectionsB) {
  if (!selectionsA || !selectionsB) return false;       // <----- avoid the type error
  if (selectionsA.length === selectionsB.length) {
    for (let i = 0; i < selectionsA.length; i++) {
      if (!selectionsA[i].isEqual(selectionsB[i])) {
        return false
      }
    }
    return true
  } else {
    return false
  }
}