@@ -701,10 +701,13 @@ define(function (require, exports, module) {
701701 * Reverts the Document to the current contents of its file on disk. Discards any unsaved changes
702702 * in the Document.
703703 * @param {Document } doc
704- * @return {$.Promise } a Promise that's resolved when done, or rejected with a FileSystemError if the
705- * file cannot be read (after showing an error dialog to the user).
704+ * @param {boolean= } suppressError If true, then a failure to read the file will be ignored and the
705+ * resulting promise will be resolved rather than rejected.
706+ * @return {$.Promise } a Promise that's resolved when done, or (if suppressError is false)
707+ * rejected with a FileSystemError if the file cannot be read (after showing an error
708+ * dialog to the user).
706709 */
707- function doRevert ( doc ) {
710+ function doRevert ( doc , suppressError ) {
708711 var result = new $ . Deferred ( ) ;
709712
710713 FileUtils . readAsText ( doc . file )
@@ -713,10 +716,14 @@ define(function (require, exports, module) {
713716 result . resolve ( ) ;
714717 } )
715718 . fail ( function ( error ) {
716- FileUtils . showFileOpenError ( error , doc . file . fullPath )
717- . done ( function ( ) {
718- result . reject ( error ) ;
719- } ) ;
719+ if ( suppressError ) {
720+ result . resolve ( ) ;
721+ } else {
722+ FileUtils . showFileOpenError ( error , doc . file . fullPath )
723+ . done ( function ( ) {
724+ result . reject ( error ) ;
725+ } ) ;
726+ }
720727 } ) ;
721728
722729 return result . promise ( ) ;
@@ -1105,13 +1112,19 @@ define(function (require, exports, module) {
11051112 // copy of whatever's on disk.
11061113 doClose ( file ) ;
11071114
1108- // Only reload from disk if we've executed the Close for real,
1109- // *and* if at least one other view still exists
1110- if ( ! promptOnly && DocumentManager . getOpenDocumentForPath ( file . fullPath ) ) {
1111- doRevert ( doc )
1112- . then ( result . resolve , result . reject ) ;
1113- } else {
1115+ // Only reload from disk if we've executed the Close for real.
1116+ if ( promptOnly ) {
11141117 result . resolve ( ) ;
1118+ } else {
1119+ // Even if there are no listeners attached to the document at this point, we want
1120+ // to do the revert anyway, because clients who are listening to the global documentChange
1121+ // event from the Document module (rather than attaching to the document directly),
1122+ // such as the Find in Files panel, should get a change event. However, in that case,
1123+ // we want to ignore errors during the revert, since we don't want a failed revert
1124+ // to throw a dialog if the document isn't actually open in the UI.
1125+ var suppressError = ! DocumentManager . getOpenDocumentForPath ( file . fullPath ) ;
1126+ doRevert ( doc , suppressError )
1127+ . then ( result . resolve , result . reject ) ;
11151128 }
11161129 }
11171130 } ) ;
@@ -1131,8 +1144,9 @@ define(function (require, exports, module) {
11311144 * @param {!Array.<FileEntry> } list
11321145 * @param {boolean } promptOnly
11331146 * @param {boolean } clearCurrentDoc
1147+ * @param {boolean } _forceClose Whether to force all the documents to close even if they have unsaved changes. For unit testing only.
11341148 */
1135- function _closeList ( list , promptOnly , clearCurrentDoc ) {
1149+ function _closeList ( list , promptOnly , clearCurrentDoc , _forceClose ) {
11361150 var result = new $ . Deferred ( ) ,
11371151 unsavedDocs = [ ] ;
11381152
@@ -1143,8 +1157,8 @@ define(function (require, exports, module) {
11431157 }
11441158 } ) ;
11451159
1146- if ( unsavedDocs . length === 0 ) {
1147- // No unsaved changes, so we can proceed without a prompt
1160+ if ( unsavedDocs . length === 0 || _forceClose ) {
1161+ // No unsaved changes or we want to ignore them , so we can proceed without a prompt
11481162 result . resolve ( ) ;
11491163
11501164 } else if ( unsavedDocs . length === 1 ) {
@@ -1160,17 +1174,7 @@ define(function (require, exports, module) {
11601174
11611175 } else {
11621176 // Multiple unsaved files: show a single bulk prompt listing all files
1163- var message = Strings . SAVE_CLOSE_MULTI_MESSAGE ;
1164-
1165- message += "<ul class='dialog-list'>" ;
1166- unsavedDocs . forEach ( function ( doc ) {
1167- var fullPath = doc . file . fullPath ;
1168-
1169- message += "<li><span class='dialog-filename'>" ;
1170- message += StringUtils . breakableUrl ( _shortTitleForDocument ( doc ) ) ;
1171- message += "</span></li>" ;
1172- } ) ;
1173- message += "</ul>" ;
1177+ var message = Strings . SAVE_CLOSE_MULTI_MESSAGE + FileUtils . makeDialogFileList ( _ . map ( unsavedDocs , _shortTitleForDocument ) ) ;
11741178
11751179 Dialogs . showModalDialog (
11761180 DefaultDialogs . DIALOG_ID_SAVE_CLOSE ,
@@ -1228,14 +1232,17 @@ define(function (require, exports, module) {
12281232 /**
12291233 * Closes all open documents; equivalent to calling handleFileClose() for each document, except
12301234 * that unsaved changes are confirmed once, in bulk.
1231- * @param {?{promptOnly: boolean} } If true, only displays the relevant confirmation UI and does NOT
1235+ * @param {?{promptOnly: boolean, _forceClose: boolean} }
1236+ * If promptOnly is true, only displays the relevant confirmation UI and does NOT
12321237 * actually close any documents. This is useful when chaining close-all together with
12331238 * other user prompts that may be cancelable.
1239+ * If _forceClose is true, forces the files to close with no confirmation even if dirty.
1240+ * Should only be used for unit test cleanup.
12341241 * @return {$.Promise } a promise that is resolved when all files are closed
12351242 */
12361243 function handleFileCloseAll ( commandData ) {
12371244 return _closeList ( DocumentManager . getWorkingSet ( ) ,
1238- ( commandData && commandData . promptOnly ) , true ) . done ( function ( ) {
1245+ ( commandData && commandData . promptOnly ) , true , ( commandData && commandData . _forceClose ) ) . done ( function ( ) {
12391246 if ( ! DocumentManager . getCurrentDocument ( ) ) {
12401247 EditorManager . _closeCustomViewer ( ) ;
12411248 }
0 commit comments