| 
					
				 | 
			
			
				@@ -100,6 +100,7 @@ function inherits(child, parent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		constructor: { value: child, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			enumerable: false, configurable: true, writable: true } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return child; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 inherits(SmalltalkBehavior, SmalltalkObject); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -156,6 +157,7 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	var dnu = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		methods: [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		selectors: [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		checker: Object.create(null), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		get: function (string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			var index = this.selectors.indexOf(string); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -164,11 +166,16 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			this.selectors.push(string); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			var selector = st.selector(string); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.checker[selector] = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			var method = {jsSelector: selector, fn: this.createHandler(selector)}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			this.methods.push(method); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return method; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		isSelector: function (selector) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return this.checker[selector]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		/* Dnu handler method */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		createHandler: function (selector) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -218,7 +225,7 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		spec = spec || {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		var meta = metaclass(spec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		var that = meta.instanceClass; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		that.fn = spec.fn || function() {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		that.fn = spec.fn || inherits(function () {}, spec.superclass.fn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		setupClass(that, spec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		that.className = spec.className; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -234,10 +241,7 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	function metaclass(spec) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		spec = spec || {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		var that = new SmalltalkMetaclass(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		inherits( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			that.fn = function() {}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			spec.superclass ? spec.superclass.klass.fn : SmalltalkClass 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		that.fn = inherits(function () {}, spec.superclass ? spec.superclass.klass.fn : SmalltalkClass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		that.instanceClass = new that.fn(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		setupClass(that); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return that; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -291,10 +295,7 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	st.initClass = function(klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if(klass.wrapped) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			klass.inheritedMethods = {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			copySuperclass(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			installSuperclass(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if(klass === st.Object || klass.wrapped) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -309,25 +310,31 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	function installSuperclass(klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// only if the klass has not been initialized yet. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if(klass.fn.prototype._yourself) { return; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if(klass.superclass && klass.superclass !== nil) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			inherits(klass.fn, klass.superclass.fn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			wireKlass(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			reinstallMethods(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	function copySuperclass(klass, superclass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		var inheritedMethods = {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		deinstallAllMethods(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		for (superclass = superclass || klass.superclass; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			superclass && superclass !== nil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			superclass = superclass.superclass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			for (var keys = Object.keys(superclass.methods), i = 0; i < keys.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				inheritMethodIfAbsent(superclass.methods[keys[i]], klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				inheritMethodIfAbsent(superclass.methods[keys[i]]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		reinstallMethods(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		function inheritMethodIfAbsent(method) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			var selector = method.selector; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			//TODO: prepare klass methods into inheritedMethods to only test once 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			//TODO: Object.create(null) to ditch hasOwnProperty call (very slow) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if(klass.methods.hasOwnProperty(selector) || inheritedMethods.hasOwnProperty(selector)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			installMethod(method, klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			inheritedMethods[method.selector] = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	function installMethod(method, klass) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -337,15 +344,14 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	function inheritMethodIfAbsent(method, klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		var selector = method.selector; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if(klass.methods.hasOwnProperty(selector) || klass.inheritedMethods.hasOwnProperty(selector)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	function deinstallAllMethods(klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		var proto = klass.fn.prototype; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for(var keys = Object.getOwnPropertyNames(proto), i=0; i<keys.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			var key = keys[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (dnu.isSelector(key)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				proto[key] = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		installMethod(method, klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		klass.inheritedMethods[method.selector] = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	function reinstallMethods(klass) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -375,6 +381,20 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	function propagateMethodChange(klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// If already initialized (else it will be done later anyway), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// re-initialize all subclasses to ensure the method change 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// propagation (for wrapped classes, not using the prototype 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// chain). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//TODO: optimize, only one method need to be updated, not all of them 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (initialized) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			st.allSubclasses(klass).forEach(function (subclass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				st.initClass(subclass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/* Answer all registered Packages as Array */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// TODO: Remove this hack 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -541,15 +561,7 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		// Therefore we populate the organizer here too 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		klass.organization.elements.addElement(method.category); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// If already initialized (else it will be done later anyway), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// re-initialize all subclasses to ensure the new method 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// propagation (for wrapped classes, not using the prototype 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// chain. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if(initialized) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			st.allSubclasses(klass).forEach(function(subclass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				st.initClass(subclass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		propagateMethodChange(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		for(var i=0; i<method.messageSends.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			var dnuHandler = dnu.get(method.messageSends[i]); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -561,16 +573,19 @@ function Smalltalk() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	st.removeMethod = function(method, klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (klass !== method.methodClass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw new Error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "Refusing to remove method " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    + method.methodClass.className+">>"+method.selector 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    + " from different class " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    + klass.className); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			throw new Error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				"Refusing to remove method " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					+ method.methodClass.className+">>"+method.selector 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					+ " from different class " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					+ klass.className); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		delete klass.fn.prototype[st.selector(method.selector)]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		delete klass.methods[method.selector]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		st.initClass(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		propagateMethodChange(klass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		// Do *not* delete protocols from here. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		// This is handled by #removeCompiledMethod 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	}; 
			 |