|
@@ -35,7 +35,7 @@
|
|
|
|
|
|
/* Make sure that console is defined */
|
|
|
|
|
|
-if (typeof console === "undefined") {
|
|
|
+if(typeof console === "undefined") {
|
|
|
this.console = {
|
|
|
log: function() {},
|
|
|
warn: function() {},
|
|
@@ -48,8 +48,8 @@ if (typeof console === "undefined") {
|
|
|
/* Array extensions */
|
|
|
|
|
|
Array.prototype.addElement = function(el) {
|
|
|
- if(typeof el === 'undefined') { return false; };
|
|
|
- if(this.indexOf(el) == -1) {
|
|
|
+ if(typeof el === 'undefined') { return false; }
|
|
|
+ if(this.indexOf(el) == -1) {
|
|
|
this.push(el);
|
|
|
}
|
|
|
};
|
|
@@ -66,45 +66,39 @@ Array.prototype.removeElement = function(el) {
|
|
|
|
|
|
/* Smalltalk constructors definition */
|
|
|
|
|
|
-function SmalltalkObject(){};
|
|
|
-function SmalltalkBehavior(){};
|
|
|
-function SmalltalkClass(){};
|
|
|
-function SmalltalkMetaclass(){
|
|
|
+function SmalltalkObject() {}
|
|
|
+function SmalltalkBehavior() {}
|
|
|
+function SmalltalkClass() {}
|
|
|
+function SmalltalkMetaclass() {
|
|
|
this.meta = true;
|
|
|
-};
|
|
|
-
|
|
|
-function SmalltalkPackage(){};
|
|
|
-function SmalltalkMethod(){};
|
|
|
-function SmalltalkNil(){};
|
|
|
-
|
|
|
-function SmalltalkSymbol(string){
|
|
|
+}
|
|
|
+function SmalltalkPackage() {}
|
|
|
+function SmalltalkMethod() {}
|
|
|
+function SmalltalkNil() {}
|
|
|
+function SmalltalkSymbol(string) {
|
|
|
this.value = string;
|
|
|
-};
|
|
|
-
|
|
|
+}
|
|
|
function SmalltalkOrganizer() {
|
|
|
this.elements = [];
|
|
|
-};
|
|
|
-
|
|
|
-SmalltalkBehavior.prototype = new SmalltalkObject();
|
|
|
-SmalltalkClass.prototype = new SmalltalkBehavior();
|
|
|
-SmalltalkMetaclass.prototype = new SmalltalkBehavior();
|
|
|
-
|
|
|
-SmalltalkNil.prototype = new SmalltalkObject();
|
|
|
-SmalltalkMethod.prototype = new SmalltalkObject();
|
|
|
-SmalltalkPackage.prototype = new SmalltalkObject();
|
|
|
-SmalltalkOrganizer.prototype = new SmalltalkObject();
|
|
|
+}
|
|
|
|
|
|
-SmalltalkBehavior.prototype.constructor = SmalltalkBehavior;
|
|
|
-SmalltalkClass.prototype.constructor = SmalltalkClass;
|
|
|
-SmalltalkMetaclass.prototype.constructor = SmalltalkMetaclass;
|
|
|
+function inherits(child, parent) {
|
|
|
+ child.prototype = Object.create(parent.prototype, {
|
|
|
+ constructor: { value: child,
|
|
|
+ enumerable: false, configurable: true, writable: true }
|
|
|
+ });
|
|
|
+}
|
|
|
|
|
|
-SmalltalkNil.prototype.constructor = SmalltalkNil;
|
|
|
-SmalltalkMethod.prototype.constructor = SmalltalkMethod;
|
|
|
-SmalltalkPackage.prototype.constructor = SmalltalkPackage;
|
|
|
-SmalltalkOrganizer.prototype.constructor = SmalltalkOrganizer;
|
|
|
+inherits(SmalltalkBehavior, SmalltalkObject);
|
|
|
+inherits(SmalltalkClass, SmalltalkBehavior);
|
|
|
+inherits(SmalltalkMetaclass, SmalltalkBehavior);
|
|
|
+inherits(SmalltalkNil, SmalltalkObject);
|
|
|
+inherits(SmalltalkMethod, SmalltalkObject);
|
|
|
+inherits(SmalltalkPackage, SmalltalkObject);
|
|
|
+inherits(SmalltalkOrganizer, SmalltalkObject);
|
|
|
|
|
|
|
|
|
-function Smalltalk(){
|
|
|
+function Smalltalk() {
|
|
|
|
|
|
var st = this;
|
|
|
|
|
@@ -134,35 +128,35 @@ function Smalltalk(){
|
|
|
|
|
|
var dnuHandlers = [];
|
|
|
|
|
|
- var addDnuHandler = function(string) {
|
|
|
+ function addDnuHandler(string) {
|
|
|
if(dnuHandlers.indexOf(string) == -1) {
|
|
|
dnuHandlers.push(string);
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- /* Dnu handler method */
|
|
|
+ /* Dnu handler method */
|
|
|
|
|
|
- var dnu = function(selector) {
|
|
|
+ function dnu(selector) {
|
|
|
return function() {
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
return messageNotUnderstood(this, selector, args);
|
|
|
};
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
/* The symbol table ensures symbol unicity */
|
|
|
|
|
|
- symbolTable = {};
|
|
|
+ var symbolTable = {};
|
|
|
st.symbolFor = function(string) {
|
|
|
if(symbolTable[string] === undefined) {
|
|
|
symbolTable[string] = new SmalltalkSymbol(string);
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
return symbolTable[string];
|
|
|
};
|
|
|
|
|
|
/* Unique ID number generator */
|
|
|
|
|
|
- oid = 0;
|
|
|
+ var oid = 0;
|
|
|
st.nextId = function() {
|
|
|
oid += 1;
|
|
|
return oid;
|
|
@@ -180,10 +174,10 @@ function Smalltalk(){
|
|
|
that.organization = new SmalltalkOrganizer();
|
|
|
that.properties = spec.properties || {};
|
|
|
return that;
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
/* Smalltalk class creation. A class is an instance of an automatically
|
|
|
- created metaclass object. Newly created classes (not their metaclass)
|
|
|
+ created metaclass object. Newly created classes (not their metaclass)
|
|
|
should be added to the smalltalk object, see smalltalk.addClass().
|
|
|
Superclass linking is *not* handled here, see smalltalk.init() */
|
|
|
|
|
@@ -217,8 +211,7 @@ function Smalltalk(){
|
|
|
var that = new SmalltalkMetaclass();
|
|
|
that.fn = function() {};
|
|
|
that.organization = new SmalltalkOrganizer();
|
|
|
- that.fn.prototype = new superConstructor();
|
|
|
- that.fn.prototype.constructor = that.fn;
|
|
|
+ inherits(that.fn, superConstructor);
|
|
|
|
|
|
setupClass(that);
|
|
|
|
|
@@ -229,7 +222,7 @@ function Smalltalk(){
|
|
|
function setupClass(klass, spec) {
|
|
|
spec = spec || {};
|
|
|
if(!klass.fn) {
|
|
|
- klass.fn = spec.fn || function(){};
|
|
|
+ klass.fn = spec.fn || function() {};
|
|
|
}
|
|
|
klass.iVarNames = spec.iVarNames || [];
|
|
|
klass.pkg = spec.pkg;
|
|
@@ -256,7 +249,7 @@ function Smalltalk(){
|
|
|
writable: true
|
|
|
}
|
|
|
});
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
/* Smalltalk method object. To add a method to a class,
|
|
|
use smalltalk.addMethod() */
|
|
@@ -297,21 +290,20 @@ function Smalltalk(){
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- var installSuperclass = function(klass) {
|
|
|
+ function installSuperclass(klass) {
|
|
|
// only if the klass has not been initialized yet.
|
|
|
- if(klass.fn.prototype._yourself) { return false; };
|
|
|
+ if(klass.fn.prototype._yourself) { return false; }
|
|
|
|
|
|
- if(klass.superclass && klass.superclass !== nil) {
|
|
|
- klass.fn.prototype = new klass.superclass.fn();
|
|
|
- klass.fn.prototype.constructor = klass.fn;
|
|
|
+ if(klass.superclass && klass.superclass !== nil) {
|
|
|
+ inherits(klass.fn, klass.superclass.fn);
|
|
|
Object.defineProperties(klass.fn.prototype, {
|
|
|
klass: { value: klass, enumerable: false, configurable: true, writable: true }
|
|
|
});
|
|
|
reinstallMethods(klass);
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- var copySuperclass = function(klass, superclass) {
|
|
|
+ function copySuperclass(klass, superclass) {
|
|
|
superclass = superclass || klass.superclass;
|
|
|
if(superclass && superclass !== nil) {
|
|
|
for(var keys = Object.keys(superclass.methods), i=0; i<keys.length; i++) {
|
|
@@ -324,44 +316,44 @@ function Smalltalk(){
|
|
|
copySuperclass(klass, superclass.superclass);
|
|
|
}
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- var installMethod = function(method, klass) {
|
|
|
+ function installMethod(method, klass) {
|
|
|
Object.defineProperty(klass.fn.prototype, method.jsSelector, {
|
|
|
value: method.fn, configurable: true, writable: true
|
|
|
});
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- var reinstallMethods = function(klass) {
|
|
|
+ function reinstallMethods(klass) {
|
|
|
for(var keys = Object.keys(klass.methods), i=0; i<keys.length; i++) {
|
|
|
installMethod(klass.methods[keys[i]], klass);
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- var installDnuHandlers = function(klass) {
|
|
|
+ function installDnuHandlers(klass) {
|
|
|
for(var i=0; i<dnuHandlers.length; i++) {
|
|
|
installDnuHandler(dnuHandlers[i], klass);
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- var installDnuHandler = function(string, klass) {
|
|
|
+ function installDnuHandler(string, klass) {
|
|
|
var selector = st.selector(string);
|
|
|
if(!klass.fn.prototype[selector]) {
|
|
|
Object.defineProperty(klass.fn.prototype, selector, {
|
|
|
value: dnu(selector), configurable: true, writable: true
|
|
|
});
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- var installNewDnuHandler = function(string) {
|
|
|
+ function installNewDnuHandler(string) {
|
|
|
if(dnuHandlers.indexOf(string) === -1) {
|
|
|
addDnuHandler(string);
|
|
|
installDnuHandler(string, smalltalk.Object);
|
|
|
for(var i=0; i<wrappedClasses.length; i++) {
|
|
|
installDnuHandler(string, wrappedClasses[i]);
|
|
|
- };
|
|
|
- }
|
|
|
- };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* Answer all registered Packages as Array */
|
|
|
// TODO: Remove this hack
|
|
@@ -369,7 +361,7 @@ function Smalltalk(){
|
|
|
st.packages.all = function() {
|
|
|
var packages = [];
|
|
|
for(var i in st.packages) {
|
|
|
- if (!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
|
|
|
+ if(!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
|
|
|
packages.push(st.packages[i]);
|
|
|
}
|
|
|
return packages
|
|
@@ -425,15 +417,15 @@ function Smalltalk(){
|
|
|
});
|
|
|
|
|
|
classes.addElement(st[className]);
|
|
|
- if(wrapped) {wrappedClasses.addElement(st[className])};
|
|
|
- pkg.organization.elements.addElement(st[className]);
|
|
|
+ if(wrapped) {wrappedClasses.addElement(st[className])}
|
|
|
+ pkg.organization.elements.addElement(st[className]);
|
|
|
};
|
|
|
|
|
|
/* Create an alias for an existing class */
|
|
|
|
|
|
st.alias = function(klass, alias) {
|
|
|
st[alias] = klass;
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
/* Add a package to the smalltalk.packages object, creating a new one if needed.
|
|
|
If pkgName is null or empty we return nil, which is an allowed package for a class.
|
|
@@ -466,7 +458,7 @@ function Smalltalk(){
|
|
|
} else {
|
|
|
if(st[className]) {
|
|
|
st.removeClass(st[className]);
|
|
|
- };
|
|
|
+ }
|
|
|
st[className] = klass({
|
|
|
className: className,
|
|
|
superclass: superclass,
|
|
@@ -502,8 +494,8 @@ function Smalltalk(){
|
|
|
addDnuHandler(method.messageSends[i]);
|
|
|
if(initialized) {
|
|
|
installNewDnuHandler(method.messageSends[i]);
|
|
|
- };
|
|
|
- };
|
|
|
+ }
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
st.removeMethod = function(method) {
|
|
@@ -517,12 +509,12 @@ function Smalltalk(){
|
|
|
for(var i=0; i<klass.methods; i++) {
|
|
|
if(klass.methods[i].category == protocol) {
|
|
|
shouldDeleteProtocol = true;
|
|
|
- };
|
|
|
- };
|
|
|
- if(shouldDeleteProtocol) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(shouldDeleteProtocol) {
|
|
|
klass.organization.elements.removeElement(protocol);
|
|
|
- };
|
|
|
- };
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
/* Handles unhandled errors during message sends */
|
|
|
|
|
@@ -557,7 +549,7 @@ function Smalltalk(){
|
|
|
} else {
|
|
|
return messageNotUnderstood(receiver, selector, args);
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
st.withContext = function(fn, receiver, selector, args) {
|
|
|
if(st.thisContext) {
|
|
@@ -581,15 +573,14 @@ function Smalltalk(){
|
|
|
var result = fn();
|
|
|
popContext(context);
|
|
|
return result;
|
|
|
- };
|
|
|
-
|
|
|
+ }
|
|
|
|
|
|
/* Handles Smalltalk errors. Triggers the registered ErrorHandler
|
|
|
(See the Smalltalk class ErrorHandler and its subclasses */
|
|
|
|
|
|
function handleError(error) {
|
|
|
smalltalk.ErrorHandler._current()._handleError_(error);
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
/* Handles #dnu: *and* JavaScript method calls.
|
|
|
if the receiver has no klass, we consider it a JS object (outside of the
|
|
@@ -609,7 +600,7 @@ function Smalltalk(){
|
|
|
._selector_(st.convertSelector(selector))
|
|
|
._arguments_(args)
|
|
|
);
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
/* Call a method of a JS object, or answer a property if it exists.
|
|
|
Else try wrapping a JSObjectProxy around the receiver.
|
|
@@ -639,8 +630,7 @@ function Smalltalk(){
|
|
|
}
|
|
|
|
|
|
return st.send(st.JSObjectProxy._on_(receiver), selector, args);
|
|
|
- };
|
|
|
-
|
|
|
+ }
|
|
|
|
|
|
/* Reuse one old context stored in oldContext */
|
|
|
|
|
@@ -657,8 +647,9 @@ function Smalltalk(){
|
|
|
|
|
|
function pushContext(receiver, selector, temps) {
|
|
|
var c = st.oldContext, tc = st.thisContext;
|
|
|
- if (!c) {
|
|
|
+ if(!c) {
|
|
|
return st.thisContext = new SmalltalkMethodContext(receiver, selector, temps, tc);
|
|
|
+
|
|
|
}
|
|
|
st.oldContext = null;
|
|
|
c.homeContext = tc;
|
|
@@ -667,15 +658,15 @@ function Smalltalk(){
|
|
|
c.selector = selector || "";
|
|
|
c.temps = temps || {};
|
|
|
return st.thisContext = c;
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
function popContext(context) {
|
|
|
st.thisContext = context.homeContext;
|
|
|
context.homeContext = undefined;
|
|
|
st.oldContext = context;
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
- /* Convert a Smalltalk selector into a JS selector */
|
|
|
+ /* Convert a Smalltalk selector into a JS selector */
|
|
|
|
|
|
st.selector = function(string) {
|
|
|
var selector = '_' + string;
|
|
@@ -710,7 +701,7 @@ function Smalltalk(){
|
|
|
|
|
|
function convertKeywordSelector(selector) {
|
|
|
return selector.replace(/^_/, '').replace(/_/g, ':');
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
function convertBinarySelector(selector) {
|
|
|
return selector
|
|
@@ -753,19 +744,19 @@ function Smalltalk(){
|
|
|
/* Boolean assertion */
|
|
|
|
|
|
st.assert = function(boolean) {
|
|
|
- if(boolean.klass === smalltalk.Boolean) {
|
|
|
- return boolean;
|
|
|
- } else {
|
|
|
- smalltalk.NonBooleanReceiver._new()._object_(boolean)._signal();
|
|
|
- }
|
|
|
- }
|
|
|
+ if(boolean.klass === smalltalk.Boolean) {
|
|
|
+ return boolean;
|
|
|
+ } else {
|
|
|
+ smalltalk.NonBooleanReceiver._new()._object_(boolean)._signal();
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
/* Smalltalk initialization. Called on page load */
|
|
|
|
|
|
st.initialize = function() {
|
|
|
- if(initialized) {return false};
|
|
|
+ if(initialized) {return false}
|
|
|
|
|
|
- classes.forEach(function(klass) {
|
|
|
+ classes.forEach(function(klass) {
|
|
|
st.init(klass);
|
|
|
});
|
|
|
classes.forEach(function(klass) {
|
|
@@ -774,10 +765,9 @@ function Smalltalk(){
|
|
|
|
|
|
initialized = true;
|
|
|
};
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
-Smalltalk.prototype = new SmalltalkObject();
|
|
|
-Smalltalk.prototype.constructor = Smalltalk;
|
|
|
+inherits(Smalltalk, SmalltalkObject);
|
|
|
|
|
|
function SmalltalkMethodContext(receiver, selector, temps, home) {
|
|
|
this.receiver = receiver;
|
|
@@ -793,8 +783,7 @@ function SmalltalkMethodContext(receiver, selector, temps, home) {
|
|
|
// };
|
|
|
};
|
|
|
|
|
|
-SmalltalkMethodContext.prototype = new SmalltalkObject();
|
|
|
-SmalltalkMethodContext.prototype.constructor = SmalltalkMethodContext;
|
|
|
+inherits(SmalltalkMethodContext, SmalltalkObject);
|
|
|
|
|
|
SmalltalkMethodContext.prototype.copy = function() {
|
|
|
var home = this.homeContext;
|
|
@@ -822,10 +811,10 @@ var smalltalk = new Smalltalk();
|
|
|
*/
|
|
|
|
|
|
var _st = function(o) {
|
|
|
- if(typeof o === 'undefined') {return nil};
|
|
|
- if(o.klass) {return o};
|
|
|
- return smalltalk.JSObjectProxy._on_(o);
|
|
|
-};
|
|
|
+ if(typeof o === 'undefined') {return nil}
|
|
|
+ if(o.klass) {return o}
|
|
|
+ return smalltalk.JSObjectProxy._on_(o);
|
|
|
+};
|
|
|
|
|
|
|
|
|
/***************************************** BOOTSTRAP ******************************************/
|