amber/js/boot.js in resin-0.3.0 vs amber/js/boot.js in resin-0.3.1
- old
+ new
@@ -31,11 +31,11 @@
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
==================================================================== */
-/* Make that console is defined */
+/* Make sure that console is defined */
if (typeof console === "undefined") {
this.console = {
log: function() {},
warn: function() {},
@@ -45,24 +45,47 @@
};
}
/* Smalltalk constructors definition */
-function SmalltalkObject(){}
-function SmalltalkBehavior(){}
-function SmalltalkClass(){}
-function SmalltalkPackage(){}
+function SmalltalkObject(){};
+function SmalltalkBehavior(){};
+function SmalltalkClass(){};
+function SmalltalkPackage(){};
function SmalltalkMetaclass(){
this.meta = true;
-}
-function SmalltalkMethod(){}
-function SmalltalkNil(){}
+};
+function SmalltalkMethod(){};
+function SmalltalkNil(){};
function SmalltalkSymbol(string){
this.value = string;
-}
+};
+function SmalltalkOrganizer() {
+ this.elements = [];
+};
+
+SmalltalkOrganizer.prototype.addElement = function(el) {
+ if(typeof el === 'undefined' || el === nil) {
+ return false;
+ }
+ if(this.elements.indexOf(el) == -1) {
+ this.elements.push(el);
+ }
+};
+
+SmalltalkOrganizer.prototype.removeElement = function(el) {
+ for(var i=0; i<this.elements.length; i++) {
+ if(this.elements[i] == el) {
+ this.elements.splice(i, 1);
+ break;
+ }
+ }
+};
+
+
function Smalltalk(){
var st = this;
/* This is the current call context object. While it is publicly available,
@@ -106,10 +129,11 @@
/* Smalltalk package creation. To add a Package, use smalltalk.addPackage() */
function pkg(spec) {
var that = new SmalltalkPackage();
that.pkgName = spec.pkgName;
+ that.organization = new SmalltalkOrganizer();
that.properties = spec.properties || {};
return that;
};
/* Smalltalk class creation. A class is an instance of an automatically
@@ -129,11 +153,11 @@
}
return that;
}
function metaclass() {
- var meta = setupClass(new SmalltalkMetaclass(), {});
+ var meta = setupClass(new SmalltalkMetaclass(), {})
meta.instanceClass = new meta.fn;
return meta;
}
function setupClass(that, spec) {
@@ -141,10 +165,11 @@
that.iVarNames = spec.iVarNames || [];
Object.defineProperty(that, "toString", {
value: function() { return 'Smalltalk ' + this.className; },
configurable: true // no writable - in par with ES6 methods
});
+ that.organization = new SmalltalkOrganizer();
that.pkg = spec.pkg;
Object.defineProperties(that.fn.prototype, {
methods: { value: {}, enumerable: false, configurable: true, writable: true },
inheritedMethods: { value: {}, enumerable: false, configurable: true, writable: true },
klass: { value: that, enumerable: false, configurable: true, writable: true }
@@ -318,23 +343,53 @@
superclass: superclass,
pkg: pkg,
iVarNames: iVarNames
});
}
+
+ pkg.organization.addElement(st[className]);
};
- /* Add a method to a class */
+ st.removeClass = function(klass) {
+ klass.pkg.organization.removeElement(klass);
+ delete st[klass.className];
+ };
+ /* Add/remove a method to/from a class */
+
st.addMethod = function(jsSelector, method, klass) {
Object.defineProperty(klass.fn.prototype, jsSelector, {
value: method.fn, configurable: true, writable: true
});
klass.fn.prototype.methods[method.selector] = method;
method.methodClass = klass;
method.jsSelector = jsSelector;
+
+ klass.organization.addElement(method.category);
};
+ st.removeMethod = function(method) {
+ var protocol = method.category;
+ var klass = method.methodClass;
+ var methods = klass.fn.prototype.methods;
+
+ delete klass.fn.prototype[method.selector._asSelector()];
+ delete methods[method.selector];
+
+ var selectors = Object.keys(methods);
+ var shouldDeleteProtocol = true;
+ for(var i= 0, l = selectors.length; i<l; i++) {
+ if(methods[selectors[i]].category === protocol) {
+ shouldDeleteProtocol = false;
+ break;
+ };
+ };
+ if(shouldDeleteProtocol) {
+ klass.organization.removeElement(protocol)
+ };
+ };
+
/* Handles unhandled errors during message sends */
st.send = function(receiver, selector, args, klass) {
if(st.thisContext) {
return withContextSend(receiver, selector, args, klass);
@@ -512,11 +567,11 @@
return object;
};
/* Boolean assertion */
st.assert = function(boolean) {
- if(boolean.klass === smalltalk.Boolean) {
+ if ((undefined !== boolean) && (boolean.klass === smalltalk.Boolean)) {
return boolean;
} else {
smalltalk.NonBooleanReceiver._new()._object_(boolean)._signal();
}
}
@@ -526,16 +581,10 @@
this.receiver = receiver;
this.selector = selector;
this.method = method;
this.temps = temps || {};
this.homeContext = home;
-
- this.resume = function() {
- //Brutally set the receiver as thisContext, then re-enter the function
- smalltalk.thisContext = this;
- return this.method.apply(receiver, temps);
- };
};
SmalltalkMethodContext.prototype.copy = function() {
var home = this.homeContext;
if(home) {home = home.copy()}
@@ -546,10 +595,16 @@
this.temps,
home
);
};
+SmalltalkMethodContext.prototype.resume = function() {
+ //Brutally set the receiver as thisContext, then re-enter the function
+ smalltalk.thisContext = this;
+ return this.method.apply(receiver, temps);
+};
+
/* Global Smalltalk objects. */
var nil = new SmalltalkNil();
var smalltalk = new Smalltalk();
@@ -568,9 +623,10 @@
smalltalk.wrapClassName("Package", "Kernel", SmalltalkPackage, smalltalk.Object);
smalltalk.wrapClassName("Behavior", "Kernel", SmalltalkBehavior, smalltalk.Object);
smalltalk.wrapClassName("Class", "Kernel", SmalltalkClass, smalltalk.Behavior);
smalltalk.wrapClassName("Metaclass", "Kernel", SmalltalkMetaclass, smalltalk.Behavior);
smalltalk.wrapClassName("CompiledMethod", "Kernel", SmalltalkMethod, smalltalk.Object);
+smalltalk.wrapClassName("Organizer", "Kernel-Objects", SmalltalkOrganizer, smalltalk.Object);
smalltalk.Object.klass.superclass = smalltalk.Class;
smalltalk.wrapClassName("Number", "Kernel", Number, smalltalk.Object);
smalltalk.wrapClassName("BlockClosure", "Kernel", Function, smalltalk.Object);