Browse Source

Makes JSObjectProxy a subclass of AbstractProxy

Nicolas Petton 11 years ago
parent
commit
a3110cb681
6 changed files with 1265 additions and 935 deletions
  1. 1002 730
      js/Kernel-Infrastructure.js
  2. 6 24
      js/Kernel-Objects.js
  3. 2 8
      js/Kernel-Tests.js
  4. 250 161
      st/Kernel-Infrastructure.st
  5. 5 11
      st/Kernel-Objects.st
  6. 0 1
      st/Kernel-Tests.st

+ 1002 - 730
js/Kernel-Infrastructure.js

@@ -2,1153 +2,1425 @@ define("amber_core/Kernel-Infrastructure", ["amber_vm/smalltalk", "amber_vm/nil"
 smalltalk.addPackage('Kernel-Infrastructure');
 smalltalk.packages["Kernel-Infrastructure"].transport = {"type":"amd","amdNamespace":"amber_core"};
 
-smalltalk.addClass('InspectorHandler', smalltalk.Object, [], 'Kernel-Infrastructure');
-smalltalk.InspectorHandler.comment="I am responsible for inspecting object.\x0a\x0aMy class-side `inspector` inst var holds the current inspector I'm delegating object inspection to.\x0a\x0aThe default inspector object is the transcript.";
-
-smalltalk.InspectorHandler.klass.iVarNames = ['inspector'];
+smalltalk.addClass('AbstractProxy', smalltalk.nil, [], 'Kernel-Infrastructure');
+smalltalk.AbstractProxy.comment="I provide a basic set of methods for proxies handling `#doesNotUnderstand:` so that inspectors, debuggers, etc. won't fail.";
 smalltalk.addMethod(
 smalltalk.method({
-selector: "inspect:",
-category: 'registration',
-fn: function (anObject){
+selector: "asString",
+category: 'converting',
+fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(self._inspector())._inspect_(anObject);
+$1=self._printString();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"inspect:",{anObject:anObject},smalltalk.InspectorHandler.klass)})},
-args: ["anObject"],
-source: "inspect: anObject\x0a\x09^ self inspector inspect: anObject",
-messageSends: ["inspect:", "inspector"],
+}, function($ctx1) {$ctx1.fill(self,"asString",{},smalltalk.AbstractProxy)})},
+args: [],
+source: "asString\x0a\x09^ self printString",
+messageSends: ["printString"],
 referencedClasses: []
 }),
-smalltalk.InspectorHandler.klass);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "inspector",
+selector: "class",
 category: 'accessing',
 fn: function (){
 var self=this;
-function $Transcript(){return smalltalk.Transcript||(typeof Transcript=="undefined"?nil:Transcript)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self["@inspector"];
-if(($receiver = $2) == nil || $receiver == null){
-self["@inspector"]=$Transcript();
-$1=self["@inspector"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"inspector",{},smalltalk.InspectorHandler.klass)})},
+return self.klass;
+return self}, function($ctx1) {$ctx1.fill(self,"class",{},smalltalk.AbstractProxy)})},
 args: [],
-source: "inspector\x0a\x09^ inspector ifNil: [ inspector := Transcript ]",
-messageSends: ["ifNil:"],
-referencedClasses: ["Transcript"]
+source: "class\x0a\x09<return self.klass>",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.InspectorHandler.klass);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "register:",
-category: 'registration',
-fn: function (anInspector){
+selector: "doesNotUnderstand:",
+category: 'error handling',
+fn: function (aMessage){
 var self=this;
+function $MessageNotUnderstood(){return smalltalk.MessageNotUnderstood||(typeof MessageNotUnderstood=="undefined"?nil:MessageNotUnderstood)}
 return smalltalk.withContext(function($ctx1) { 
-self["@inspector"]=anInspector;
-return self}, function($ctx1) {$ctx1.fill(self,"register:",{anInspector:anInspector},smalltalk.InspectorHandler.klass)})},
-args: ["anInspector"],
-source: "register: anInspector\x0a\x09inspector := anInspector",
+var $1,$2;
+$1=_st($MessageNotUnderstood())._new();
+_st($1)._receiver_(self);
+_st($1)._message_(aMessage);
+$2=_st($1)._signal();
+return self}, function($ctx1) {$ctx1.fill(self,"doesNotUnderstand:",{aMessage:aMessage},smalltalk.AbstractProxy)})},
+args: ["aMessage"],
+source: "doesNotUnderstand: aMessage\x0a\x09MessageNotUnderstood new\x0a\x09\x09receiver: self;\x0a\x09\x09message: aMessage;\x0a\x09\x09signal",
+messageSends: ["receiver:", "new", "message:", "signal"],
+referencedClasses: ["MessageNotUnderstood"]
+}),
+smalltalk.AbstractProxy);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "identityHash",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+
+		var hash=self.identityHash;
+		if (hash) return hash;
+		hash=smalltalk.nextId();
+		Object.defineProperty(self, 'identityHash', {value:hash});
+		return hash;
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"identityHash",{},smalltalk.AbstractProxy)})},
+args: [],
+source: "identityHash\x0a\x09<\x0a\x09\x09var hash=self.identityHash;\x0a\x09\x09if (hash) return hash;\x0a\x09\x09hash=smalltalk.nextId();\x0a\x09\x09Object.defineProperty(self, 'identityHash', {value:hash});\x0a\x09\x09return hash;\x0a\x09>",
 messageSends: [],
 referencedClasses: []
 }),
-smalltalk.InspectorHandler.klass);
+smalltalk.AbstractProxy);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initialize",
+category: 'initialization',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return self}, function($ctx1) {$ctx1.fill(self,"initialize",{},smalltalk.AbstractProxy)})},
+args: [],
+source: "initialize",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AbstractProxy);
 
-smalltalk.addClass('InterfacingObject', smalltalk.Object, [], 'Kernel-Infrastructure');
-smalltalk.InterfacingObject.comment="I am superclass of all object that interface with user or environment. `Widget` and a few other classes are subclasses of me. I delegate all of the above APIs to `PlatformInterface`.\x0a\x0a## API\x0a\x0a    self alert: 'Hey, there is a problem'.\x0a    self confirm: 'Affirmative?'.\x0a    self prompt: 'Your name:'.\x0a\x0a    self ajax: #{\x0a        'url' -> '/patch.js'. 'type' -> 'GET'. dataType->'script'\x0a    }.";
 smalltalk.addMethod(
 smalltalk.method({
-selector: "ajax:",
-category: 'actions',
-fn: function (anObject){
+selector: "inspect",
+category: 'inspecting',
+fn: function (){
 var self=this;
-function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
+function $InspectorHandler(){return smalltalk.InspectorHandler||(typeof InspectorHandler=="undefined"?nil:InspectorHandler)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st($PlatformInterface())._ajax_(anObject);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"ajax:",{anObject:anObject},smalltalk.InterfacingObject)})},
-args: ["anObject"],
-source: "ajax: anObject\x0a\x09^ PlatformInterface ajax: anObject",
-messageSends: ["ajax:"],
-referencedClasses: ["PlatformInterface"]
+_st($InspectorHandler())._inspect_(self);
+return self}, function($ctx1) {$ctx1.fill(self,"inspect",{},smalltalk.AbstractProxy)})},
+args: [],
+source: "inspect\x0a\x09InspectorHandler inspect: self",
+messageSends: ["inspect:"],
+referencedClasses: ["InspectorHandler"]
 }),
-smalltalk.InterfacingObject);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "alert:",
-category: 'actions',
-fn: function (aString){
+selector: "inspectOn:",
+category: 'inspecting',
+fn: function (anInspector){
 var self=this;
-function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st($PlatformInterface())._alert_(aString);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"alert:",{aString:aString},smalltalk.InterfacingObject)})},
-args: ["aString"],
-source: "alert: aString\x0a\x09^ PlatformInterface alert: aString",
-messageSends: ["alert:"],
-referencedClasses: ["PlatformInterface"]
+return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector},smalltalk.AbstractProxy)})},
+args: ["anInspector"],
+source: "inspectOn: anInspector",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.InterfacingObject);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "confirm:",
-category: 'actions',
+selector: "instVarAt:",
+category: 'accessing',
 fn: function (aString){
 var self=this;
-function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st($PlatformInterface())._confirm_(aString);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"confirm:",{aString:aString},smalltalk.InterfacingObject)})},
+ return self['@'+aString] ;
+return self}, function($ctx1) {$ctx1.fill(self,"instVarAt:",{aString:aString},smalltalk.AbstractProxy)})},
 args: ["aString"],
-source: "confirm: aString\x0a\x09^ PlatformInterface confirm: aString",
-messageSends: ["confirm:"],
-referencedClasses: ["PlatformInterface"]
+source: "instVarAt: aString\x0a\x09< return self['@'+aString] >",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.InterfacingObject);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "prompt:",
-category: 'actions',
+selector: "instVarAt:put:",
+category: 'accessing',
+fn: function (aString,anObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+ self['@' + aString] = anObject ;
+return self}, function($ctx1) {$ctx1.fill(self,"instVarAt:put:",{aString:aString,anObject:anObject},smalltalk.AbstractProxy)})},
+args: ["aString", "anObject"],
+source: "instVarAt: aString put: anObject\x0a\x09< self['@' + aString] = anObject >",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.AbstractProxy);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "perform:",
+category: 'message handling',
 fn: function (aString){
 var self=this;
-function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st($PlatformInterface())._prompt_(aString);
+$1=self._perform_withArguments_(aString,[]);
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"prompt:",{aString:aString},smalltalk.InterfacingObject)})},
+}, function($ctx1) {$ctx1.fill(self,"perform:",{aString:aString},smalltalk.AbstractProxy)})},
 args: ["aString"],
-source: "prompt: aString\x0a\x09^ PlatformInterface prompt: aString",
-messageSends: ["prompt:"],
-referencedClasses: ["PlatformInterface"]
+source: "perform: aString\x0a\x09^ self perform: aString withArguments: #()",
+messageSends: ["perform:withArguments:"],
+referencedClasses: []
 }),
-smalltalk.InterfacingObject);
+smalltalk.AbstractProxy);
 
-
-
-smalltalk.addClass('Environment', smalltalk.InterfacingObject, [], 'Kernel-Infrastructure');
-smalltalk.Environment.comment="I provide an unified entry point to manipulate Amber packages, classes and methods.\x0a\x0aTypical use cases include IDEs, remote access and restricting browsing.";
 smalltalk.addMethod(
 smalltalk.method({
-selector: "addInstVarNamed:to:",
-category: 'compiling',
-fn: function (aString,aClass){
+selector: "perform:withArguments:",
+category: 'message handling',
+fn: function (aString,aCollection){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2,$3,$4,$5;
-$1=self._classBuilder();
-$2=_st(aClass)._superclass();
-$3=_st(aClass)._name();
-$ctx1.sendIdx["name"]=1;
-$4=_st(_st(aClass)._instanceVariableNames())._copy();
-_st($4)._add_(aString);
-$5=_st($4)._yourself();
-_st($1)._addSubclassOf_named_instanceVariableNames_package_($2,$3,$5,_st(_st(aClass)._package())._name());
-return self}, function($ctx1) {$ctx1.fill(self,"addInstVarNamed:to:",{aString:aString,aClass:aClass},smalltalk.Environment)})},
-args: ["aString", "aClass"],
-source: "addInstVarNamed: aString to: aClass\x0a\x09self classBuilder\x0a\x09\x09addSubclassOf: aClass superclass \x0a\x09\x09named: aClass name \x0a\x09\x09instanceVariableNames: (aClass instanceVariableNames copy add: aString; yourself)\x0a\x09\x09package: aClass package name",
-messageSends: ["addSubclassOf:named:instanceVariableNames:package:", "classBuilder", "superclass", "name", "add:", "copy", "instanceVariableNames", "yourself", "package"],
+return smalltalk.send(self, aString._asSelector(), aCollection);
+return self}, function($ctx1) {$ctx1.fill(self,"perform:withArguments:",{aString:aString,aCollection:aCollection},smalltalk.AbstractProxy)})},
+args: ["aString", "aCollection"],
+source: "perform: aString withArguments: aCollection\x0a\x09<return smalltalk.send(self, aString._asSelector(), aCollection)>",
+messageSends: [],
 referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "allSelectors",
-category: 'accessing',
-fn: function (){
+selector: "printOn:",
+category: 'printing',
+fn: function (aStream){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(_st($Smalltalk())._current())._at_("allSelectors"))._value();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"allSelectors",{},smalltalk.Environment)})},
-args: [],
-source: "allSelectors\x0a\x09^ (Smalltalk current at: 'allSelectors') value",
-messageSends: ["value", "at:", "current"],
-referencedClasses: ["Smalltalk"]
+var $5,$4,$3,$2,$1;
+$5=self._class();
+$ctx1.sendIdx["class"]=1;
+$4=_st($5)._name();
+$ctx1.sendIdx["name"]=1;
+$3=_st($4)._first();
+$2=_st($3)._isVowel();
+if(smalltalk.assert($2)){
+$1="an ";
+} else {
+$1="a ";
+};
+_st(aStream)._nextPutAll_($1);
+$ctx1.sendIdx["nextPutAll:"]=1;
+_st(aStream)._nextPutAll_(_st(self._class())._name());
+return self}, function($ctx1) {$ctx1.fill(self,"printOn:",{aStream:aStream},smalltalk.AbstractProxy)})},
+args: ["aStream"],
+source: "printOn: aStream\x0a\x09aStream nextPutAll: (self class name first isVowel\x0a\x09\x09ifTrue: [ 'an ' ]\x0a\x09\x09ifFalse: [ 'a ' ]).\x0a\x09aStream nextPutAll: self class name",
+messageSends: ["nextPutAll:", "ifTrue:ifFalse:", "isVowel", "first", "name", "class"],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "availableClassNames",
-category: 'accessing',
+selector: "printString",
+category: 'printing',
 fn: function (){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+function $String(){return smalltalk.String||(typeof String=="undefined"?nil:String)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(_st(_st($Smalltalk())._current())._classes())._collect_((function(each){
+$1=_st($String())._streamContents_((function(str){
 return smalltalk.withContext(function($ctx2) {
-return _st(each)._name();
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return self._printOn_(str);
+}, function($ctx2) {$ctx2.fillBlock({str:str},$ctx1,1)})}));
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"availableClassNames",{},smalltalk.Environment)})},
+}, function($ctx1) {$ctx1.fill(self,"printString",{},smalltalk.AbstractProxy)})},
 args: [],
-source: "availableClassNames\x0a\x09^ Smalltalk current classes \x0a\x09\x09collect: [ :each | each name ]",
-messageSends: ["collect:", "classes", "current", "name"],
-referencedClasses: ["Smalltalk"]
+source: "printString\x0a\x09^ String streamContents: [ :str | \x0a\x09\x09self printOn: str ]",
+messageSends: ["streamContents:", "printOn:"],
+referencedClasses: ["String"]
 }),
-smalltalk.Environment);
+smalltalk.AbstractProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "availablePackageNames",
+selector: "yourself",
 category: 'accessing',
 fn: function (){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(_st(_st($Smalltalk())._current())._packages())._collect_((function(each){
-return smalltalk.withContext(function($ctx2) {
-return _st(each)._name();
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.Environment)})},
+return self;
+}, function($ctx1) {$ctx1.fill(self,"yourself",{},smalltalk.AbstractProxy)})},
 args: [],
-source: "availablePackageNames\x0a\x09^ Smalltalk current packages \x0a\x09\x09collect: [ :each | each name ]",
-messageSends: ["collect:", "packages", "current", "name"],
-referencedClasses: ["Smalltalk"]
+source: "yourself\x0a\x09^ self",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.AbstractProxy);
+
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "availableProtocolsFor:",
-category: 'accessing',
-fn: function (aClass){
+selector: "heliosClass",
+category: 'helios',
+fn: function (){
 var self=this;
-var protocols;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-protocols=_st(aClass)._protocols();
-$1=_st(aClass)._superclass();
-$ctx1.sendIdx["superclass"]=1;
-if(($receiver = $1) == nil || $receiver == null){
-$1;
-} else {
-_st(protocols)._addAll_(self._availableProtocolsFor_(_st(aClass)._superclass()));
-};
-$2=_st(_st(protocols)._asSet())._asArray();
-return $2;
-}, function($ctx1) {$ctx1.fill(self,"availableProtocolsFor:",{aClass:aClass,protocols:protocols},smalltalk.Environment)})},
-args: ["aClass"],
-source: "availableProtocolsFor: aClass\x0a\x09| protocols |\x0a\x09\x0a\x09protocols := aClass protocols.\x0a\x09aClass superclass ifNotNil: [ protocols addAll: (self availableProtocolsFor: aClass superclass) ].\x0a\x09^ protocols asSet asArray",
-messageSends: ["protocols", "ifNotNil:", "superclass", "addAll:", "availableProtocolsFor:", "asArray", "asSet"],
+return "class";
+}, function($ctx1) {$ctx1.fill(self,"heliosClass",{},smalltalk.AbstractProxy.klass)})},
+args: [],
+source: "heliosClass\x0a\x09^ 'class'",
+messageSends: [],
 referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.AbstractProxy.klass);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "classBuilder",
-category: 'accessing',
+selector: "initialize",
+category: 'initialization',
 fn: function (){
 var self=this;
-function $ClassBuilder(){return smalltalk.ClassBuilder||(typeof ClassBuilder=="undefined"?nil:ClassBuilder)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st($ClassBuilder())._new();
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"classBuilder",{},smalltalk.Environment)})},
+return self}, function($ctx1) {$ctx1.fill(self,"initialize",{},smalltalk.AbstractProxy.klass)})},
 args: [],
-source: "classBuilder\x0a\x09^ ClassBuilder new",
-messageSends: ["new"],
-referencedClasses: ["ClassBuilder"]
+source: "initialize",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.AbstractProxy.klass);
 
-smalltalk.addMethod(
+
+smalltalk.addClass('JSObjectProxy', smalltalk.AbstractProxy, ['jsObject'], 'Kernel-Infrastructure');
+smalltalk.JSObjectProxy.comment="I handle sending messages to JavaScript objects, making  JavaScript object accessing from Amber fully transparent.\x0aMy instances make intensive use of `#doesNotUnderstand:`.\x0a\x0aMy instances are automatically created by Amber whenever a message is sent to a JavaScript object.\x0a\x0a## Usage examples\x0a\x0aJSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.\x0a\x0a\x09window alert: 'hello world'.\x0a\x09window inspect.\x0a\x09(window jQuery: 'body') append: 'hello world'\x0a\x0aAmber messages sends are converted to JavaScript function calls or object property access _(in this order)_. If n one of them match, a `MessageNotUnderstood` error will be thrown.\x0a\x0a## Message conversion rules\x0a\x0a- `someUser name` becomes `someUser.name`\x0a- `someUser name: 'John'` becomes `someUser name = \x22John\x22`\x0a- `console log: 'hello world'` becomes `console.log('hello world')`\x0a- `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`\x0a\x0a__Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.";
+smalltalk.addMethod(
 smalltalk.method({
-selector: "classNamed:",
-category: 'accessing',
-fn: function (aString){
+selector: "addObjectVariablesTo:",
+category: 'proxy',
+fn: function (aDictionary){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=_st(_st($Smalltalk())._current())._at_(_st(aString)._asSymbol());
-if(($receiver = $2) == nil || $receiver == null){
-$1=self._error_("Invalid class name");
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"classNamed:",{aString:aString},smalltalk.Environment)})},
-args: ["aString"],
-source: "classNamed: aString\x0a\x09^ (Smalltalk current at: aString asSymbol)\x0a\x09\x09ifNil: [ self error: 'Invalid class name' ]",
-messageSends: ["ifNil:", "at:", "current", "asSymbol", "error:"],
-referencedClasses: ["Smalltalk"]
+
+		for(var i in self['@jsObject']) {
+			aDictionary._at_put_(i, self['@jsObject'][i]);
+		}
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"addObjectVariablesTo:",{aDictionary:aDictionary},smalltalk.JSObjectProxy)})},
+args: ["aDictionary"],
+source: "addObjectVariablesTo: aDictionary\x0a\x09<\x0a\x09\x09for(var i in self['@jsObject']) {\x0a\x09\x09\x09aDictionary._at_put_(i, self['@jsObject'][i]);\x0a\x09\x09}\x0a\x09>",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "classes",
-category: 'accessing',
+selector: "asJSON",
+category: 'enumerating',
 fn: function (){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(_st($Smalltalk())._current())._classes();
+$1=self["@jsObject"];
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"classes",{},smalltalk.Environment)})},
+}, function($ctx1) {$ctx1.fill(self,"asJSON",{},smalltalk.JSObjectProxy)})},
 args: [],
-source: "classes\x0a\x09^ Smalltalk current classes",
-messageSends: ["classes", "current"],
-referencedClasses: ["Smalltalk"]
+source: "asJSON\x0a\x09\x22Answers the receiver in a stringyfy-friendly fashion\x22\x0a\x0a\x09^ jsObject",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "commitPackage:",
-category: 'actions',
-fn: function (aPackage){
+selector: "at:",
+category: 'accessing',
+fn: function (aString){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(aPackage)._commit();
-return self}, function($ctx1) {$ctx1.fill(self,"commitPackage:",{aPackage:aPackage},smalltalk.Environment)})},
-args: ["aPackage"],
-source: "commitPackage: aPackage\x0a\x09aPackage commit",
-messageSends: ["commit"],
+return self['@jsObject'][aString];
+return self}, function($ctx1) {$ctx1.fill(self,"at:",{aString:aString},smalltalk.JSObjectProxy)})},
+args: ["aString"],
+source: "at: aString\x0a\x09<return self['@jsObject'][aString]>",
+messageSends: [],
 referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "compileClassComment:for:",
-category: 'compiling',
-fn: function (aString,aClass){
+selector: "at:ifAbsent:",
+category: 'accessing',
+fn: function (aString,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(aClass)._comment_(aString);
-return self}, function($ctx1) {$ctx1.fill(self,"compileClassComment:for:",{aString:aString,aClass:aClass},smalltalk.Environment)})},
-args: ["aString", "aClass"],
-source: "compileClassComment: aString for: aClass\x0a\x09aClass comment: aString",
-messageSends: ["comment:"],
+
+		var obj = self['@jsObject'];
+		return aString in obj ? obj[aString] : aBlock._value();
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"at:ifAbsent:",{aString:aString,aBlock:aBlock},smalltalk.JSObjectProxy)})},
+args: ["aString", "aBlock"],
+source: "at: aString ifAbsent: aBlock\x0a\x09\x22return the aString property or evaluate aBlock if the property is not defined on the object\x22\x0a\x09<\x0a\x09\x09var obj = self['@jsObject'];\x0a\x09\x09return aString in obj ? obj[aString] : aBlock._value();\x0a\x09>",
+messageSends: [],
 referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "compileClassDefinition:",
-category: 'compiling',
-fn: function (aString){
+selector: "at:ifPresent:",
+category: 'accessing',
+fn: function (aString,aBlock){
 var self=this;
-function $DoIt(){return smalltalk.DoIt||(typeof DoIt=="undefined"?nil:DoIt)}
 return smalltalk.withContext(function($ctx1) { 
-self._eval_on_(aString,_st($DoIt())._new());
-return self}, function($ctx1) {$ctx1.fill(self,"compileClassDefinition:",{aString:aString},smalltalk.Environment)})},
-args: ["aString"],
-source: "compileClassDefinition: aString\x0a\x09self eval: aString on: DoIt new",
-messageSends: ["eval:on:", "new"],
-referencedClasses: ["DoIt"]
+
+		var obj = self['@jsObject'];
+		return aString in obj ? aBlock._value_(obj[aString]) : nil;
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:",{aString:aString,aBlock:aBlock},smalltalk.JSObjectProxy)})},
+args: ["aString", "aBlock"],
+source: "at: aString ifPresent: aBlock\x0a\x09\x22return the evaluation of aBlock with the value if the property is defined or return nil\x22\x0a\x09<\x0a\x09\x09var obj = self['@jsObject'];\x0a\x09\x09return aString in obj ? aBlock._value_(obj[aString]) : nil;\x0a\x09>",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "compileMethod:for:protocol:",
-category: 'compiling',
-fn: function (sourceCode,class_,protocol){
+selector: "at:ifPresent:ifAbsent:",
+category: 'accessing',
+fn: function (aString,aBlock,anotherBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st(class_)._compile_category_(sourceCode,protocol);
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"compileMethod:for:protocol:",{sourceCode:sourceCode,class_:class_,protocol:protocol},smalltalk.Environment)})},
-args: ["sourceCode", "class", "protocol"],
-source: "compileMethod: sourceCode for: class protocol: protocol\x0a\x09^ class\x0a\x09\x09compile: sourceCode\x0a\x09\x09category: protocol",
-messageSends: ["compile:category:"],
+
+		var obj = self['@jsObject'];
+		return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:ifAbsent:",{aString:aString,aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.JSObjectProxy)})},
+args: ["aString", "aBlock", "anotherBlock"],
+source: "at: aString ifPresent: aBlock ifAbsent: anotherBlock\x0a\x09\x22return the evaluation of aBlock with the value if the property is defined\x0a\x09or return value of anotherBlock\x22\x0a\x09<\x0a\x09\x09var obj = self['@jsObject'];\x0a\x09\x09return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();\x0a\x09>",
+messageSends: [],
 referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "copyClass:to:",
-category: 'actions',
-fn: function (aClass,aClassName){
+selector: "at:put:",
+category: 'accessing',
+fn: function (aString,anObject){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
-function $ClassBuilder(){return smalltalk.ClassBuilder||(typeof ClassBuilder=="undefined"?nil:ClassBuilder)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st($Smalltalk())._current())._at_(aClassName);
-if(($receiver = $1) == nil || $receiver == null){
-$1;
-} else {
-$2=_st("A class named ".__comma(aClassName)).__comma(" already exists");
-$ctx1.sendIdx[","]=1;
-self._error_($2);
-};
-_st(_st($ClassBuilder())._new())._copyClass_named_(aClass,aClassName);
-return self}, function($ctx1) {$ctx1.fill(self,"copyClass:to:",{aClass:aClass,aClassName:aClassName},smalltalk.Environment)})},
-args: ["aClass", "aClassName"],
-source: "copyClass: aClass to: aClassName\x0a\x09(Smalltalk current at: aClassName)\x0a\x09\x09ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].\x0a\x09\x09\x0a\x09ClassBuilder new copyClass: aClass named: aClassName",
-messageSends: ["ifNotNil:", "at:", "current", "error:", ",", "copyClass:named:", "new"],
-referencedClasses: ["Smalltalk", "ClassBuilder"]
+self['@jsObject'][aString] = anObject;
+return self}, function($ctx1) {$ctx1.fill(self,"at:put:",{aString:aString,anObject:anObject},smalltalk.JSObjectProxy)})},
+args: ["aString", "anObject"],
+source: "at: aString put: anObject\x0a\x09<self['@jsObject'][aString] = anObject>",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "doItReceiver",
-category: 'accessing',
-fn: function (){
+selector: "doesNotUnderstand:",
+category: 'proxy',
+fn: function (aMessage){
 var self=this;
-function $DoIt(){return smalltalk.DoIt||(typeof DoIt=="undefined"?nil:DoIt)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=_st($DoIt())._new();
+var $2,$1;
+$2=self._lookupProperty_(_st(_st(aMessage)._selector())._asJavaScriptSelector());
+if(($receiver = $2) == nil || $receiver == null){
+$1=smalltalk.JSObjectProxy.superclass.fn.prototype._doesNotUnderstand_.apply(_st(self), [aMessage]);
+} else {
+var jsSelector;
+jsSelector=$receiver;
+$1=self._forwardMessage_withArguments_(jsSelector,_st(aMessage)._arguments());
+};
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"doItReceiver",{},smalltalk.Environment)})},
-args: [],
-source: "doItReceiver\x0a\x09^ DoIt new",
-messageSends: ["new"],
-referencedClasses: ["DoIt"]
+}, function($ctx1) {$ctx1.fill(self,"doesNotUnderstand:",{aMessage:aMessage},smalltalk.JSObjectProxy)})},
+args: ["aMessage"],
+source: "doesNotUnderstand: aMessage\x0a\x09^ (self lookupProperty: aMessage selector asJavaScriptSelector)\x0a\x09\x09ifNil: [ super doesNotUnderstand: aMessage ]\x0a\x09\x09ifNotNil: [ :jsSelector | \x0a\x09\x09\x09self \x0a\x09\x09\x09\x09forwardMessage: jsSelector \x0a\x09\x09\x09\x09withArguments: aMessage arguments ]",
+messageSends: ["ifNil:ifNotNil:", "lookupProperty:", "asJavaScriptSelector", "selector", "doesNotUnderstand:", "forwardMessage:withArguments:", "arguments"],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "eval:on:",
-category: 'actions',
-fn: function (aString,aReceiver){
+selector: "forwardMessage:withArguments:",
+category: 'proxy',
+fn: function (aString,anArray){
 var self=this;
-var compiler;
-function $Compiler(){return smalltalk.Compiler||(typeof Compiler=="undefined"?nil:Compiler)}
-function $Error(){return smalltalk.Error||(typeof Error=="undefined"?nil:Error)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-var $early={};
-try {
-compiler=_st($Compiler())._new();
-_st((function(){
-return smalltalk.withContext(function($ctx2) {
-return _st(compiler)._parseExpression_(aString);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._on_do_($Error(),(function(ex){
-return smalltalk.withContext(function($ctx2) {
-$1=self._alert_(_st(ex)._messageText());
-throw $early=[$1];
-}, function($ctx2) {$ctx2.fillBlock({ex:ex},$ctx1,2)})}));
-$2=_st(compiler)._evaluateExpression_on_(aString,aReceiver);
-return $2;
-}
-catch(e) {if(e===$early)return e[0]; throw e}
-}, function($ctx1) {$ctx1.fill(self,"eval:on:",{aString:aString,aReceiver:aReceiver,compiler:compiler},smalltalk.Environment)})},
-args: ["aString", "aReceiver"],
-source: "eval: aString on: aReceiver\x0a\x09| compiler |\x0a\x09compiler := Compiler new.\x0a\x09[ compiler parseExpression: aString ] on: Error do: [ :ex |\x0a\x09\x09^ self alert: ex messageText ].\x0a\x09^ compiler evaluateExpression: aString on: aReceiver",
-messageSends: ["new", "on:do:", "parseExpression:", "alert:", "messageText", "evaluateExpression:on:"],
-referencedClasses: ["Compiler", "Error"]
+
+		return smalltalk.send(self._jsObject(), aString, anArray);
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"forwardMessage:withArguments:",{aString:aString,anArray:anArray},smalltalk.JSObjectProxy)})},
+args: ["aString", "anArray"],
+source: "forwardMessage: aString withArguments: anArray\x0a\x09<\x0a\x09\x09return smalltalk.send(self._jsObject(), aString, anArray);\x0a\x09>",
+messageSends: [],
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "evaluate:on:do:",
-category: 'error handling',
-fn: function (aBlock,anErrorClass,exceptionBlock){
+selector: "inspectOn:",
+category: 'proxy',
+fn: function (anInspector){
 var self=this;
+var variables;
+function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-self._try_catch_(aBlock,(function(exception){
-return smalltalk.withContext(function($ctx2) {
-$1=_st(exception)._isKindOf_(self._classNamed_(_st(anErrorClass)._name()));
-if(smalltalk.assert($1)){
-return _st(exceptionBlock)._value_(exception);
-} else {
-return _st(exception)._signal();
-};
-}, function($ctx2) {$ctx2.fillBlock({exception:exception},$ctx1,1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"evaluate:on:do:",{aBlock:aBlock,anErrorClass:anErrorClass,exceptionBlock:exceptionBlock},smalltalk.Environment)})},
-args: ["aBlock", "anErrorClass", "exceptionBlock"],
-source: "evaluate: aBlock on: anErrorClass do: exceptionBlock\x0a\x09\x22Evaluate a block and catch exceptions happening on the environment stack\x22\x0a\x09\x0a\x09self try: aBlock catch: [ :exception | \x0a\x09\x09(exception isKindOf: (self classNamed: anErrorClass name))\x0a\x09\x09\x09ifTrue: [ exceptionBlock value: exception ]\x0a \x09\x09\x09ifFalse: [ exception signal ] ]",
-messageSends: ["try:catch:", "ifTrue:ifFalse:", "isKindOf:", "classNamed:", "name", "value:", "signal"],
+variables=_st($Dictionary())._new();
+_st(variables)._at_put_("#self",self._jsObject());
+_st(anInspector)._setLabel_(self._printString());
+self._addObjectVariablesTo_(variables);
+_st(anInspector)._setVariables_(variables);
+return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.JSObjectProxy)})},
+args: ["anInspector"],
+source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self jsObject.\x0a\x09anInspector setLabel: self printString.\x0a\x09self addObjectVariablesTo: variables.\x0a\x09anInspector setVariables: variables",
+messageSends: ["new", "at:put:", "jsObject", "setLabel:", "printString", "addObjectVariablesTo:", "setVariables:"],
+referencedClasses: ["Dictionary"]
+}),
+smalltalk.JSObjectProxy);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "jsObject",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@jsObject"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"jsObject",{},smalltalk.JSObjectProxy)})},
+args: [],
+source: "jsObject\x0a\x09^ jsObject",
+messageSends: [],
 referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.JSObjectProxy);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "jsObject:",
+category: 'accessing',
+fn: function (aJSObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@jsObject"]=aJSObject;
+return self}, function($ctx1) {$ctx1.fill(self,"jsObject:",{aJSObject:aJSObject},smalltalk.JSObjectProxy)})},
+args: ["aJSObject"],
+source: "jsObject: aJSObject\x0a\x09jsObject := aJSObject",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.JSObjectProxy);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "keysAndValuesDo:",
+category: 'enumerating',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+
+		var o = self['@jsObject'];
+		for(var i in o) {
+			aBlock._value_value_(i, o[i]);
+		}
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"keysAndValuesDo:",{aBlock:aBlock},smalltalk.JSObjectProxy)})},
+args: ["aBlock"],
+source: "keysAndValuesDo: aBlock\x0a\x09<\x0a\x09\x09var o = self['@jsObject'];\x0a\x09\x09for(var i in o) {\x0a\x09\x09\x09aBlock._value_value_(i, o[i]);\x0a\x09\x09}\x0a\x09>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.JSObjectProxy);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "lookupProperty:",
+category: 'accessing',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return aString in self._jsObject() ? aString : nil;
+return self}, function($ctx1) {$ctx1.fill(self,"lookupProperty:",{aString:aString},smalltalk.JSObjectProxy)})},
+args: ["aString"],
+source: "lookupProperty: aString\x0a\x09\x22Looks up a property in JS object.\x0a\x09Answer the property if it is present, or nil if it is not present.\x22\x0a\x09\x0a\x09<return aString in self._jsObject() ? aString : nil>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.JSObjectProxy);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "printOn:",
+category: 'printing',
+fn: function (aStream){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(aStream)._nextPutAll_(self._printString());
+return self}, function($ctx1) {$ctx1.fill(self,"printOn:",{aStream:aStream},smalltalk.JSObjectProxy)})},
+args: ["aStream"],
+source: "printOn: aStream\x0a\x09aStream nextPutAll: self printString",
+messageSends: ["nextPutAll:", "printString"],
+referencedClasses: []
+}),
+smalltalk.JSObjectProxy);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "printString",
+category: 'printing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+
+		var js = self['@jsObject'];
+		return js.toString
+			? js.toString()
+			: Object.prototype.toString.call(js)
+	;
+return self}, function($ctx1) {$ctx1.fill(self,"printString",{},smalltalk.JSObjectProxy)})},
+args: [],
+source: "printString\x0a\x09<\x0a\x09\x09var js = self['@jsObject'];\x0a\x09\x09return js.toString\x0a\x09\x09\x09? js.toString()\x0a\x09\x09\x09: Object.prototype.toString.call(js)\x0a\x09>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.JSObjectProxy);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "on:",
+category: 'instance creation',
+fn: function (aJSObject){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=self._new();
+_st($2)._jsObject_(aJSObject);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:",{aJSObject:aJSObject},smalltalk.JSObjectProxy.klass)})},
+args: ["aJSObject"],
+source: "on: aJSObject\x0a\x09^ self new\x0a\x09\x09jsObject: aJSObject;\x0a\x09\x09yourself",
+messageSends: ["jsObject:", "new", "yourself"],
+referencedClasses: []
+}),
+smalltalk.JSObjectProxy.klass);
+
+
+smalltalk.addClass('InspectorHandler', smalltalk.Object, [], 'Kernel-Infrastructure');
+smalltalk.InspectorHandler.comment="I am responsible for inspecting object.\x0a\x0aMy class-side `inspector` inst var holds the current inspector I'm delegating object inspection to.\x0a\x0aThe default inspector object is the transcript.";
+
+smalltalk.InspectorHandler.klass.iVarNames = ['inspector'];
 smalltalk.addMethod(
 smalltalk.method({
 selector: "inspect:",
-category: 'actions',
+category: 'registration',
 fn: function (anObject){
 var self=this;
-function $InspectorHandler(){return smalltalk.InspectorHandler||(typeof InspectorHandler=="undefined"?nil:InspectorHandler)}
 return smalltalk.withContext(function($ctx1) { 
-_st(_st($InspectorHandler())._inspector())._inspect_(anObject);
-return self}, function($ctx1) {$ctx1.fill(self,"inspect:",{anObject:anObject},smalltalk.Environment)})},
+var $1;
+$1=_st(self._inspector())._inspect_(anObject);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inspect:",{anObject:anObject},smalltalk.InspectorHandler.klass)})},
 args: ["anObject"],
-source: "inspect: anObject\x0a\x09InspectorHandler inspector inspect: anObject",
+source: "inspect: anObject\x0a\x09^ self inspector inspect: anObject",
 messageSends: ["inspect:", "inspector"],
-referencedClasses: ["InspectorHandler"]
+referencedClasses: []
 }),
-smalltalk.Environment);
+smalltalk.InspectorHandler.klass);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "moveClass:toPackage:",
-category: 'actions',
-fn: function (aClass,aPackageName){
+selector: "inspector",
+category: 'accessing',
+fn: function (){
 var self=this;
-var package_;
-function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
+function $Transcript(){return smalltalk.Transcript||(typeof Transcript=="undefined"?nil:Transcript)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-package_=_st($Package())._named_(aPackageName);
-$1=package_;
-if(($receiver = $1) == nil || $receiver == null){
-self._error_("Invalid package name");
+var $2,$1;
+$2=self["@inspector"];
+if(($receiver = $2) == nil || $receiver == null){
+self["@inspector"]=$Transcript();
+$1=self["@inspector"];
 } else {
-$1;
-};
-$2=_st(package_).__eq_eq(_st(aClass)._package());
-if(smalltalk.assert($2)){
-return self;
+$1=$2;
 };
-_st(aClass)._package_(package_);
-return self}, function($ctx1) {$ctx1.fill(self,"moveClass:toPackage:",{aClass:aClass,aPackageName:aPackageName,package_:package_},smalltalk.Environment)})},
-args: ["aClass", "aPackageName"],
-source: "moveClass: aClass toPackage: aPackageName\x0a\x09| package |\x0a\x09\x0a\x09package := Package named: aPackageName.\x0a\x09package ifNil: [ self error: 'Invalid package name' ].\x0a\x09package == aClass package ifTrue: [ ^ self ].\x0a\x09\x0a\x09aClass package: package",
-messageSends: ["named:", "ifNil:", "error:", "ifTrue:", "==", "package", "package:"],
-referencedClasses: ["Package"]
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inspector",{},smalltalk.InspectorHandler.klass)})},
+args: [],
+source: "inspector\x0a\x09^ inspector ifNil: [ inspector := Transcript ]",
+messageSends: ["ifNil:"],
+referencedClasses: ["Transcript"]
 }),
-smalltalk.Environment);
+smalltalk.InspectorHandler.klass);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "moveMethod:toClass:",
+selector: "register:",
+category: 'registration',
+fn: function (anInspector){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@inspector"]=anInspector;
+return self}, function($ctx1) {$ctx1.fill(self,"register:",{anInspector:anInspector},smalltalk.InspectorHandler.klass)})},
+args: ["anInspector"],
+source: "register: anInspector\x0a\x09inspector := anInspector",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.InspectorHandler.klass);
+
+
+smalltalk.addClass('InterfacingObject', smalltalk.Object, [], 'Kernel-Infrastructure');
+smalltalk.InterfacingObject.comment="I am superclass of all object that interface with user or environment. `Widget` and a few other classes are subclasses of me. I delegate all of the above APIs to `PlatformInterface`.\x0a\x0a## API\x0a\x0a    self alert: 'Hey, there is a problem'.\x0a    self confirm: 'Affirmative?'.\x0a    self prompt: 'Your name:'.\x0a\x0a    self ajax: #{\x0a        'url' -> '/patch.js'. 'type' -> 'GET'. dataType->'script'\x0a    }.";
+smalltalk.addMethod(
+smalltalk.method({
+selector: "ajax:",
 category: 'actions',
-fn: function (aMethod,aClassName){
+fn: function (anObject){
 var self=this;
-var destinationClass;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$4,$2;
-destinationClass=_st(_st($Smalltalk())._current())._at_(_st(aClassName)._asSymbol());
-$1=destinationClass;
-if(($receiver = $1) == nil || $receiver == null){
-self._error_("Invalid class name");
-} else {
-$1;
-};
-$3=destinationClass;
-$4=_st(aMethod)._methodClass();
-$ctx1.sendIdx["methodClass"]=1;
-$2=_st($3).__eq_eq($4);
-if(smalltalk.assert($2)){
-return self;
-};
-_st(destinationClass)._compile_category_(_st(aMethod)._source(),_st(aMethod)._protocol());
-_st(_st(aMethod)._methodClass())._removeCompiledMethod_(aMethod);
-return self}, function($ctx1) {$ctx1.fill(self,"moveMethod:toClass:",{aMethod:aMethod,aClassName:aClassName,destinationClass:destinationClass},smalltalk.Environment)})},
-args: ["aMethod", "aClassName"],
-source: "moveMethod: aMethod toClass: aClassName\x0a\x09| destinationClass |\x0a\x09\x0a\x09destinationClass := Smalltalk current at: aClassName asSymbol.\x0a\x09destinationClass ifNil: [ self error: 'Invalid class name' ].\x0a\x09destinationClass == aMethod methodClass ifTrue: [ ^ self ].\x0a\x09\x0a\x09destinationClass \x0a\x09\x09compile: aMethod source\x0a\x09\x09category: aMethod protocol.\x0a\x09aMethod methodClass \x0a\x09\x09removeCompiledMethod: aMethod",
-messageSends: ["at:", "current", "asSymbol", "ifNil:", "error:", "ifTrue:", "==", "methodClass", "compile:category:", "source", "protocol", "removeCompiledMethod:"],
+var $1;
+$1=_st($PlatformInterface())._ajax_(anObject);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"ajax:",{anObject:anObject},smalltalk.InterfacingObject)})},
+args: ["anObject"],
+source: "ajax: anObject\x0a\x09^ PlatformInterface ajax: anObject",
+messageSends: ["ajax:"],
+referencedClasses: ["PlatformInterface"]
+}),
+smalltalk.InterfacingObject);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "alert:",
+category: 'actions',
+fn: function (aString){
+var self=this;
+function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st($PlatformInterface())._alert_(aString);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"alert:",{aString:aString},smalltalk.InterfacingObject)})},
+args: ["aString"],
+source: "alert: aString\x0a\x09^ PlatformInterface alert: aString",
+messageSends: ["alert:"],
+referencedClasses: ["PlatformInterface"]
+}),
+smalltalk.InterfacingObject);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "confirm:",
+category: 'actions',
+fn: function (aString){
+var self=this;
+function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st($PlatformInterface())._confirm_(aString);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"confirm:",{aString:aString},smalltalk.InterfacingObject)})},
+args: ["aString"],
+source: "confirm: aString\x0a\x09^ PlatformInterface confirm: aString",
+messageSends: ["confirm:"],
+referencedClasses: ["PlatformInterface"]
+}),
+smalltalk.InterfacingObject);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "prompt:",
+category: 'actions',
+fn: function (aString){
+var self=this;
+function $PlatformInterface(){return smalltalk.PlatformInterface||(typeof PlatformInterface=="undefined"?nil:PlatformInterface)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st($PlatformInterface())._prompt_(aString);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"prompt:",{aString:aString},smalltalk.InterfacingObject)})},
+args: ["aString"],
+source: "prompt: aString\x0a\x09^ PlatformInterface prompt: aString",
+messageSends: ["prompt:"],
+referencedClasses: ["PlatformInterface"]
+}),
+smalltalk.InterfacingObject);
+
+
+
+smalltalk.addClass('Environment', smalltalk.InterfacingObject, [], 'Kernel-Infrastructure');
+smalltalk.Environment.comment="I provide an unified entry point to manipulate Amber packages, classes and methods.\x0a\x0aTypical use cases include IDEs, remote access and restricting browsing.";
+smalltalk.addMethod(
+smalltalk.method({
+selector: "addInstVarNamed:to:",
+category: 'compiling',
+fn: function (aString,aClass){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2,$3,$4,$5;
+$1=self._classBuilder();
+$2=_st(aClass)._superclass();
+$3=_st(aClass)._name();
+$ctx1.sendIdx["name"]=1;
+$4=_st(_st(aClass)._instanceVariableNames())._copy();
+_st($4)._add_(aString);
+$5=_st($4)._yourself();
+_st($1)._addSubclassOf_named_instanceVariableNames_package_($2,$3,$5,_st(_st(aClass)._package())._name());
+return self}, function($ctx1) {$ctx1.fill(self,"addInstVarNamed:to:",{aString:aString,aClass:aClass},smalltalk.Environment)})},
+args: ["aString", "aClass"],
+source: "addInstVarNamed: aString to: aClass\x0a\x09self classBuilder\x0a\x09\x09addSubclassOf: aClass superclass \x0a\x09\x09named: aClass name \x0a\x09\x09instanceVariableNames: (aClass instanceVariableNames copy add: aString; yourself)\x0a\x09\x09package: aClass package name",
+messageSends: ["addSubclassOf:named:instanceVariableNames:package:", "classBuilder", "superclass", "name", "add:", "copy", "instanceVariableNames", "yourself", "package"],
+referencedClasses: []
+}),
+smalltalk.Environment);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "allSelectors",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(_st(_st($Smalltalk())._current())._at_("allSelectors"))._value();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"allSelectors",{},smalltalk.Environment)})},
+args: [],
+source: "allSelectors\x0a\x09^ (Smalltalk current at: 'allSelectors') value",
+messageSends: ["value", "at:", "current"],
 referencedClasses: ["Smalltalk"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "moveMethod:toProtocol:",
-category: 'actions',
-fn: function (aMethod,aProtocol){
+selector: "availableClassNames",
+category: 'accessing',
+fn: function (){
 var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-_st(aMethod)._category_(aProtocol);
-return self}, function($ctx1) {$ctx1.fill(self,"moveMethod:toProtocol:",{aMethod:aMethod,aProtocol:aProtocol},smalltalk.Environment)})},
-args: ["aMethod", "aProtocol"],
-source: "moveMethod: aMethod toProtocol: aProtocol\x0a\x09aMethod category: aProtocol",
-messageSends: ["category:"],
-referencedClasses: []
+var $1;
+$1=_st(_st(_st($Smalltalk())._current())._classes())._collect_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each)._name();
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"availableClassNames",{},smalltalk.Environment)})},
+args: [],
+source: "availableClassNames\x0a\x09^ Smalltalk current classes \x0a\x09\x09collect: [ :each | each name ]",
+messageSends: ["collect:", "classes", "current", "name"],
+referencedClasses: ["Smalltalk"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "packages",
+selector: "availablePackageNames",
 category: 'accessing',
 fn: function (){
 var self=this;
 function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(_st($Smalltalk())._current())._packages();
+$1=_st(_st(_st($Smalltalk())._current())._packages())._collect_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each)._name();
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})}));
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"packages",{},smalltalk.Environment)})},
+}, function($ctx1) {$ctx1.fill(self,"availablePackageNames",{},smalltalk.Environment)})},
 args: [],
-source: "packages\x0a\x09^ Smalltalk current packages",
-messageSends: ["packages", "current"],
+source: "availablePackageNames\x0a\x09^ Smalltalk current packages \x0a\x09\x09collect: [ :each | each name ]",
+messageSends: ["collect:", "packages", "current", "name"],
 referencedClasses: ["Smalltalk"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "registerErrorHandler:",
-category: 'actions',
-fn: function (anErrorHandler){
+selector: "availableProtocolsFor:",
+category: 'accessing',
+fn: function (aClass){
 var self=this;
-function $ErrorHandler(){return smalltalk.ErrorHandler||(typeof ErrorHandler=="undefined"?nil:ErrorHandler)}
+var protocols;
 return smalltalk.withContext(function($ctx1) { 
-_st($ErrorHandler())._setCurrent_(anErrorHandler);
-return self}, function($ctx1) {$ctx1.fill(self,"registerErrorHandler:",{anErrorHandler:anErrorHandler},smalltalk.Environment)})},
-args: ["anErrorHandler"],
-source: "registerErrorHandler: anErrorHandler\x0a\x09ErrorHandler setCurrent: anErrorHandler",
-messageSends: ["setCurrent:"],
-referencedClasses: ["ErrorHandler"]
+var $1,$2;
+protocols=_st(aClass)._protocols();
+$1=_st(aClass)._superclass();
+$ctx1.sendIdx["superclass"]=1;
+if(($receiver = $1) == nil || $receiver == null){
+$1;
+} else {
+_st(protocols)._addAll_(self._availableProtocolsFor_(_st(aClass)._superclass()));
+};
+$2=_st(_st(protocols)._asSet())._asArray();
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"availableProtocolsFor:",{aClass:aClass,protocols:protocols},smalltalk.Environment)})},
+args: ["aClass"],
+source: "availableProtocolsFor: aClass\x0a\x09| protocols |\x0a\x09\x0a\x09protocols := aClass protocols.\x0a\x09aClass superclass ifNotNil: [ protocols addAll: (self availableProtocolsFor: aClass superclass) ].\x0a\x09^ protocols asSet asArray",
+messageSends: ["protocols", "ifNotNil:", "superclass", "addAll:", "availableProtocolsFor:", "asArray", "asSet"],
+referencedClasses: []
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "registerInspector:",
-category: 'actions',
-fn: function (anInspector){
+selector: "classBuilder",
+category: 'accessing',
+fn: function (){
 var self=this;
-function $InspectorHandler(){return smalltalk.InspectorHandler||(typeof InspectorHandler=="undefined"?nil:InspectorHandler)}
+function $ClassBuilder(){return smalltalk.ClassBuilder||(typeof ClassBuilder=="undefined"?nil:ClassBuilder)}
 return smalltalk.withContext(function($ctx1) { 
-_st($InspectorHandler())._register_(anInspector);
-return self}, function($ctx1) {$ctx1.fill(self,"registerInspector:",{anInspector:anInspector},smalltalk.Environment)})},
-args: ["anInspector"],
-source: "registerInspector: anInspector\x0a\x09InspectorHandler register: anInspector",
-messageSends: ["register:"],
-referencedClasses: ["InspectorHandler"]
+var $1;
+$1=_st($ClassBuilder())._new();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"classBuilder",{},smalltalk.Environment)})},
+args: [],
+source: "classBuilder\x0a\x09^ ClassBuilder new",
+messageSends: ["new"],
+referencedClasses: ["ClassBuilder"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "registerProgressHandler:",
-category: 'actions',
-fn: function (aProgressHandler){
+selector: "classNamed:",
+category: 'accessing',
+fn: function (aString){
 var self=this;
-function $ProgressHandler(){return smalltalk.ProgressHandler||(typeof ProgressHandler=="undefined"?nil:ProgressHandler)}
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-_st($ProgressHandler())._setCurrent_(aProgressHandler);
-return self}, function($ctx1) {$ctx1.fill(self,"registerProgressHandler:",{aProgressHandler:aProgressHandler},smalltalk.Environment)})},
-args: ["aProgressHandler"],
-source: "registerProgressHandler: aProgressHandler\x0a\x09ProgressHandler setCurrent: aProgressHandler",
-messageSends: ["setCurrent:"],
-referencedClasses: ["ProgressHandler"]
+var $2,$1;
+$2=_st(_st($Smalltalk())._current())._at_(_st(aString)._asSymbol());
+if(($receiver = $2) == nil || $receiver == null){
+$1=self._error_("Invalid class name");
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"classNamed:",{aString:aString},smalltalk.Environment)})},
+args: ["aString"],
+source: "classNamed: aString\x0a\x09^ (Smalltalk current at: aString asSymbol)\x0a\x09\x09ifNil: [ self error: 'Invalid class name' ]",
+messageSends: ["ifNil:", "at:", "current", "asSymbol", "error:"],
+referencedClasses: ["Smalltalk"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "removeClass:",
-category: 'actions',
-fn: function (aClass){
+selector: "classes",
+category: 'accessing',
+fn: function (){
 var self=this;
 function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-_st(_st($Smalltalk())._current())._removeClass_(aClass);
-return self}, function($ctx1) {$ctx1.fill(self,"removeClass:",{aClass:aClass},smalltalk.Environment)})},
-args: ["aClass"],
-source: "removeClass: aClass\x0a\x09Smalltalk current removeClass: aClass",
-messageSends: ["removeClass:", "current"],
+var $1;
+$1=_st(_st($Smalltalk())._current())._classes();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"classes",{},smalltalk.Environment)})},
+args: [],
+source: "classes\x0a\x09^ Smalltalk current classes",
+messageSends: ["classes", "current"],
 referencedClasses: ["Smalltalk"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "removeMethod:",
+selector: "commitPackage:",
 category: 'actions',
-fn: function (aMethod){
+fn: function (aPackage){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(_st(aMethod)._methodClass())._removeCompiledMethod_(aMethod);
-return self}, function($ctx1) {$ctx1.fill(self,"removeMethod:",{aMethod:aMethod},smalltalk.Environment)})},
-args: ["aMethod"],
-source: "removeMethod: aMethod\x0a\x09aMethod methodClass removeCompiledMethod: aMethod",
-messageSends: ["removeCompiledMethod:", "methodClass"],
+_st(aPackage)._commit();
+return self}, function($ctx1) {$ctx1.fill(self,"commitPackage:",{aPackage:aPackage},smalltalk.Environment)})},
+args: ["aPackage"],
+source: "commitPackage: aPackage\x0a\x09aPackage commit",
+messageSends: ["commit"],
 referencedClasses: []
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "removeProtocol:from:",
-category: 'actions',
+selector: "compileClassComment:for:",
+category: 'compiling',
 fn: function (aString,aClass){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(_st(_st(aClass)._methods())._select_((function(each){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(each)._protocol()).__eq(aString);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})})))._do_((function(each){
-return smalltalk.withContext(function($ctx2) {
-return _st(aClass)._removeCompiledMethod_(each);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"removeProtocol:from:",{aString:aString,aClass:aClass},smalltalk.Environment)})},
+_st(aClass)._comment_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"compileClassComment:for:",{aString:aString,aClass:aClass},smalltalk.Environment)})},
 args: ["aString", "aClass"],
-source: "removeProtocol: aString from: aClass\x0a\x09(aClass methods\x0a\x09\x09select: [ :each | each protocol = aString ])\x0a\x09\x09do: [ :each | aClass removeCompiledMethod: each ]",
-messageSends: ["do:", "select:", "methods", "=", "protocol", "removeCompiledMethod:"],
+source: "compileClassComment: aString for: aClass\x0a\x09aClass comment: aString",
+messageSends: ["comment:"],
 referencedClasses: []
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "renameClass:to:",
-category: 'actions',
-fn: function (aClass,aClassName){
+selector: "compileClassDefinition:",
+category: 'compiling',
+fn: function (aString){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
-function $ClassBuilder(){return smalltalk.ClassBuilder||(typeof ClassBuilder=="undefined"?nil:ClassBuilder)}
+function $DoIt(){return smalltalk.DoIt||(typeof DoIt=="undefined"?nil:DoIt)}
 return smalltalk.withContext(function($ctx1) { 
-var $1,$2;
-$1=_st(_st($Smalltalk())._current())._at_(aClassName);
-if(($receiver = $1) == nil || $receiver == null){
-$1;
-} else {
-$2=_st("A class named ".__comma(aClassName)).__comma(" already exists");
-$ctx1.sendIdx[","]=1;
-self._error_($2);
-};
-_st(_st($ClassBuilder())._new())._renameClass_to_(aClass,aClassName);
-return self}, function($ctx1) {$ctx1.fill(self,"renameClass:to:",{aClass:aClass,aClassName:aClassName},smalltalk.Environment)})},
-args: ["aClass", "aClassName"],
-source: "renameClass: aClass to: aClassName\x0a\x09(Smalltalk current at: aClassName)\x0a\x09\x09ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].\x0a\x09\x09\x0a\x09ClassBuilder new renameClass: aClass to: aClassName",
-messageSends: ["ifNotNil:", "at:", "current", "error:", ",", "renameClass:to:", "new"],
-referencedClasses: ["Smalltalk", "ClassBuilder"]
+self._eval_on_(aString,_st($DoIt())._new());
+return self}, function($ctx1) {$ctx1.fill(self,"compileClassDefinition:",{aString:aString},smalltalk.Environment)})},
+args: ["aString"],
+source: "compileClassDefinition: aString\x0a\x09self eval: aString on: DoIt new",
+messageSends: ["eval:on:", "new"],
+referencedClasses: ["DoIt"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "renameProtocol:to:in:",
-category: 'actions',
-fn: function (aString,anotherString,aClass){
+selector: "compileMethod:for:protocol:",
+category: 'compiling',
+fn: function (sourceCode,class_,protocol){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-_st(_st(_st(aClass)._methods())._select_((function(each){
-return smalltalk.withContext(function($ctx2) {
-return _st(_st(each)._protocol()).__eq(aString);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})})))._do_((function(each){
-return smalltalk.withContext(function($ctx2) {
-return _st(each)._protocol_(anotherString);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"renameProtocol:to:in:",{aString:aString,anotherString:anotherString,aClass:aClass},smalltalk.Environment)})},
-args: ["aString", "anotherString", "aClass"],
-source: "renameProtocol: aString to: anotherString in: aClass\x0a\x09(aClass methods\x0a\x09\x09select: [ :each | each protocol = aString ])\x0a\x09\x09do: [ :each | each protocol: anotherString ]",
-messageSends: ["do:", "select:", "methods", "=", "protocol", "protocol:"],
+var $1;
+$1=_st(class_)._compile_category_(sourceCode,protocol);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"compileMethod:for:protocol:",{sourceCode:sourceCode,class_:class_,protocol:protocol},smalltalk.Environment)})},
+args: ["sourceCode", "class", "protocol"],
+source: "compileMethod: sourceCode for: class protocol: protocol\x0a\x09^ class\x0a\x09\x09compile: sourceCode\x0a\x09\x09category: protocol",
+messageSends: ["compile:category:"],
 referencedClasses: []
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "setClassCommentOf:to:",
+selector: "copyClass:to:",
 category: 'actions',
-fn: function (aClass,aString){
+fn: function (aClass,aClassName){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(aClass)._comment_(aString);
-return self}, function($ctx1) {$ctx1.fill(self,"setClassCommentOf:to:",{aClass:aClass,aString:aString},smalltalk.Environment)})},
-args: ["aClass", "aString"],
-source: "setClassCommentOf: aClass to: aString\x0a\x09aClass comment: aString",
-messageSends: ["comment:"],
-referencedClasses: []
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+function $ClassBuilder(){return smalltalk.ClassBuilder||(typeof ClassBuilder=="undefined"?nil:ClassBuilder)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=_st(_st($Smalltalk())._current())._at_(aClassName);
+if(($receiver = $1) == nil || $receiver == null){
+$1;
+} else {
+$2=_st("A class named ".__comma(aClassName)).__comma(" already exists");
+$ctx1.sendIdx[","]=1;
+self._error_($2);
+};
+_st(_st($ClassBuilder())._new())._copyClass_named_(aClass,aClassName);
+return self}, function($ctx1) {$ctx1.fill(self,"copyClass:to:",{aClass:aClass,aClassName:aClassName},smalltalk.Environment)})},
+args: ["aClass", "aClassName"],
+source: "copyClass: aClass to: aClassName\x0a\x09(Smalltalk current at: aClassName)\x0a\x09\x09ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].\x0a\x09\x09\x0a\x09ClassBuilder new copyClass: aClass named: aClassName",
+messageSends: ["ifNotNil:", "at:", "current", "error:", ",", "copyClass:named:", "new"],
+referencedClasses: ["Smalltalk", "ClassBuilder"]
 }),
 smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "systemAnnouncer",
+selector: "doItReceiver",
 category: 'accessing',
 fn: function (){
 var self=this;
-function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+function $DoIt(){return smalltalk.DoIt||(typeof DoIt=="undefined"?nil:DoIt)}
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(_st(_st($Smalltalk())._current())._at_("SystemAnnouncer"))._current();
-$ctx1.sendIdx["current"]=1;
+$1=_st($DoIt())._new();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"systemAnnouncer",{},smalltalk.Environment)})},
+}, function($ctx1) {$ctx1.fill(self,"doItReceiver",{},smalltalk.Environment)})},
 args: [],
-source: "systemAnnouncer\x0a\x09^ (Smalltalk current at: #SystemAnnouncer) current",
-messageSends: ["current", "at:"],
-referencedClasses: ["Smalltalk"]
+source: "doItReceiver\x0a\x09^ DoIt new",
+messageSends: ["new"],
+referencedClasses: ["DoIt"]
 }),
 smalltalk.Environment);
 
-
-
-smalltalk.addClass('JSObjectProxy', smalltalk.Object, ['jsObject'], 'Kernel-Infrastructure');
-smalltalk.JSObjectProxy.comment="I handle sending messages to JavaScript objects, making  JavaScript object accessing from Amber fully transparent.\x0aMy instances make intensive use of `#doesNotUnderstand:`.\x0a\x0aMy instances are automatically created by Amber whenever a message is sent to a JavaScript object.\x0a\x0a## Usage examples\x0a\x0aJSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.\x0a\x0a\x09window alert: 'hello world'.\x0a\x09window inspect.\x0a\x09(window jQuery: 'body') append: 'hello world'\x0a\x0aAmber messages sends are converted to JavaScript function calls or object property access _(in this order)_. If n one of them match, a `MessageNotUnderstood` error will be thrown.\x0a\x0a## Message conversion rules\x0a\x0a- `someUser name` becomes `someUser.name`\x0a- `someUser name: 'John'` becomes `someUser name = \x22John\x22`\x0a- `console log: 'hello world'` becomes `console.log('hello world')`\x0a- `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`\x0a\x0a__Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.";
 smalltalk.addMethod(
 smalltalk.method({
-selector: "addObjectVariablesTo:",
-category: 'proxy',
-fn: function (aDictionary){
+selector: "eval:on:",
+category: 'actions',
+fn: function (aString,aReceiver){
 var self=this;
+var compiler;
+function $Compiler(){return smalltalk.Compiler||(typeof Compiler=="undefined"?nil:Compiler)}
+function $Error(){return smalltalk.Error||(typeof Error=="undefined"?nil:Error)}
 return smalltalk.withContext(function($ctx1) { 
-
-		for(var i in self['@jsObject']) {
-			aDictionary._at_put_(i, self['@jsObject'][i]);
-		}
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"addObjectVariablesTo:",{aDictionary:aDictionary},smalltalk.JSObjectProxy)})},
-args: ["aDictionary"],
-source: "addObjectVariablesTo: aDictionary\x0a\x09<\x0a\x09\x09for(var i in self['@jsObject']) {\x0a\x09\x09\x09aDictionary._at_put_(i, self['@jsObject'][i]);\x0a\x09\x09}\x0a\x09>",
-messageSends: [],
-referencedClasses: []
+var $1,$2;
+var $early={};
+try {
+compiler=_st($Compiler())._new();
+_st((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(compiler)._parseExpression_(aString);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}))._on_do_($Error(),(function(ex){
+return smalltalk.withContext(function($ctx2) {
+$1=self._alert_(_st(ex)._messageText());
+throw $early=[$1];
+}, function($ctx2) {$ctx2.fillBlock({ex:ex},$ctx1,2)})}));
+$2=_st(compiler)._evaluateExpression_on_(aString,aReceiver);
+return $2;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+}, function($ctx1) {$ctx1.fill(self,"eval:on:",{aString:aString,aReceiver:aReceiver,compiler:compiler},smalltalk.Environment)})},
+args: ["aString", "aReceiver"],
+source: "eval: aString on: aReceiver\x0a\x09| compiler |\x0a\x09compiler := Compiler new.\x0a\x09[ compiler parseExpression: aString ] on: Error do: [ :ex |\x0a\x09\x09^ self alert: ex messageText ].\x0a\x09^ compiler evaluateExpression: aString on: aReceiver",
+messageSends: ["new", "on:do:", "parseExpression:", "alert:", "messageText", "evaluateExpression:on:"],
+referencedClasses: ["Compiler", "Error"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "asJSON",
-category: 'enumerating',
-fn: function (){
+selector: "evaluate:on:do:",
+category: 'error handling',
+fn: function (aBlock,anErrorClass,exceptionBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=self["@jsObject"];
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"asJSON",{},smalltalk.JSObjectProxy)})},
-args: [],
-source: "asJSON\x0a\x09\x22Answers the receiver in a stringyfy-friendly fashion\x22\x0a\x0a\x09^ jsObject",
-messageSends: [],
+self._try_catch_(aBlock,(function(exception){
+return smalltalk.withContext(function($ctx2) {
+$1=_st(exception)._isKindOf_(self._classNamed_(_st(anErrorClass)._name()));
+if(smalltalk.assert($1)){
+return _st(exceptionBlock)._value_(exception);
+} else {
+return _st(exception)._signal();
+};
+}, function($ctx2) {$ctx2.fillBlock({exception:exception},$ctx1,1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"evaluate:on:do:",{aBlock:aBlock,anErrorClass:anErrorClass,exceptionBlock:exceptionBlock},smalltalk.Environment)})},
+args: ["aBlock", "anErrorClass", "exceptionBlock"],
+source: "evaluate: aBlock on: anErrorClass do: exceptionBlock\x0a\x09\x22Evaluate a block and catch exceptions happening on the environment stack\x22\x0a\x09\x0a\x09self try: aBlock catch: [ :exception | \x0a\x09\x09(exception isKindOf: (self classNamed: anErrorClass name))\x0a\x09\x09\x09ifTrue: [ exceptionBlock value: exception ]\x0a \x09\x09\x09ifFalse: [ exception signal ] ]",
+messageSends: ["try:catch:", "ifTrue:ifFalse:", "isKindOf:", "classNamed:", "name", "value:", "signal"],
 referencedClasses: []
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "at:",
-category: 'accessing',
-fn: function (aString){
+selector: "inspect:",
+category: 'actions',
+fn: function (anObject){
 var self=this;
+function $InspectorHandler(){return smalltalk.InspectorHandler||(typeof InspectorHandler=="undefined"?nil:InspectorHandler)}
 return smalltalk.withContext(function($ctx1) { 
-return self['@jsObject'][aString];
-return self}, function($ctx1) {$ctx1.fill(self,"at:",{aString:aString},smalltalk.JSObjectProxy)})},
-args: ["aString"],
-source: "at: aString\x0a\x09<return self['@jsObject'][aString]>",
-messageSends: [],
-referencedClasses: []
+_st(_st($InspectorHandler())._inspector())._inspect_(anObject);
+return self}, function($ctx1) {$ctx1.fill(self,"inspect:",{anObject:anObject},smalltalk.Environment)})},
+args: ["anObject"],
+source: "inspect: anObject\x0a\x09InspectorHandler inspector inspect: anObject",
+messageSends: ["inspect:", "inspector"],
+referencedClasses: ["InspectorHandler"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "at:ifAbsent:",
-category: 'accessing',
-fn: function (aString,aBlock){
+selector: "moveClass:toPackage:",
+category: 'actions',
+fn: function (aClass,aPackageName){
 var self=this;
+var package_;
+function $Package(){return smalltalk.Package||(typeof Package=="undefined"?nil:Package)}
 return smalltalk.withContext(function($ctx1) { 
-
-		var obj = self['@jsObject'];
-		return aString in obj ? obj[aString] : aBlock._value();
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"at:ifAbsent:",{aString:aString,aBlock:aBlock},smalltalk.JSObjectProxy)})},
-args: ["aString", "aBlock"],
-source: "at: aString ifAbsent: aBlock\x0a\x09\x22return the aString property or evaluate aBlock if the property is not defined on the object\x22\x0a\x09<\x0a\x09\x09var obj = self['@jsObject'];\x0a\x09\x09return aString in obj ? obj[aString] : aBlock._value();\x0a\x09>",
-messageSends: [],
-referencedClasses: []
+var $1,$2;
+package_=_st($Package())._named_(aPackageName);
+$1=package_;
+if(($receiver = $1) == nil || $receiver == null){
+self._error_("Invalid package name");
+} else {
+$1;
+};
+$2=_st(package_).__eq_eq(_st(aClass)._package());
+if(smalltalk.assert($2)){
+return self;
+};
+_st(aClass)._package_(package_);
+return self}, function($ctx1) {$ctx1.fill(self,"moveClass:toPackage:",{aClass:aClass,aPackageName:aPackageName,package_:package_},smalltalk.Environment)})},
+args: ["aClass", "aPackageName"],
+source: "moveClass: aClass toPackage: aPackageName\x0a\x09| package |\x0a\x09\x0a\x09package := Package named: aPackageName.\x0a\x09package ifNil: [ self error: 'Invalid package name' ].\x0a\x09package == aClass package ifTrue: [ ^ self ].\x0a\x09\x0a\x09aClass package: package",
+messageSends: ["named:", "ifNil:", "error:", "ifTrue:", "==", "package", "package:"],
+referencedClasses: ["Package"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "at:ifPresent:",
-category: 'accessing',
-fn: function (aString,aBlock){
+selector: "moveMethod:toClass:",
+category: 'actions',
+fn: function (aMethod,aClassName){
 var self=this;
+var destinationClass;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-
-		var obj = self['@jsObject'];
-		return aString in obj ? aBlock._value_(obj[aString]) : nil;
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:",{aString:aString,aBlock:aBlock},smalltalk.JSObjectProxy)})},
-args: ["aString", "aBlock"],
-source: "at: aString ifPresent: aBlock\x0a\x09\x22return the evaluation of aBlock with the value if the property is defined or return nil\x22\x0a\x09<\x0a\x09\x09var obj = self['@jsObject'];\x0a\x09\x09return aString in obj ? aBlock._value_(obj[aString]) : nil;\x0a\x09>",
-messageSends: [],
-referencedClasses: []
+var $1,$3,$4,$2;
+destinationClass=_st(_st($Smalltalk())._current())._at_(_st(aClassName)._asSymbol());
+$1=destinationClass;
+if(($receiver = $1) == nil || $receiver == null){
+self._error_("Invalid class name");
+} else {
+$1;
+};
+$3=destinationClass;
+$4=_st(aMethod)._methodClass();
+$ctx1.sendIdx["methodClass"]=1;
+$2=_st($3).__eq_eq($4);
+if(smalltalk.assert($2)){
+return self;
+};
+_st(destinationClass)._compile_category_(_st(aMethod)._source(),_st(aMethod)._protocol());
+_st(_st(aMethod)._methodClass())._removeCompiledMethod_(aMethod);
+return self}, function($ctx1) {$ctx1.fill(self,"moveMethod:toClass:",{aMethod:aMethod,aClassName:aClassName,destinationClass:destinationClass},smalltalk.Environment)})},
+args: ["aMethod", "aClassName"],
+source: "moveMethod: aMethod toClass: aClassName\x0a\x09| destinationClass |\x0a\x09\x0a\x09destinationClass := Smalltalk current at: aClassName asSymbol.\x0a\x09destinationClass ifNil: [ self error: 'Invalid class name' ].\x0a\x09destinationClass == aMethod methodClass ifTrue: [ ^ self ].\x0a\x09\x0a\x09destinationClass \x0a\x09\x09compile: aMethod source\x0a\x09\x09category: aMethod protocol.\x0a\x09aMethod methodClass \x0a\x09\x09removeCompiledMethod: aMethod",
+messageSends: ["at:", "current", "asSymbol", "ifNil:", "error:", "ifTrue:", "==", "methodClass", "compile:category:", "source", "protocol", "removeCompiledMethod:"],
+referencedClasses: ["Smalltalk"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "at:ifPresent:ifAbsent:",
-category: 'accessing',
-fn: function (aString,aBlock,anotherBlock){
+selector: "moveMethod:toProtocol:",
+category: 'actions',
+fn: function (aMethod,aProtocol){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-
-		var obj = self['@jsObject'];
-		return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"at:ifPresent:ifAbsent:",{aString:aString,aBlock:aBlock,anotherBlock:anotherBlock},smalltalk.JSObjectProxy)})},
-args: ["aString", "aBlock", "anotherBlock"],
-source: "at: aString ifPresent: aBlock ifAbsent: anotherBlock\x0a\x09\x22return the evaluation of aBlock with the value if the property is defined\x0a\x09or return value of anotherBlock\x22\x0a\x09<\x0a\x09\x09var obj = self['@jsObject'];\x0a\x09\x09return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();\x0a\x09>",
-messageSends: [],
+_st(aMethod)._category_(aProtocol);
+return self}, function($ctx1) {$ctx1.fill(self,"moveMethod:toProtocol:",{aMethod:aMethod,aProtocol:aProtocol},smalltalk.Environment)})},
+args: ["aMethod", "aProtocol"],
+source: "moveMethod: aMethod toProtocol: aProtocol\x0a\x09aMethod category: aProtocol",
+messageSends: ["category:"],
 referencedClasses: []
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "at:put:",
+selector: "packages",
 category: 'accessing',
-fn: function (aString,anObject){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-self['@jsObject'][aString] = anObject;
-return self}, function($ctx1) {$ctx1.fill(self,"at:put:",{aString:aString,anObject:anObject},smalltalk.JSObjectProxy)})},
-args: ["aString", "anObject"],
-source: "at: aString put: anObject\x0a\x09<self['@jsObject'][aString] = anObject>",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.JSObjectProxy);
-
-smalltalk.addMethod(
-smalltalk.method({
-selector: "doesNotUnderstand:",
-category: 'proxy',
-fn: function (aMessage){
+fn: function (){
 var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
-$2=self._lookupProperty_(_st(_st(aMessage)._selector())._asJavaScriptSelector());
-if(($receiver = $2) == nil || $receiver == null){
-$1=smalltalk.JSObjectProxy.superclass.fn.prototype._doesNotUnderstand_.apply(_st(self), [aMessage]);
-} else {
-var jsSelector;
-jsSelector=$receiver;
-$1=self._forwardMessage_withArguments_(jsSelector,_st(aMessage)._arguments());
-};
+var $1;
+$1=_st(_st($Smalltalk())._current())._packages();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"doesNotUnderstand:",{aMessage:aMessage},smalltalk.JSObjectProxy)})},
-args: ["aMessage"],
-source: "doesNotUnderstand: aMessage\x0a\x09^ (self lookupProperty: aMessage selector asJavaScriptSelector)\x0a\x09\x09ifNil: [ super doesNotUnderstand: aMessage ]\x0a\x09\x09ifNotNil: [ :jsSelector | \x0a\x09\x09\x09self \x0a\x09\x09\x09\x09forwardMessage: jsSelector \x0a\x09\x09\x09\x09withArguments: aMessage arguments ]",
-messageSends: ["ifNil:ifNotNil:", "lookupProperty:", "asJavaScriptSelector", "selector", "doesNotUnderstand:", "forwardMessage:withArguments:", "arguments"],
-referencedClasses: []
+}, function($ctx1) {$ctx1.fill(self,"packages",{},smalltalk.Environment)})},
+args: [],
+source: "packages\x0a\x09^ Smalltalk current packages",
+messageSends: ["packages", "current"],
+referencedClasses: ["Smalltalk"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "forwardMessage:withArguments:",
-category: 'proxy',
-fn: function (aString,anArray){
+selector: "registerErrorHandler:",
+category: 'actions',
+fn: function (anErrorHandler){
 var self=this;
+function $ErrorHandler(){return smalltalk.ErrorHandler||(typeof ErrorHandler=="undefined"?nil:ErrorHandler)}
 return smalltalk.withContext(function($ctx1) { 
-
-		return smalltalk.send(self._jsObject(), aString, anArray);
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"forwardMessage:withArguments:",{aString:aString,anArray:anArray},smalltalk.JSObjectProxy)})},
-args: ["aString", "anArray"],
-source: "forwardMessage: aString withArguments: anArray\x0a\x09<\x0a\x09\x09return smalltalk.send(self._jsObject(), aString, anArray);\x0a\x09>",
-messageSends: [],
-referencedClasses: []
+_st($ErrorHandler())._setCurrent_(anErrorHandler);
+return self}, function($ctx1) {$ctx1.fill(self,"registerErrorHandler:",{anErrorHandler:anErrorHandler},smalltalk.Environment)})},
+args: ["anErrorHandler"],
+source: "registerErrorHandler: anErrorHandler\x0a\x09ErrorHandler setCurrent: anErrorHandler",
+messageSends: ["setCurrent:"],
+referencedClasses: ["ErrorHandler"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "inspectOn:",
-category: 'proxy',
+selector: "registerInspector:",
+category: 'actions',
 fn: function (anInspector){
 var self=this;
-var variables;
-function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
+function $InspectorHandler(){return smalltalk.InspectorHandler||(typeof InspectorHandler=="undefined"?nil:InspectorHandler)}
 return smalltalk.withContext(function($ctx1) { 
-variables=_st($Dictionary())._new();
-_st(variables)._at_put_("#self",self._jsObject());
-_st(anInspector)._setLabel_(self._printString());
-self._addObjectVariablesTo_(variables);
-_st(anInspector)._setVariables_(variables);
-return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables},smalltalk.JSObjectProxy)})},
+_st($InspectorHandler())._register_(anInspector);
+return self}, function($ctx1) {$ctx1.fill(self,"registerInspector:",{anInspector:anInspector},smalltalk.Environment)})},
 args: ["anInspector"],
-source: "inspectOn: anInspector\x0a\x09| variables |\x0a\x09variables := Dictionary new.\x0a\x09variables at: '#self' put: self jsObject.\x0a\x09anInspector setLabel: self printString.\x0a\x09self addObjectVariablesTo: variables.\x0a\x09anInspector setVariables: variables",
-messageSends: ["new", "at:put:", "jsObject", "setLabel:", "printString", "addObjectVariablesTo:", "setVariables:"],
-referencedClasses: ["Dictionary"]
+source: "registerInspector: anInspector\x0a\x09InspectorHandler register: anInspector",
+messageSends: ["register:"],
+referencedClasses: ["InspectorHandler"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "jsObject",
-category: 'accessing',
-fn: function (){
+selector: "registerProgressHandler:",
+category: 'actions',
+fn: function (aProgressHandler){
 var self=this;
+function $ProgressHandler(){return smalltalk.ProgressHandler||(typeof ProgressHandler=="undefined"?nil:ProgressHandler)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self["@jsObject"];
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"jsObject",{},smalltalk.JSObjectProxy)})},
-args: [],
-source: "jsObject\x0a\x09^ jsObject",
-messageSends: [],
-referencedClasses: []
+_st($ProgressHandler())._setCurrent_(aProgressHandler);
+return self}, function($ctx1) {$ctx1.fill(self,"registerProgressHandler:",{aProgressHandler:aProgressHandler},smalltalk.Environment)})},
+args: ["aProgressHandler"],
+source: "registerProgressHandler: aProgressHandler\x0a\x09ProgressHandler setCurrent: aProgressHandler",
+messageSends: ["setCurrent:"],
+referencedClasses: ["ProgressHandler"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "jsObject:",
-category: 'accessing',
-fn: function (aJSObject){
+selector: "removeClass:",
+category: 'actions',
+fn: function (aClass){
 var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-self["@jsObject"]=aJSObject;
-return self}, function($ctx1) {$ctx1.fill(self,"jsObject:",{aJSObject:aJSObject},smalltalk.JSObjectProxy)})},
-args: ["aJSObject"],
-source: "jsObject: aJSObject\x0a\x09jsObject := aJSObject",
-messageSends: [],
-referencedClasses: []
+_st(_st($Smalltalk())._current())._removeClass_(aClass);
+return self}, function($ctx1) {$ctx1.fill(self,"removeClass:",{aClass:aClass},smalltalk.Environment)})},
+args: ["aClass"],
+source: "removeClass: aClass\x0a\x09Smalltalk current removeClass: aClass",
+messageSends: ["removeClass:", "current"],
+referencedClasses: ["Smalltalk"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "keysAndValuesDo:",
-category: 'enumerating',
-fn: function (aBlock){
+selector: "removeMethod:",
+category: 'actions',
+fn: function (aMethod){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-
-		var o = self['@jsObject'];
-		for(var i in o) {
-			aBlock._value_value_(i, o[i]);
-		}
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"keysAndValuesDo:",{aBlock:aBlock},smalltalk.JSObjectProxy)})},
-args: ["aBlock"],
-source: "keysAndValuesDo: aBlock\x0a\x09<\x0a\x09\x09var o = self['@jsObject'];\x0a\x09\x09for(var i in o) {\x0a\x09\x09\x09aBlock._value_value_(i, o[i]);\x0a\x09\x09}\x0a\x09>",
-messageSends: [],
+_st(_st(aMethod)._methodClass())._removeCompiledMethod_(aMethod);
+return self}, function($ctx1) {$ctx1.fill(self,"removeMethod:",{aMethod:aMethod},smalltalk.Environment)})},
+args: ["aMethod"],
+source: "removeMethod: aMethod\x0a\x09aMethod methodClass removeCompiledMethod: aMethod",
+messageSends: ["removeCompiledMethod:", "methodClass"],
 referencedClasses: []
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "lookupProperty:",
-category: 'accessing',
-fn: function (aString){
+selector: "removeProtocol:from:",
+category: 'actions',
+fn: function (aString,aClass){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-return aString in self._jsObject() ? aString : nil;
-return self}, function($ctx1) {$ctx1.fill(self,"lookupProperty:",{aString:aString},smalltalk.JSObjectProxy)})},
-args: ["aString"],
-source: "lookupProperty: aString\x0a\x09\x22Looks up a property in JS object.\x0a\x09Answer the property if it is present, or nil if it is not present.\x22\x0a\x09\x0a\x09<return aString in self._jsObject() ? aString : nil>",
-messageSends: [],
+_st(_st(_st(aClass)._methods())._select_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(each)._protocol()).__eq(aString);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})})))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(aClass)._removeCompiledMethod_(each);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"removeProtocol:from:",{aString:aString,aClass:aClass},smalltalk.Environment)})},
+args: ["aString", "aClass"],
+source: "removeProtocol: aString from: aClass\x0a\x09(aClass methods\x0a\x09\x09select: [ :each | each protocol = aString ])\x0a\x09\x09do: [ :each | aClass removeCompiledMethod: each ]",
+messageSends: ["do:", "select:", "methods", "=", "protocol", "removeCompiledMethod:"],
 referencedClasses: []
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "printOn:",
-category: 'printing',
-fn: function (aStream){
+selector: "renameClass:to:",
+category: 'actions',
+fn: function (aClass,aClassName){
 var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
+function $ClassBuilder(){return smalltalk.ClassBuilder||(typeof ClassBuilder=="undefined"?nil:ClassBuilder)}
 return smalltalk.withContext(function($ctx1) { 
-_st(aStream)._nextPutAll_(self._printString());
-return self}, function($ctx1) {$ctx1.fill(self,"printOn:",{aStream:aStream},smalltalk.JSObjectProxy)})},
-args: ["aStream"],
-source: "printOn: aStream\x0a\x09aStream nextPutAll: self printString",
-messageSends: ["nextPutAll:", "printString"],
-referencedClasses: []
+var $1,$2;
+$1=_st(_st($Smalltalk())._current())._at_(aClassName);
+if(($receiver = $1) == nil || $receiver == null){
+$1;
+} else {
+$2=_st("A class named ".__comma(aClassName)).__comma(" already exists");
+$ctx1.sendIdx[","]=1;
+self._error_($2);
+};
+_st(_st($ClassBuilder())._new())._renameClass_to_(aClass,aClassName);
+return self}, function($ctx1) {$ctx1.fill(self,"renameClass:to:",{aClass:aClass,aClassName:aClassName},smalltalk.Environment)})},
+args: ["aClass", "aClassName"],
+source: "renameClass: aClass to: aClassName\x0a\x09(Smalltalk current at: aClassName)\x0a\x09\x09ifNotNil: [ self error: 'A class named ', aClassName, ' already exists' ].\x0a\x09\x09\x0a\x09ClassBuilder new renameClass: aClass to: aClassName",
+messageSends: ["ifNotNil:", "at:", "current", "error:", ",", "renameClass:to:", "new"],
+referencedClasses: ["Smalltalk", "ClassBuilder"]
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "printString",
-category: 'printing',
-fn: function (){
+selector: "renameProtocol:to:in:",
+category: 'actions',
+fn: function (aString,anotherString,aClass){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-
-		var js = self['@jsObject'];
-		return js.toString
-			? js.toString()
-			: Object.prototype.toString.call(js)
-	;
-return self}, function($ctx1) {$ctx1.fill(self,"printString",{},smalltalk.JSObjectProxy)})},
-args: [],
-source: "printString\x0a\x09<\x0a\x09\x09var js = self['@jsObject'];\x0a\x09\x09return js.toString\x0a\x09\x09\x09? js.toString()\x0a\x09\x09\x09: Object.prototype.toString.call(js)\x0a\x09>",
-messageSends: [],
+_st(_st(_st(aClass)._methods())._select_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(_st(each)._protocol()).__eq(aString);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)})})))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
+return _st(each)._protocol_(anotherString);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"renameProtocol:to:in:",{aString:aString,anotherString:anotherString,aClass:aClass},smalltalk.Environment)})},
+args: ["aString", "anotherString", "aClass"],
+source: "renameProtocol: aString to: anotherString in: aClass\x0a\x09(aClass methods\x0a\x09\x09select: [ :each | each protocol = aString ])\x0a\x09\x09do: [ :each | each protocol: anotherString ]",
+messageSends: ["do:", "select:", "methods", "=", "protocol", "protocol:"],
 referencedClasses: []
 }),
-smalltalk.JSObjectProxy);
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "value",
-category: 'accessing',
-fn: function (){
+selector: "setClassCommentOf:to:",
+category: 'actions',
+fn: function (aClass,aString){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self._at_ifAbsent_("value",(function(){
-return smalltalk.withContext(function($ctx2) {
-return smalltalk.JSObjectProxy.superclass.fn.prototype._value.apply(_st(self), []);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)})}));
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"value",{},smalltalk.JSObjectProxy)})},
-args: [],
-source: "value\x0a\x09\x22if attribute 'value' exists on the JS object return it,\x0a\x09otherwise return the result of Object>>value.\x22\x0a\x09\x0a\x09^ self \x0a\x09\x09at: 'value' \x0a\x09\x09ifAbsent: [ super value ]",
-messageSends: ["at:ifAbsent:", "value"],
+_st(aClass)._comment_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"setClassCommentOf:to:",{aClass:aClass,aString:aString},smalltalk.Environment)})},
+args: ["aClass", "aString"],
+source: "setClassCommentOf: aClass to: aString\x0a\x09aClass comment: aString",
+messageSends: ["comment:"],
 referencedClasses: []
 }),
-smalltalk.JSObjectProxy);
-
+smalltalk.Environment);
 
 smalltalk.addMethod(
 smalltalk.method({
-selector: "on:",
-category: 'instance creation',
-fn: function (aJSObject){
+selector: "systemAnnouncer",
+category: 'accessing',
+fn: function (){
 var self=this;
+function $Smalltalk(){return smalltalk.Smalltalk||(typeof Smalltalk=="undefined"?nil:Smalltalk)}
 return smalltalk.withContext(function($ctx1) { 
-var $2,$3,$1;
-$2=self._new();
-_st($2)._jsObject_(aJSObject);
-$3=_st($2)._yourself();
-$1=$3;
+var $1;
+$1=_st(_st(_st($Smalltalk())._current())._at_("SystemAnnouncer"))._current();
+$ctx1.sendIdx["current"]=1;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"on:",{aJSObject:aJSObject},smalltalk.JSObjectProxy.klass)})},
-args: ["aJSObject"],
-source: "on: aJSObject\x0a\x09^ self new\x0a\x09\x09jsObject: aJSObject;\x0a\x09\x09yourself",
-messageSends: ["jsObject:", "new", "yourself"],
-referencedClasses: []
+}, function($ctx1) {$ctx1.fill(self,"systemAnnouncer",{},smalltalk.Environment)})},
+args: [],
+source: "systemAnnouncer\x0a\x09^ (Smalltalk current at: #SystemAnnouncer) current",
+messageSends: ["current", "at:"],
+referencedClasses: ["Smalltalk"]
 }),
-smalltalk.JSObjectProxy.klass);
+smalltalk.Environment);
+
 
 
 smalltalk.addClass('Organizer', smalltalk.Object, [], 'Kernel-Infrastructure');

+ 6 - 24
js/Kernel-Objects.js

@@ -373,15 +373,15 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 
-	var hash=self.identityHash;
-	if (hash) return hash;
-	hash=smalltalk.nextId();
-	Object.defineProperty(self, 'identityHash', {value:hash});
-	return hash;
+		var hash=self.identityHash;
+		if (hash) return hash;
+		hash=smalltalk.nextId();
+		Object.defineProperty(self, 'identityHash', {value:hash});
+		return hash;
 	;
 return self}, function($ctx1) {$ctx1.fill(self,"identityHash",{},smalltalk.Object)})},
 args: [],
-source: "identityHash\x0a\x09<\x0a\x09var hash=self.identityHash;\x0a\x09if (hash) return hash;\x0a\x09hash=smalltalk.nextId();\x0a\x09Object.defineProperty(self, 'identityHash', {value:hash});\x0a\x09return hash;\x0a\x09>",
+source: "identityHash\x0a\x09<\x0a\x09\x09var hash=self.identityHash;\x0a\x09\x09if (hash) return hash;\x0a\x09\x09hash=smalltalk.nextId();\x0a\x09\x09Object.defineProperty(self, 'identityHash', {value:hash});\x0a\x09\x09return hash;\x0a\x09>",
 messageSends: [],
 referencedClasses: []
 }),
@@ -1006,24 +1006,6 @@ referencedClasses: []
 }),
 smalltalk.Object);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "test",
-category: 'converting',
-fn: function (){
-var self=this;
-var a;
-return smalltalk.withContext(function($ctx1) { 
-a=(1);
-self._halt();
-return self}, function($ctx1) {$ctx1.fill(self,"test",{a:a},smalltalk.Object)})},
-args: [],
-source: "test\x0a\x09| a |\x0a\x09a := 1.\x0a\x09self halt",
-messageSends: ["halt"],
-referencedClasses: []
-}),
-smalltalk.Object);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "throw:",

+ 2 - 8
js/Kernel-Tests.js

@@ -4218,19 +4218,13 @@ fn: function (){
 var self=this;
 var testObject;
 return smalltalk.withContext(function($ctx1) { 
-var $2,$1;
 testObject=self._jsObject();
-$2=_st(testObject)._value();
-$ctx1.sendIdx["value"]=1;
-$1=_st($2)._printString();
-self._assert_equals_($1,"[object Object]");
-$ctx1.sendIdx["assert:equals:"]=1;
 _st(testObject)._at_put_("value","aValue");
 self._assert_equals_(_st(testObject)._value(),"aValue");
 return self}, function($ctx1) {$ctx1.fill(self,"testValue",{testObject:testObject},smalltalk.JSObjectProxyTest)})},
 args: [],
-source: "testValue\x0a\x09| testObject |\x0a\x09testObject := self jsObject.\x0a\x09self assert: testObject value printString equals: '[object Object]'.\x0a\x09testObject at: 'value' put: 'aValue'.\x0a\x09self assert: testObject value equals: 'aValue'",
-messageSends: ["jsObject", "assert:equals:", "printString", "value", "at:put:"],
+source: "testValue\x0a\x09| testObject |\x0a\x09testObject := self jsObject.\x0a\x09testObject at: 'value' put: 'aValue'.\x0a\x09self assert: testObject value equals: 'aValue'",
+messageSends: ["jsObject", "at:put:", "assert:equals:", "value"],
 referencedClasses: []
 }),
 smalltalk.JSObjectProxyTest);

+ 250 - 161
st/Kernel-Infrastructure.st

@@ -1,4 +1,254 @@
 Smalltalk current createPackage: 'Kernel-Infrastructure'!
+nil subclass: #AbstractProxy
+	instanceVariableNames: ''
+	package: 'Kernel-Infrastructure'!
+!AbstractProxy commentStamp!
+I provide a basic set of methods for proxies handling `#doesNotUnderstand:` so that inspectors, debuggers, etc. won't fail.!
+
+!AbstractProxy methodsFor: 'accessing'!
+
+class
+	<return self.klass>
+!
+
+identityHash
+	<
+		var hash=self.identityHash;
+		if (hash) return hash;
+		hash=smalltalk.nextId();
+		Object.defineProperty(self, 'identityHash', {value:hash});
+		return hash;
+	>
+!
+
+instVarAt: aString
+	< return self['@'+aString] >
+!
+
+instVarAt: aString put: anObject
+	< self['@' + aString] = anObject >
+!
+
+yourself
+	^ self
+! !
+
+!AbstractProxy methodsFor: 'converting'!
+
+asString
+	^ self printString
+! !
+
+!AbstractProxy methodsFor: 'error handling'!
+
+doesNotUnderstand: aMessage
+	MessageNotUnderstood new
+		receiver: self;
+		message: aMessage;
+		signal
+! !
+
+!AbstractProxy methodsFor: 'initialization'!
+
+initialize
+! !
+
+!AbstractProxy methodsFor: 'inspecting'!
+
+inspect
+	InspectorHandler inspect: self
+!
+
+inspectOn: anInspector
+! !
+
+!AbstractProxy methodsFor: 'message handling'!
+
+perform: aString
+	^ self perform: aString withArguments: #()
+!
+
+perform: aString withArguments: aCollection
+	<return smalltalk.send(self, aString._asSelector(), aCollection)>
+! !
+
+!AbstractProxy methodsFor: 'printing'!
+
+printOn: aStream
+	aStream nextPutAll: (self class name first isVowel
+		ifTrue: [ 'an ' ]
+		ifFalse: [ 'a ' ]).
+	aStream nextPutAll: self class name
+!
+
+printString
+	^ String streamContents: [ :str | 
+		self printOn: str ]
+! !
+
+!AbstractProxy class methodsFor: 'helios'!
+
+heliosClass
+	^ 'class'
+! !
+
+!AbstractProxy class methodsFor: 'initialization'!
+
+initialize
+! !
+
+AbstractProxy subclass: #JSObjectProxy
+	instanceVariableNames: 'jsObject'
+	package: 'Kernel-Infrastructure'!
+!JSObjectProxy commentStamp!
+I handle sending messages to JavaScript objects, making  JavaScript object accessing from Amber fully transparent.
+My instances make intensive use of `#doesNotUnderstand:`.
+
+My instances are automatically created by Amber whenever a message is sent to a JavaScript object.
+
+## Usage examples
+
+JSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.
+
+	window alert: 'hello world'.
+	window inspect.
+	(window jQuery: 'body') append: 'hello world'
+
+Amber messages sends are converted to JavaScript function calls or object property access _(in this order)_. If n one of them match, a `MessageNotUnderstood` error will be thrown.
+
+## Message conversion rules
+
+- `someUser name` becomes `someUser.name`
+- `someUser name: 'John'` becomes `someUser name = "John"`
+- `console log: 'hello world'` becomes `console.log('hello world')`
+- `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`
+
+__Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.!
+
+!JSObjectProxy methodsFor: 'accessing'!
+
+at: aString
+	<return self['@jsObject'][aString]>
+!
+
+at: aString ifAbsent: aBlock
+	"return the aString property or evaluate aBlock if the property is not defined on the object"
+	<
+		var obj = self['@jsObject'];
+		return aString in obj ? obj[aString] : aBlock._value();
+	>
+!
+
+at: aString ifPresent: aBlock
+	"return the evaluation of aBlock with the value if the property is defined or return nil"
+	<
+		var obj = self['@jsObject'];
+		return aString in obj ? aBlock._value_(obj[aString]) : nil;
+	>
+!
+
+at: aString ifPresent: aBlock ifAbsent: anotherBlock
+	"return the evaluation of aBlock with the value if the property is defined
+	or return value of anotherBlock"
+	<
+		var obj = self['@jsObject'];
+		return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();
+	>
+!
+
+at: aString put: anObject
+	<self['@jsObject'][aString] = anObject>
+!
+
+jsObject
+	^ jsObject
+!
+
+jsObject: aJSObject
+	jsObject := aJSObject
+!
+
+lookupProperty: aString
+	"Looks up a property in JS object.
+	Answer the property if it is present, or nil if it is not present."
+	
+	<return aString in self._jsObject() ? aString : nil>
+! !
+
+!JSObjectProxy methodsFor: 'enumerating'!
+
+asJSON
+	"Answers the receiver in a stringyfy-friendly fashion"
+
+	^ jsObject
+!
+
+keysAndValuesDo: aBlock
+	<
+		var o = self['@jsObject'];
+		for(var i in o) {
+			aBlock._value_value_(i, o[i]);
+		}
+	>
+! !
+
+!JSObjectProxy methodsFor: 'printing'!
+
+printOn: aStream
+	aStream nextPutAll: self printString
+!
+
+printString
+	<
+		var js = self['@jsObject'];
+		return js.toString
+			? js.toString()
+			: Object.prototype.toString.call(js)
+	>
+! !
+
+!JSObjectProxy methodsFor: 'proxy'!
+
+addObjectVariablesTo: aDictionary
+	<
+		for(var i in self['@jsObject']) {
+			aDictionary._at_put_(i, self['@jsObject'][i]);
+		}
+	>
+!
+
+doesNotUnderstand: aMessage
+	^ (self lookupProperty: aMessage selector asJavaScriptSelector)
+		ifNil: [ super doesNotUnderstand: aMessage ]
+		ifNotNil: [ :jsSelector | 
+			self 
+				forwardMessage: jsSelector 
+				withArguments: aMessage arguments ]
+!
+
+forwardMessage: aString withArguments: anArray
+	<
+		return smalltalk.send(self._jsObject(), aString, anArray);
+	>
+!
+
+inspectOn: anInspector
+	| variables |
+	variables := Dictionary new.
+	variables at: '#self' put: self jsObject.
+	anInspector setLabel: self printString.
+	self addObjectVariablesTo: variables.
+	anInspector setVariables: variables
+! !
+
+!JSObjectProxy class methodsFor: 'instance creation'!
+
+on: aJSObject
+	^ self new
+		jsObject: aJSObject;
+		yourself
+! !
+
 Object subclass: #InspectorHandler
 	instanceVariableNames: ''
 	package: 'Kernel-Infrastructure'!
@@ -249,167 +499,6 @@ evaluate: aBlock on: anErrorClass do: exceptionBlock
  			ifFalse: [ exception signal ] ]
 ! !
 
-Object subclass: #JSObjectProxy
-	instanceVariableNames: 'jsObject'
-	package: 'Kernel-Infrastructure'!
-!JSObjectProxy commentStamp!
-I handle sending messages to JavaScript objects, making  JavaScript object accessing from Amber fully transparent.
-My instances make intensive use of `#doesNotUnderstand:`.
-
-My instances are automatically created by Amber whenever a message is sent to a JavaScript object.
-
-## Usage examples
-
-JSObjectProxy objects are instanciated by Amber when a Smalltalk message is sent to a JavaScript object.
-
-	window alert: 'hello world'.
-	window inspect.
-	(window jQuery: 'body') append: 'hello world'
-
-Amber messages sends are converted to JavaScript function calls or object property access _(in this order)_. If n one of them match, a `MessageNotUnderstood` error will be thrown.
-
-## Message conversion rules
-
-- `someUser name` becomes `someUser.name`
-- `someUser name: 'John'` becomes `someUser name = "John"`
-- `console log: 'hello world'` becomes `console.log('hello world')`
-- `(window jQuery: 'foo') css: 'background' color: 'red'` becomes `window.jQuery('foo').css('background', 'red')`
-
-__Note:__ For keyword-based messages, only the first keyword is kept: `window foo: 1 bar: 2` is equivalent to `window foo: 1 baz: 2`.!
-
-!JSObjectProxy methodsFor: 'accessing'!
-
-at: aString
-	<return self['@jsObject'][aString]>
-!
-
-at: aString ifAbsent: aBlock
-	"return the aString property or evaluate aBlock if the property is not defined on the object"
-	<
-		var obj = self['@jsObject'];
-		return aString in obj ? obj[aString] : aBlock._value();
-	>
-!
-
-at: aString ifPresent: aBlock
-	"return the evaluation of aBlock with the value if the property is defined or return nil"
-	<
-		var obj = self['@jsObject'];
-		return aString in obj ? aBlock._value_(obj[aString]) : nil;
-	>
-!
-
-at: aString ifPresent: aBlock ifAbsent: anotherBlock
-	"return the evaluation of aBlock with the value if the property is defined
-	or return value of anotherBlock"
-	<
-		var obj = self['@jsObject'];
-		return aString in obj ? aBlock._value_(obj[aString]) : anotherBlock._value();
-	>
-!
-
-at: aString put: anObject
-	<self['@jsObject'][aString] = anObject>
-!
-
-jsObject
-	^ jsObject
-!
-
-jsObject: aJSObject
-	jsObject := aJSObject
-!
-
-lookupProperty: aString
-	"Looks up a property in JS object.
-	Answer the property if it is present, or nil if it is not present."
-	
-	<return aString in self._jsObject() ? aString : nil>
-!
-
-value
-	"if attribute 'value' exists on the JS object return it,
-	otherwise return the result of Object>>value."
-	
-	^ self 
-		at: 'value' 
-		ifAbsent: [ super value ]
-! !
-
-!JSObjectProxy methodsFor: 'enumerating'!
-
-asJSON
-	"Answers the receiver in a stringyfy-friendly fashion"
-
-	^ jsObject
-!
-
-keysAndValuesDo: aBlock
-	<
-		var o = self['@jsObject'];
-		for(var i in o) {
-			aBlock._value_value_(i, o[i]);
-		}
-	>
-! !
-
-!JSObjectProxy methodsFor: 'printing'!
-
-printOn: aStream
-	aStream nextPutAll: self printString
-!
-
-printString
-	<
-		var js = self['@jsObject'];
-		return js.toString
-			? js.toString()
-			: Object.prototype.toString.call(js)
-	>
-! !
-
-!JSObjectProxy methodsFor: 'proxy'!
-
-addObjectVariablesTo: aDictionary
-	<
-		for(var i in self['@jsObject']) {
-			aDictionary._at_put_(i, self['@jsObject'][i]);
-		}
-	>
-!
-
-doesNotUnderstand: aMessage
-	^ (self lookupProperty: aMessage selector asJavaScriptSelector)
-		ifNil: [ super doesNotUnderstand: aMessage ]
-		ifNotNil: [ :jsSelector | 
-			self 
-				forwardMessage: jsSelector 
-				withArguments: aMessage arguments ]
-!
-
-forwardMessage: aString withArguments: anArray
-	<
-		return smalltalk.send(self._jsObject(), aString, anArray);
-	>
-!
-
-inspectOn: anInspector
-	| variables |
-	variables := Dictionary new.
-	variables at: '#self' put: self jsObject.
-	anInspector setLabel: self printString.
-	self addObjectVariablesTo: variables.
-	anInspector setVariables: variables
-! !
-
-!JSObjectProxy class methodsFor: 'instance creation'!
-
-on: aJSObject
-	^ self new
-		jsObject: aJSObject;
-		yourself
-! !
-
 Object subclass: #Organizer
 	instanceVariableNames: ''
 	package: 'Kernel-Infrastructure'!

+ 5 - 11
st/Kernel-Objects.st

@@ -59,11 +59,11 @@ class
 
 identityHash
 	<
-	var hash=self.identityHash;
-	if (hash) return hash;
-	hash=smalltalk.nextId();
-	Object.defineProperty(self, 'identityHash', {value:hash});
-	return hash;
+		var hash=self.identityHash;
+		if (hash) return hash;
+		hash=smalltalk.nextId();
+		Object.defineProperty(self, 'identityHash', {value:hash});
+		return hash;
 	>
 !
 
@@ -129,12 +129,6 @@ asJavascript
 
 asString
 	^ self printString
-!
-
-test
-	| a |
-	a := 1.
-	self halt
 ! !
 
 !Object methodsFor: 'copying'!

+ 0 - 1
st/Kernel-Tests.st

@@ -1264,7 +1264,6 @@ testPropertyThatReturnsUndefined
 testValue
 	| testObject |
 	testObject := self jsObject.
-	self assert: testObject value printString equals: '[object Object]'.
 	testObject at: 'value' put: 'aValue'.
 	self assert: testObject value equals: 'aValue'
 !