1 // ========================================================================== 2 // Project: SproutCore Costello - Property Observing Library 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 9 /** 10 Standard Error that should be raised when you try to modify a frozen object. 11 12 @type Error 13 */ 14 SC.FROZEN_ERROR = "Cannot modify a frozen object"; 15 16 /** 17 @class 18 19 The SC.Freezable mixin implements some basic methods for marking an object 20 as frozen. Once an object is frozen it should be read only. No changes 21 may be made the internal state of the object. 22 23 Enforcement 24 --- 25 26 To fully support freezing in your subclass, you must include this mixin and 27 override any method that might alter any property on the object to instead 28 raise an exception. You can check the state of an object by checking the 29 isFrozen property. 30 31 Although future versions of JavaScript may support language-level freezing 32 object objects, that is not the case today. Even if an object is freezable, 33 it is still technically possible to modify the object, even though it could 34 break other parts of your application that do not expect a frozen object to 35 change. It is, therefore, very important that you always respect the 36 isFrozen property on all freezable objects. 37 38 Example 39 40 The example below shows a simple object that implement the SC.Freezable 41 protocol. 42 43 Contact = SC.Object.extend(SC.Freezable, { 44 45 firstName: null, 46 47 lastName: null, 48 49 // swaps the names 50 swapNames: function() { 51 if (this.get('isFrozen')) throw new Error(SC.FROZEN_ERROR); 52 var tmp = this.get('firstName'); 53 this.set('firstName', this.get('lastName')); 54 this.set('lastName', tmp); 55 return this; 56 } 57 58 }); 59 60 c = Context.create({ firstName: "John", lastName: "Doe" }); 61 c.swapNames(); => returns c 62 c.freeze(); 63 c.swapNames(); => EXCEPTION 64 65 Copying 66 --- 67 68 Usually the SC.Freezable protocol is implemented in cooperation with the 69 SC.Copyable protocol, which defines a frozenCopy() method that will return 70 a frozen object, if the object implements this method as well. 71 72 */ 73 SC.Freezable = /** @scope SC.Freezable.prototype */ { 74 75 /** 76 Walk like a duck. 77 78 @type Boolean 79 */ 80 isFreezable: YES, 81 82 /** 83 Set to YES when the object is frozen. Use this property to detect whether 84 your object is frozen or not. 85 86 @type Boolean 87 */ 88 isFrozen: NO, 89 90 /** 91 Freezes the object. Once this method has been called the object should 92 no longer allow any properties to be edited. 93 94 @returns {Object} receiver 95 */ 96 freeze: function() { 97 // NOTE: Once someone actually implements Object.freeze() in the browser, 98 // add a call to that here also. 99 100 if (this.set) this.set('isFrozen', YES); 101 else this.isFrozen = YES; 102 return this; 103 } 104 105 }; 106 107 108 // Add to Array 109 SC.mixin(Array.prototype, SC.Freezable); 110