Browse Source

Fixes #544

Herbert Vojčík 11 years ago
parent
commit
54c1afd8ea
1 changed files with 28 additions and 0 deletions
  1. 28 0
      js/boot.js

+ 28 - 0
js/boot.js

@@ -156,6 +156,7 @@ function Smalltalk() {
 	var dnu = {
 		methods: [],
 		selectors: [],
+		checker: Object.create(null),
 
 		get: function (string) {
 			var index = this.selectors.indexOf(string);
@@ -164,11 +165,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) {
@@ -321,6 +327,7 @@ function Smalltalk() {
 	}
 
 	function copySuperclass(klass, superclass) {
+		deinstallAllMethods(klass);
 		for (superclass = superclass || klass.superclass;
 			superclass && superclass !== nil;
 			superclass = superclass.superclass) {
@@ -328,6 +335,7 @@ function Smalltalk() {
 				inheritMethodIfAbsent(superclass.methods[keys[i]], klass);
 			}
 		}
+		reinstallMethods(klass);
 	}
 
 	function installMethod(method, klass) {
@@ -348,6 +356,16 @@ function Smalltalk() {
 		klass.inheritedMethods[method.selector] = true;
 	}
 
+	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;
+			}
+		}
+	}
+
 	function reinstallMethods(klass) {
 		for(var keys = Object.keys(klass.methods), i=0; i<keys.length; i++) {
 			installMethod(klass.methods[keys[i]], klass);
@@ -571,6 +589,16 @@ function Smalltalk() {
 		delete klass.fn.prototype[st.selector(method.selector)];
 		delete klass.methods[method.selector];
 
+		// If already initialized (else it will be done later anyway),
+		// re-initialize all subclasses to ensure the method removal
+		// propagation (for wrapped classes, not using the prototype
+		// chain.
+		if(initialized) {
+			st.allSubclasses(klass).forEach(function(subclass) {
+				st.initClass(subclass);
+			});
+		}
+
 		// Do *not* delete protocols from here.
 		// This is handled by #removeCompiledMethod
 	};