@@ -75,6 +75,7 @@ define(function (require, exports, module) {
7575 */
7676
7777 /**
78+ * @constructor
7879 * MemoryStorage, as the name implies, stores the preferences in memory.
7980 * This is suitable for single session data or testing.
8081 *
@@ -93,7 +94,7 @@ define(function (require, exports, module) {
9394 * @return {Promise } promise that is already resolved
9495 */
9596 load : function ( ) {
96- var result = $ . Deferred ( ) ;
97+ var result = new $ . Deferred ( ) ;
9798 result . resolve ( this . data ) ;
9899 return result . promise ( ) ;
99100 } ,
@@ -106,7 +107,7 @@ define(function (require, exports, module) {
106107 * @return {Promise } promise that is already resolved
107108 */
108109 save : function ( newData ) {
109- var result = $ . Deferred ( ) ;
110+ var result = new $ . Deferred ( ) ;
110111 this . data = newData ;
111112 result . resolve ( ) ;
112113 return result . promise ( ) ;
@@ -122,6 +123,7 @@ define(function (require, exports, module) {
122123 } ;
123124
124125 /**
126+ * @constructor
125127 * Error type for problems parsing preference files.
126128 *
127129 * @param {string } message Error message
@@ -134,6 +136,7 @@ define(function (require, exports, module) {
134136 ParsingError . prototype = new Error ( ) ;
135137
136138 /**
139+ * @constructor
137140 * Loads/saves preferences from a JSON file on disk.
138141 *
139142 * @param {string } path Path to the preferences file
@@ -156,7 +159,7 @@ define(function (require, exports, module) {
156159 * @return {Promise } Resolved with the data once it has been parsed.
157160 */
158161 load : function ( ) {
159- var result = $ . Deferred ( ) ;
162+ var result = new $ . Deferred ( ) ;
160163 var path = this . path ;
161164 var createIfNew = this . createIfNew ;
162165 var self = this ;
@@ -200,7 +203,7 @@ define(function (require, exports, module) {
200203 * @return {Promise } Promise resolved (with no arguments) once the data has been saved
201204 */
202205 save : function ( newData ) {
203- var result = $ . Deferred ( ) ;
206+ var result = new $ . Deferred ( ) ;
204207 var path = this . path ;
205208 var prefFile = FileSystem . getFileForPath ( path ) ;
206209
@@ -251,6 +254,7 @@ define(function (require, exports, module) {
251254 } ;
252255
253256 /**
257+ * @constructor
254258 * A `Scope` is a data container that is tied to a `Storage`.
255259 *
256260 * Additionally, `Scope`s support "layers" which are additional levels of preferences
@@ -275,7 +279,7 @@ define(function (require, exports, module) {
275279 * @return {Promise } Promise that is resolved once loading is complete
276280 */
277281 load : function ( ) {
278- var result = $ . Deferred ( ) ;
282+ var result = new $ . Deferred ( ) ;
279283 this . storage . load ( )
280284 . then ( function ( data ) {
281285 var oldKeys = this . getKeys ( ) ;
@@ -302,7 +306,7 @@ define(function (require, exports, module) {
302306 self . _dirty = false ;
303307 return this . storage . save ( this . data ) ;
304308 } else {
305- return $ . Deferred ( ) . resolve ( ) . promise ( ) ;
309+ return ( new $ . Deferred ( ) ) . resolve ( ) . promise ( ) ;
306310 }
307311 } ,
308312
@@ -672,6 +676,7 @@ define(function (require, exports, module) {
672676// }
673677
674678 /**
679+ * @constructor
675680 * There can be multiple paths and they are each checked in turn. The first that matches the
676681 * currently edited file wins.
677682 *
@@ -833,6 +838,7 @@ define(function (require, exports, module) {
833838 } ;
834839
835840 /**
841+ * @constructor
836842 * Represents a single, known Preference.
837843 *
838844 * @param {Object } properties Information about the Preference that is stored on this object
@@ -864,10 +870,11 @@ define(function (require, exports, module) {
864870 } ) ;
865871
866872 /**
873+ * @constructor
867874 * Provides a subset of the PreferencesSystem functionality with preference
868875 * access always occurring with the given prefix.
869876 *
870- * @param {PreferencesSystem } baseSystem The real PreferencesSystem that is backing this one
877+ * @param {PreferencesSystem } base The real PreferencesSystem that is backing this one
871878 * @param {string } prefix Prefix that is used for preferences lookup. Any separator characters should already be added.
872879 */
873880 function PrefixedPreferencesSystem ( base , prefix ) {
@@ -1030,6 +1037,7 @@ define(function (require, exports, module) {
10301037 } ;
10311038
10321039 /**
1040+ * @constructor
10331041 * PreferencesSystem ties everything together to provide a simple interface for
10341042 * managing the whole prefs system.
10351043 *
@@ -1064,8 +1072,9 @@ define(function (require, exports, module) {
10641072
10651073 this . _pendingScopes = { } ;
10661074
1067- this . _saveInProgress = false ;
1075+ this . _saveInProgress = null ;
10681076 this . _nextSaveDeferred = null ;
1077+ this . finalized = false ;
10691078
10701079 // The objects that define the different kinds of path-based Scope handlers.
10711080 // Examples could include the handler for .brackets.json files or an .editorconfig
@@ -1552,31 +1561,37 @@ define(function (require, exports, module) {
15521561
15531562 /**
15541563 * Saves the preferences. If a save is already in progress, a Promise is returned for
1555- * that save operation.
1564+ * that save operation. If preferences have already been finalized then return a
1565+ * rejected promise.
15561566 *
15571567 * @return {Promise } Resolved when the preferences are done saving.
15581568 */
15591569 save : function ( ) {
1570+ if ( this . finalized ) {
1571+ console . log ( "PreferencesSystem.save() called after finalized!" ) ;
1572+ return ( new $ . Deferred ( ) ) . reject ( ) . promise ( ) ;
1573+ }
1574+
15601575 if ( this . _saveInProgress ) {
15611576 if ( ! this . _nextSaveDeferred ) {
1562- this . _nextSaveDeferred = $ . Deferred ( ) ;
1577+ this . _nextSaveDeferred = new $ . Deferred ( ) ;
15631578 }
15641579 return this . _nextSaveDeferred . promise ( ) ;
15651580 }
15661581
1567- this . _saveInProgress = true ;
1568- var deferred = this . _nextSaveDeferred || $ . Deferred ( ) ;
1582+ var deferred = this . _nextSaveDeferred || ( new $ . Deferred ( ) ) ;
1583+ this . _saveInProgress = deferred ;
15691584 this . _nextSaveDeferred = null ;
15701585
15711586 Async . doInParallel ( _ . values ( this . _scopes ) , function ( scope ) {
15721587 if ( scope ) {
15731588 return scope . save ( ) ;
15741589 } else {
1575- return $ . Deferred ( ) . resolve ( ) . promise ( ) ;
1590+ return ( new $ . Deferred ( ) ) . resolve ( ) . promise ( ) ;
15761591 }
15771592 } . bind ( this ) )
15781593 . then ( function ( ) {
1579- this . _saveInProgress = false ;
1594+ this . _saveInProgress = null ;
15801595 if ( this . _nextSaveDeferred ) {
15811596 this . save ( ) ;
15821597 }
@@ -1742,6 +1757,34 @@ define(function (require, exports, module) {
17421757 */
17431758 getPrefixedSystem : function ( prefix ) {
17441759 return new PrefixedPreferencesSystem ( this , prefix + "." ) ;
1760+ } ,
1761+
1762+ /**
1763+ * Return a promise that is resolved when all preferences have been saved.
1764+ * Disallow any other preferences from getting saved after promise is resolved.
1765+ *
1766+ * @return {Promise } Resolved when the preferences are done saving.
1767+ */
1768+ _finalize : function ( ) {
1769+ var deferred = new $ . Deferred ( ) ,
1770+ self = this ;
1771+
1772+ // Don't resolve promise until last `_saveInProgress` promise completes.
1773+ // There will only ever be a `_nextSaveDeferred`, if there is already a
1774+ // `_saveInProgress` and it will become the new `_saveInProgress` as soon as
1775+ // previous `_saveInProgress` resolves, so only need to wait for `_saveInProgress`.
1776+ function checkForSaveAndFinalize ( ) {
1777+ if ( self . _saveInProgress ) {
1778+ self . _saveInProgress . done ( checkForSaveAndFinalize ) ;
1779+ } else {
1780+ self . finalized = true ;
1781+ deferred . resolve ( ) ;
1782+ }
1783+ }
1784+
1785+ checkForSaveAndFinalize ( ) ;
1786+
1787+ return deferred . promise ( ) ;
17451788 }
17461789 } ) ;
17471790
0 commit comments