'From Moshi of 3 March 2007 [latest update: #275] on 25 September 2007 at 11:15:27 am'! !JSObject class methodsFor: 'as yet unclassified' stamp: 'tak 9/20/2007 22:45'! helpInitialize "self helpInitialize" self eval: ' Object.prototype.help = "This object has no help message." Boolean.prototype.help = "The boolean object is logical value. Example: (!!true && !!true) == !!(true || true)" Number.prototype.help = "This is a number object." null.help = "A special keyword denoting a null value" undefined.help = "A variable that has not been assigned a value is of type undefined. A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value." Function.help = "Function is an executable code. You can execute this value with parenthesis. Example: var func = function (x) {alert(''Hello '' + x)}; func(''Alex'')" Function.prototype.help = "This function has no help message." Object.prototype.printString.help = "Returns a programer friendly string representing the object. Example: {first: 1, second: 2}.printString() See also: this.toString.help" Object.prototype.toString.help = "Returns a string representing the object. Example: {first: 1, second: 2}.toString() See also: this.printString.help" '.! ! !JSObject class methodsFor: 'as yet unclassified' stamp: 'tak 9/19/2007 17:44'! initialize " JSObject initialize " | identityConstructor identityConstructorFactory arrayConstructor | JSParser initialize. ObjectProto := JSObjectProto new. Global := JSGlobalProto new. FunctionProto := ObjectProto makeChild. FunctionProto jsAt: #apply put: (self functionWithEnv: Global args: #(thisArg argArray) body: [:ctxt | | f args | f := ctxt jsAt: #this. args := ctxt jsAt: #argArray. args == Undefined ifTrue: [args := ArrayProto makeChild]. (f jsAt: #'__body__') copy fixTemps value: ((f createActivationRecord: args jsArrayValues) at: #this put: (ctxt jsAt: #thisArg); yourself) ]); jsAt: #call put: (self functionWithEnv: Global args: #(thisArg) body: [:ctxt | | f args | f := ctxt jsAt: #this. args := ctxt jsAt: #arguments. (f jsAt: #'__body__') copy fixTemps value: ((f createActivationRecord: (args copyFrom: 2 to: args size)) at: #this put: (ctxt jsAt: #thisArg); yourself) ]). ObjectProto at: #'__proto__' put: nil; bridgeSqueakMethod: #~= as: #!!=; bridgeSqueakMethod: #= as: #==; bridgeSqueakMethod: #== as: #===; bridgeSqueakMethod: #~== as: #!!==; jsAt: #!! put: (self functionWithEnv: Global args: #() body: [:ctxt | ((ctxt jsAt: #this) jsSend: #'__toBoolean__' withArguments: #()) not]); jsAt: #'__localProperties__' put: (self functionWithEnv: Global args: #() body: [:ctxt | (ctxt jsAt: #this) keys asArray]). Undefined := ObjectProto makeChild. Global at: #undefined put: Undefined; at: #toString put: (self functionWithEnv: Global args: #() body: [:ctxt | '[Global]']); at: #printString put: (self functionWithEnv: Global args: #() body: [:ctxt | (ObjectProto jsAt: #printString) jsSend: #call withArguments: {ctxt jsAt: #this}]). NumberProto := JSBuiltInProto new at: #'__proto__' put: 0; jsAt: #toString put: (self functionWithEnv: Global args: #() body: [:ctxt | (ctxt jsAt: #this) asString]); jsAt: #toFixed put: (self functionWithEnv: Global args: #(n) body: [:ctxt | | n | n := (ctxt jsAt: #n). n == Undefined ifTrue: [n := 0]. (ctxt jsAt: #this) printShowingDecimalPlaces: n ]); bridgeSqueakMethod: #+ as: #+; bridgeSqueakMethod: #- as: #-; bridgeSqueakMethod: #* as: #*; bridgeSqueakMethod: #/ as: #/; bridgeSqueakMethod: #\\ as: #%; bridgeSqueakMethod: #> as: #>; bridgeSqueakMethod: #>= as: #>=; bridgeSqueakMethod: #< as: #<; bridgeSqueakMethod: #<= as: #<=; yourself. StringProto := JSBuiltInProto new at: #'__proto__' put: ''; jsAt: #toString put: (self functionWithEnv: Global args: #() body: [:ctxt | ctxt jsAt: #this]); jsAt: #=== put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #this) jsSend: #== withArguments: {ctxt jsAt: #x}]); jsAt: #charCodeAt put: (self functionWithEnv: Global args: #() body: [:ctxt | ((ctxt jsAt: #this) jsSend: #charAt withArguments: #(0)) first asciiValue ]); bridgeSqueakMethod: #, as: #+; yourself. NullProto := ObjectProto makeChild. BooleanProto := ObjectProto makeChild jsAt: #toString put: (self functionWithEnv: Global args: #() body: [:ctxt | (ctxt jsAt: #this) printString]); yourself. identityConstructor := self functionWithEnv: Global args: #(x) body: [:ctxt | ctxt jsAt: #this put: (ctxt jsAt: #x)]. identityConstructorFactory := [:c | identityConstructor copy at: #prototype put: c; yourself]. arrayConstructor := self functionWithEnv: Global args: #() body: [:ctxt | | this arguments | this := ctxt jsAt: #this. arguments := ctxt jsAt: #arguments. arguments size == 0 ifTrue: [this jsAt: #length put: 0]. arguments size == 1 ifTrue: [ arguments first isInteger ifTrue: [this jsAt: #length put: arguments first] ifFalse: [this jsAt: 0 put: arguments first] ]. (arguments size > 1) ifTrue: [ arguments withIndexDo: [:a :i | this jsAt: i - 1 put: a] ]. ]. ArrayProto := JSArray new at: #length put: 0; jsAt: #'__proto__' put: ObjectProto; yourself. arrayConstructor jsAt: #prototype put: ArrayProto. Global jsAt: #null put: nil; jsAt: #true put: true; jsAt: #false put: false; jsAt: #Infinity put: Float infinity; jsAt: #usleep put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (Delay forMilliseconds: (ctxt jsAt: #x)) wait]); jsAt: #alert put: (self functionWithEnv: Global args: #(x) body: [:ctxt | nil inform: ((ctxt at: #x) jsSend: #toString withArguments: #())]); jsAt: #print put: (self functionWithEnv: Global args: #(x) body: [:ctxt | Transcript show: ((ctxt at: #x) jsSend: #toString withArguments: #())]); jsAt: #eval put: (self functionWithEnv: Global args: #(x) body: [:ctxt | JSObject eval: ((ctxt at: #x) jsSend: #toString withArguments: #())]); jsAt: #Object put: ((self functionWithEnv: Global args: #() body: [:ctxt | nil]) at: #prototype put: ObjectProto; yourself); jsAt: #Function put: ((self functionWithEnv: Global args: #() body: [:ctxt | nil]) at: #prototype put: FunctionProto; yourself); jsAt: #Boolean put: ((self functionWithEnv: Global args: #() body: [:ctxt | nil]) at: #prototype put: BooleanProto; yourself); jsAt: #Number put: (identityConstructorFactory value: 0); jsAt: #String put: (identityConstructorFactory value: ''); jsAt: #Array put: arrayConstructor; jsAt: #Math put: ( ObjectProto makeChild jsAt: #pi put: Float pi; jsAt: #abs put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #x) abs]); jsAt: #sin put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #x) sin]); jsAt: #cos put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #x) cos]); jsAt: #tan put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #x) tan]); jsAt: #atan2 put: (self functionWithEnv: Global args: #(x y) body: [:ctxt | (ctxt jsAt: #x) arcTan: (ctxt jsAt: #y)]); jsAt: #floor put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #x) floor]); jsAt: #round put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #x) rounded]); jsAt: #sqrt put: (self functionWithEnv: Global args: #(x) body: [:ctxt | (ctxt jsAt: #x) sqrt]); jsAt: #'__random__' put: Random new; jsAt: #random put: (self functionWithEnv: Global args: #() body: [:ctxt | ((ctxt jsAt: #Math) jsAt: #'__random__') next]); yourself ); yourself. self eval: ' Object.prototype.__toBoolean__ = function() { return true; } Boolean.prototype.__toBoolean__ = function() { return this; } Number.prototype.__toBoolean__ = function() { return this !!= 0; } null.__toBoolean__ = function() { return false; } undefined.__toBoolean__ = function() { return false; } Object.prototype["&&"] = function(thatThunk) { return this.__toBoolean__() ? thatThunk().__toBoolean__() : false } Object.prototype["||"] = function(thatThunk) { return this.__toBoolean__() ? true : thatThunk().__toBoolean__() } undefined.toString = function() { return "undefined" } null.toString = function() { return "null" } Object.prototype.toString = function() { return "[object Object]" } Function.prototype.toString = function() { return this.__code__ } Array.prototype.genericPrint = function(m) { var first = true, r = "[" for (var idx in this) { if (first) first = false else r = r + ", " r = r + this[idx].perform(m) } return r + "]" } Array.prototype.toString = function() { return this.genericPrint("toString") } justToString = function() { return this.toString() } undefined.printString = justToString null.printString = justToString Object.prototype.printString = function() { var first = true, r = "{" for (var idx in this) { if (first) first = false else r = r + ", " r = r + idx.toString() + ": " + this[idx].printString() } return r + "}" } Number.prototype.printString = justToString Boolean.prototype.printString = justToString String.prototype.printString = function() { var r = "\"" for (var idx in this) switch (this[idx]) { case "\r": r += "\\r"; break; case "\n": r += "\\n"; break; case "\t": r += "\\t"; break; case "\"": r += "\\\""; break; case "\\": r += "\\\\"; break; default: r += this[idx] } return r + "\"" } Function.prototype.printString = justToString Array.prototype.printString = function() { return this.genericPrint("printString") } Array.__with__ = function(x) { var r = new Array() r[0] = x return r } Function.prototype.__hasInstance__ = function(x) { while (x !!= null && x !!= undefined) { if (x.__proto__ == this.prototype) return true // kludge required for Number and String if (x.__proto__ == x) return this == Object x = x.__proto__ } // the standard states that null is not an instance of anything return false } Object.prototype.perform = function(m, args) { return this[m].apply(this, args) } Object.prototype["+"] = function(that) { return this.toString() + that.toString() } Array.prototype.map = function(f) { var r = [] for (var idx in this) r[idx] = f(this[idx]) return r } Array.prototype.reduce = function(f, z) { var r = z for (var idx in this) r = f(r, this[idx]) return r } Array.prototype.push = function(x) { this[this.length] = x } Array.prototype.pop = function() { var ans = this[this.length - 1] this.length = this.length - 1 return ans } String.prototype.charAt = function(idx) { return this[idx] } Math.min = function() { var ans = Infinity for (var idx in arguments) if (arguments[idx] < ans) ans = arguments[idx] return ans } Math.max = function() { var ans = -Infinity for (var idx in arguments) if (arguments[idx] > ans) ans = arguments[idx] return ans } Math.randomInt = function(n) { return Math.round(Math.random() * (n - 1)) } '.! ! JSObject initialize!