1
0
Преглед на файлове

- Better error handling taking advantage of message sends
- MethodContext & thisContext are now working (temps still missing)
- unhandled errors now log a stacktrace
- Rendering widgets do not add an extra surrounding div anymore

Nicolas Petton преди 13 години
родител
ревизия
2737561109
променени са 15 файла, в които са добавени 984 реда и са изтрити 192 реда
  1. 70 10
      js/Canvas.js
  2. 12 12
      js/Compiler.js
  3. 1 1
      js/Examples.js
  4. 168 38
      js/IDE.js
  5. 47 18
      js/JQuery.js
  6. 286 4
      js/Kernel.js
  7. 16 16
      js/Parser.js
  8. 27 11
      js/SUnit.js
  9. 103 16
      js/boot.js
  10. 26 3
      st/Canvas.st
  11. 3 2
      st/Compiler.st
  12. 86 37
      st/IDE.st
  13. 24 15
      st/JQuery.st
  14. 103 2
      st/Kernel.st
  15. 12 7
      st/SUnit.st

+ 70 - 10
js/Canvas.js

@@ -265,11 +265,11 @@ category: 'initialization',
 fn: function (){
 var self=this;
 smalltalk.send(self, "_initialize", [], smalltalk.Object);
-self['@root']=smalltalk.send(smalltalk.TagBrush, "_fromString_canvas_", ["div", self]);
+smalltalk.send(self['@root'], "_ifNil_", [(function(){return self['@root']=smalltalk.send(smalltalk.TagBrush, "_fromString_canvas_", ["div", self]);})]);
 return self;},
-source: unescape('initialize%0A%20%20%20%20super%20initialize.%0A%20%20%20%20root%20%3A%3D%20TagBrush%20fromString%3A%20%27div%27%20canvas%3A%20self'),
-messageSends: ["initialize", "fromString:canvas:"],
-referencedClasses: [smalltalk.TagBrush]
+source: unescape('initialize%0A%20%20%20%20super%20initialize.%0A%20%20%20%20root%20ifNil%3A%20%5Broot%20%3A%3D%20TagBrush%20fromString%3A%20%27div%27%20canvas%3A%20self%5D'),
+messageSends: ["initialize", "ifNil:", "fromString:canvas:"],
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.HTMLCanvas);
 
@@ -299,7 +299,7 @@ return smalltalk.send(smalltalk.TagBrush, "_fromString_canvas_", [aString, self]
 return self;},
 source: unescape('newTag%3A%20aString%0A%20%20%20%20%5ETagBrush%20fromString%3A%20aString%20canvas%3A%20self'),
 messageSends: ["fromString:canvas:"],
-referencedClasses: [smalltalk.TagBrush]
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.HTMLCanvas);
 
@@ -693,6 +693,36 @@ referencedClasses: []
 }),
 smalltalk.HTMLCanvas);
 
+smalltalk.addMethod(
+'_initializeFromJQuery_',
+smalltalk.method({
+selector: 'initializeFromJQuery:',
+category: 'initialization',
+fn: function (aJQuery){
+var self=this;
+self['@root']=smalltalk.send(smalltalk.TagBrush, "_fromJQuery_canvas_", [aJQuery, self]);
+return self;},
+source: unescape('initializeFromJQuery%3A%20aJQuery%0A%20%20%20%20root%20%3A%3D%20TagBrush%20fromJQuery%3A%20aJQuery%20canvas%3A%20self'),
+messageSends: ["fromJQuery:canvas:"],
+referencedClasses: [smalltalk.nil]
+}),
+smalltalk.HTMLCanvas);
+
+
+smalltalk.addMethod(
+'_onJQuery_',
+smalltalk.method({
+selector: 'onJQuery:',
+category: 'instance creation',
+fn: function (aJQuery){
+var self=this;
+return (function($rec){smalltalk.send($rec, "_initializeFromJQuery_", [aJQuery]);smalltalk.send($rec, "_initialize", []);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(self, "_basicNew", []));
+return self;},
+source: unescape('onJQuery%3A%20aJQuery%0A%09%5Eself%20basicNew%0A%09%09initializeFromJQuery%3A%20aJQuery%3B%0A%09%09initialize%3B%0A%09%09yourself'),
+messageSends: ["initializeFromJQuery:", "initialize", "yourself", "basicNew"],
+referencedClasses: []
+}),
+smalltalk.HTMLCanvas.klass);
 
 
 smalltalk.addClass('TagBrush', smalltalk.Object, ['canvas', 'element'], 'Canvas');
@@ -1138,6 +1168,22 @@ referencedClasses: []
 }),
 smalltalk.TagBrush);
 
+smalltalk.addMethod(
+'_initializeFromJQuery_canvas_',
+smalltalk.method({
+selector: 'initializeFromJQuery:canvas:',
+category: 'initialization',
+fn: function (aJQuery, aCanvas){
+var self=this;
+self['@element']=smalltalk.send(smalltalk.send(aJQuery, "_jquery", []), "_get_", [(0)]);
+self['@canvas']=aCanvas;
+return self;},
+source: unescape('initializeFromJQuery%3A%20aJQuery%20canvas%3A%20aCanvas%0A%20%20%20%20element%20%3A%3D%20aJQuery%20jquery%20get%3A%200.%0A%20%20%20%20canvas%20%3A%3D%20aCanvas'),
+messageSends: ["get:", "jquery"],
+referencedClasses: []
+}),
+smalltalk.TagBrush);
+
 
 smalltalk.addMethod(
 '_fromString_canvas_',
@@ -1154,6 +1200,21 @@ referencedClasses: []
 }),
 smalltalk.TagBrush.klass);
 
+smalltalk.addMethod(
+'_fromJQuery_canvas_',
+smalltalk.method({
+selector: 'fromJQuery:canvas:',
+category: 'instance creation',
+fn: function (aJQuery, aCanvas){
+var self=this;
+return (function($rec){smalltalk.send($rec, "_initializeFromJQuery_canvas_", [aJQuery, aCanvas]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(self, "_new", []));
+return self;},
+source: unescape('fromJQuery%3A%20aJQuery%20canvas%3A%20aCanvas%0A%20%20%20%20%5Eself%20new%0A%09initializeFromJQuery%3A%20aJQuery%20canvas%3A%20aCanvas%3B%0A%09yourself'),
+messageSends: ["initializeFromJQuery:canvas:", "yourself", "new"],
+referencedClasses: []
+}),
+smalltalk.TagBrush.klass);
+
 
 smalltalk.addClass('Widget', smalltalk.Object, ['root'], 'Canvas');
 smalltalk.addMethod(
@@ -1193,12 +1254,11 @@ selector: 'appendToJQuery:',
 category: 'adding',
 fn: function (aJQuery){
 var self=this;
-smalltalk.send(self, "_render", []);
-smalltalk.send(aJQuery, "_append_", [smalltalk.send(smalltalk.send(self, "_root", []), "_asJQuery", [])]);
+smalltalk.send(self, "_renderOn_", [smalltalk.send(smalltalk.HTMLCanvas, "_onJQuery_", [aJQuery])]);
 return self;},
-source: unescape('appendToJQuery%3A%20aJQuery%0A%20%20%20%20self%20render.%0A%20%20%20%20aJQuery%20append%3A%20self%20root%20asJQuery'),
-messageSends: ["render", "append:", "asJQuery", "root"],
-referencedClasses: []
+source: unescape('appendToJQuery%3A%20aJQuery%0A%20%20%20self%20renderOn%3A%20%28HTMLCanvas%20onJQuery%3A%20aJQuery%29'),
+messageSends: ["renderOn:", "onJQuery:"],
+referencedClasses: [smalltalk.HTMLCanvas]
 }),
 smalltalk.Widget);
 

+ 12 - 12
js/Compiler.js

@@ -288,7 +288,7 @@ return (function($rec){smalltalk.send($rec, "_receiver_", [smalltalk.send(self,
 return self;},
 source: unescape('cascadeNodeWithMessages%3A%20aCollection%0A%09%7C%20first%20%7C%0A%09first%20%3A%3D%20SendNode%20new%0A%09%20%20%20%20selector%3A%20self%20selector%3B%0A%09%20%20%20%20arguments%3A%20self%20arguments%3B%0A%09%20%20%20%20yourself.%0A%09%5ECascadeNode%20new%0A%09%20%20%20%20receiver%3A%20self%20receiver%3B%0A%09%20%20%20%20nodes%3A%20%28Array%20with%3A%20first%29%2C%20aCollection%3B%0A%09%20%20%20%20yourself'),
 messageSends: ["selector:", "selector", "arguments:", "arguments", "yourself", "new", "receiver:", "receiver", "nodes:", unescape("%2C"), "with:"],
-referencedClasses: [smalltalk.SendNode,smalltalk.Array,smalltalk.nil]
+referencedClasses: [smalltalk.SendNode,smalltalk.Array,smalltalk.CascadeNode]
 }),
 smalltalk.SendNode);
 
@@ -525,7 +525,7 @@ return (function($rec){smalltalk.send($rec, "_nodes_", [smalltalk.send(self, "_n
 return self;},
 source: unescape('asBlockSequenceNode%0A%09%5EBlockSequenceNode%20new%0A%09%20%20%20%20nodes%3A%20self%20nodes%3B%0A%09%20%20%20%20temps%3A%20self%20temps%3B%0A%09%20%20%20%20yourself'),
 messageSends: ["nodes:", "nodes", "temps:", "temps", "yourself", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.BlockSequenceNode]
 }),
 smalltalk.SequenceNode);
 
@@ -1005,7 +1005,7 @@ return smalltalk.send(smalltalk.send(smalltalk.DoIt, "_new", []), "_doIt", []);
 return self;},
 source: unescape('loadExpression%3A%20aString%0A%09DoIt%20addCompiledMethod%3A%20%28self%20eval%3A%20%28self%20compileExpression%3A%20aString%29%29.%0A%09%5EDoIt%20new%20doIt'),
 messageSends: ["addCompiledMethod:", "eval:", "compileExpression:", "doIt", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.DoIt]
 }),
 smalltalk.Compiler);
 
@@ -1055,7 +1055,7 @@ return smalltalk.send(self, "_compileNode_", [smalltalk.send(self, "_parseExpres
 return self;},
 source: unescape('compileExpression%3A%20aString%0A%09self%20currentClass%3A%20DoIt.%0A%09%5Eself%20compileNode%3A%20%28self%20parseExpression%3A%20aString%29'),
 messageSends: ["currentClass:", "compileNode:", "parseExpression:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.DoIt]
 }),
 smalltalk.Compiler);
 
@@ -1478,11 +1478,11 @@ selector: 'recompileAll',
 category: 'compiling',
 fn: function (){
 var self=this;
-smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.Smalltalk, "_current", []), "_classes", []), "_do_", [(function(each){return smalltalk.send(self, "_recompile_", [each]);})]);
+smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.Smalltalk, "_current", []), "_classes", []), "_do_", [(function(each){(function($rec){smalltalk.send($rec, "_show_", [each]);return smalltalk.send($rec, "_cr", []);})(smalltalk.Transcript);return smalltalk.send((function(){return smalltalk.send(self, "_recompile_", [each]);}), "_valueWithTimeout_", [(100)]);})]);
 return self;},
-source: unescape('recompileAll%0A%09Smalltalk%20current%20classes%20do%3A%20%5B%3Aeach%20%7C%0A%09%09self%20recompile%3A%20each%5D'),
-messageSends: ["do:", "classes", "current", "recompile:"],
-referencedClasses: [smalltalk.Smalltalk]
+source: unescape('recompileAll%0A%09Smalltalk%20current%20classes%20do%3A%20%5B%3Aeach%20%7C%0A%09%09Transcript%20show%3A%20each%3B%20cr.%0A%09%09%5Bself%20recompile%3A%20each%5D%20valueWithTimeout%3A%20100%5D'),
+messageSends: ["do:", "classes", "current", "show:", "cr", "valueWithTimeout:", "recompile:"],
+referencedClasses: [smalltalk.Smalltalk,smalltalk.Transcript]
 }),
 smalltalk.Compiler);
 
@@ -1573,11 +1573,11 @@ selector: 'doIt',
 category: '',
 fn: function (){
 var self=this;
-return smalltalk.send((function(){return self["@"+'foo'];}), "_value", []);
+return smalltalk.send((function(){return smalltalk.send(smalltalk.send(smalltalk.Compiler, "_new", []), "_recompileAll", []);}), "_value", []);
 return self;},
-source: unescape('doIt%20%5E%5B%3Cself%5B%22@%22+%27foo%27%5D%3E%5D%20value'),
-messageSends: ["value"],
-referencedClasses: []
+source: unescape('doIt%20%5E%5BCompiler%20new%20recompileAll%5D%20value'),
+messageSends: ["value", "recompileAll", "new"],
+referencedClasses: [smalltalk.Compiler]
 }),
 smalltalk.DoIt);
 

+ 1 - 1
js/Examples.js

@@ -271,7 +271,7 @@ self['@movingPiece']=smalltalk.send(smalltalk.TetrisPiece, "_atRandom", []);
 return self;},
 source: unescape('newPiece%0A%09movingPiece%20%3A%3D%20TetrisPiece%20atRandom'),
 messageSends: ["atRandom"],
-referencedClasses: []
+referencedClasses: [smalltalk.TetrisPiece]
 }),
 smalltalk.Tetris);
 

+ 168 - 38
js/IDE.js

@@ -1,4 +1,4 @@
-smalltalk.addClass('TabManager', smalltalk.Widget, ['selectedTab', 'tabs', 'opened'], 'IDE');
+smalltalk.addClass('TabManager', smalltalk.Widget, ['selectedTab', 'tabs', 'opened', 'ul'], 'IDE');
 smalltalk.addMethod(
 '_tabs',
 smalltalk.method({
@@ -115,10 +115,10 @@ selector: 'open',
 category: 'actions',
 fn: function (){
 var self=this;
-smalltalk.send(self['@opened'], "_ifFalse_", [(function(){smalltalk.send(smalltalk.send(smalltalk.send(self, "_root", []), "_asJQuery", []), "_show", []);smalltalk.send(smalltalk.send("body", "_asJQuery", []), "_addClass_", ["jtalkBody"]);smalltalk.send(smalltalk.send(unescape("%23jtalk"), "_asJQuery", []), "_show", []);smalltalk.send(self, "_updateBodyMargin", []);smalltalk.send(smalltalk.send(smalltalk.send(self['@selectedTab'], "_root", []), "_asJQuery", []), "_show", []);return self['@opened']=true;})]);
+smalltalk.send(self['@opened'], "_ifFalse_", [(function(){smalltalk.send(smalltalk.send("body", "_asJQuery", []), "_addClass_", ["jtalkBody"]);smalltalk.send(smalltalk.send(unescape("%23jtalk"), "_asJQuery", []), "_show", []);smalltalk.send(smalltalk.send(self['@ul'], "_asJQuery", []), "_show", []);smalltalk.send(self, "_updateBodyMargin", []);smalltalk.send(self['@selectedTab'], "_show", []);return self['@opened']=true;})]);
 return self;},
-source: unescape('open%0A%20%20%20%20opened%20ifFalse%3A%20%5B%0A%09self%20root%20asJQuery%20show.%0A%09%27body%27%20asJQuery%20addClass%3A%20%27jtalkBody%27.%0A%09%27%23jtalk%27%20asJQuery%20show.%0A%09self%20updateBodyMargin.%0A%09selectedTab%20root%20asJQuery%20show.%0A%09opened%20%3A%3D%20true%5D'),
-messageSends: ["ifFalse:", "show", "asJQuery", "root", "addClass:", "updateBodyMargin"],
+source: unescape('open%0A%20%20%20%20opened%20ifFalse%3A%20%5B%0A%09%27body%27%20asJQuery%20addClass%3A%20%27jtalkBody%27.%0A%09%27%23jtalk%27%20asJQuery%20show.%0A%09ul%20asJQuery%20show.%0A%09self%20updateBodyMargin.%0A%09selectedTab%20show.%0A%09opened%20%3A%3D%20true%5D'),
+messageSends: ["ifFalse:", "addClass:", "asJQuery", "show", "updateBodyMargin"],
 referencedClasses: []
 }),
 smalltalk.TabManager);
@@ -130,10 +130,10 @@ selector: 'close',
 category: 'actions',
 fn: function (){
 var self=this;
-smalltalk.send(self['@opened'], "_ifTrue_", [(function(){smalltalk.send(smalltalk.send(smalltalk.send(self, "_root", []), "_asJQuery", []), "_hide", []);smalltalk.send(smalltalk.send(unescape("%23jtalk"), "_asJQuery", []), "_hide", []);smalltalk.send(self, "_removeBodyMargin", []);smalltalk.send(smalltalk.send("body", "_asJQuery", []), "_removeClass_", ["jtalkBody"]);return self['@opened']=false;})]);
+smalltalk.send(self['@opened'], "_ifTrue_", [(function(){smalltalk.send(smalltalk.send(unescape("%23jtalk"), "_asJQuery", []), "_hide", []);smalltalk.send(smalltalk.send(self['@ul'], "_asJQuery", []), "_hide", []);smalltalk.send(self['@selectedTab'], "_hide", []);smalltalk.send(self, "_removeBodyMargin", []);smalltalk.send(smalltalk.send("body", "_asJQuery", []), "_removeClass_", ["jtalkBody"]);return self['@opened']=false;})]);
 return self;},
-source: unescape('close%0A%20%20%20%20opened%20ifTrue%3A%20%5B%0A%09self%20root%20asJQuery%20hide.%0A%09%27%23jtalk%27%20asJQuery%20hide.%0A%09self%20removeBodyMargin.%0A%09%27body%27%20asJQuery%20removeClass%3A%20%27jtalkBody%27.%0A%09opened%20%3A%3D%20false%5D'),
-messageSends: ["ifTrue:", "hide", "asJQuery", "root", "removeBodyMargin", "removeClass:"],
+source: unescape('close%0A%20%20%20%20opened%20ifTrue%3A%20%5B%0A%09%27%23jtalk%27%20asJQuery%20hide.%0A%09ul%20asJQuery%20hide.%0A%09selectedTab%20hide.%0A%09self%20removeBodyMargin.%0A%09%27body%27%20asJQuery%20removeClass%3A%20%27jtalkBody%27.%0A%09opened%20%3A%3D%20false%5D'),
+messageSends: ["ifTrue:", "hide", "asJQuery", "removeBodyMargin", "removeClass:"],
 referencedClasses: []
 }),
 smalltalk.TabManager);
@@ -149,7 +149,7 @@ smalltalk.send(smalltalk.Browser, "_open", []);
 return self;},
 source: unescape('newBrowserTab%0A%20%20%20%20Browser%20open'),
 messageSends: ["open"],
-referencedClasses: []
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.TabManager);
 
@@ -162,12 +162,12 @@ fn: function (aWidget){
 var self=this;
 smalltalk.send(self, "_open", []);
 self['@selectedTab']=aWidget;
-smalltalk.send(smalltalk.send(self, "_tabs", []), "_do_", [(function(each){return smalltalk.send(smalltalk.send(smalltalk.send(each, "_root", []), "_asJQuery", []), "_hide", []);})]);
-smalltalk.send(smalltalk.send(smalltalk.send(aWidget, "_root", []), "_asJQuery", []), "_show", []);
+smalltalk.send(smalltalk.send(self, "_tabs", []), "_do_", [(function(each){return smalltalk.send(each, "_hide", []);})]);
+smalltalk.send(aWidget, "_show", []);
 smalltalk.send(self, "_update", []);
 return self;},
-source: unescape('selectTab%3A%20aWidget%0A%20%20%20%20self%20open.%0A%20%20%20%20selectedTab%20%3A%3D%20aWidget.%0A%20%20%20%20self%20tabs%20do%3A%20%5B%3Aeach%20%7C%0A%09each%20root%20asJQuery%20hide%5D.%0A%20%20%20%20aWidget%20root%20asJQuery%20show.%0A%20%20%20%20self%20update'),
-messageSends: ["open", "do:", "tabs", "hide", "asJQuery", "root", "show", "update"],
+source: unescape('selectTab%3A%20aWidget%0A%20%20%20%20self%20open.%0A%20%20%20%20selectedTab%20%3A%3D%20aWidget.%0A%20%20%20%20self%20tabs%20do%3A%20%5B%3Aeach%20%7C%0A%09each%20hide%5D.%0A%20%20%20%20aWidget%20show.%0A%09%0A%20%20%20%20self%20update'),
+messageSends: ["open", "do:", "tabs", "hide", "show", "update"],
 referencedClasses: []
 }),
 smalltalk.TabManager);
@@ -181,11 +181,11 @@ fn: function (aWidget){
 var self=this;
 smalltalk.send(self, "_removeTab_", [aWidget]);
 smalltalk.send(self, "_selectTab_", [smalltalk.send(smalltalk.send(self, "_tabs", []), "_last", [])]);
-smalltalk.send(smalltalk.send(smalltalk.send(aWidget, "_root", []), "_asJQuery", []), "_remove", []);
+smalltalk.send(aWidget, "_remove", []);
 smalltalk.send(self, "_update", []);
 return self;},
-source: unescape('closeTab%3A%20aWidget%0A%20%20%20%20self%20removeTab%3A%20aWidget.%0A%20%20%20%20self%20selectTab%3A%20self%20tabs%20last.%0A%20%20%20%20aWidget%20root%20asJQuery%20remove.%0A%20%20%20%20self%20update'),
-messageSends: ["removeTab:", "selectTab:", "last", "tabs", "remove", "asJQuery", "root", "update"],
+source: unescape('closeTab%3A%20aWidget%0A%20%20%20%20self%20removeTab%3A%20aWidget.%0A%20%20%20%20self%20selectTab%3A%20self%20tabs%20last.%0A%20%20%20%20aWidget%20remove.%0A%20%20%20%20self%20update'),
+messageSends: ["removeTab:", "selectTab:", "last", "tabs", "remove", "update"],
 referencedClasses: []
 }),
 smalltalk.TabManager);
@@ -199,10 +199,10 @@ fn: function (aWidget){
 var self=this;
 smalltalk.send(smalltalk.send(self, "_tabs", []), "_add_", [aWidget]);
 smalltalk.send(smalltalk.send(unescape("%23jtalk"), "_asJQuery", []), "_append_", [aWidget]);
-smalltalk.send(smalltalk.send(smalltalk.send(aWidget, "_root", []), "_asJQuery", []), "_hide", []);
+smalltalk.send(aWidget, "_hide", []);
 return self;},
-source: unescape('addTab%3A%20aWidget%0A%20%20%20%20self%20tabs%20add%3A%20aWidget.%0A%20%20%20%20%27%23jtalk%27%20asJQuery%20append%3A%20aWidget.%0A%20%20%20%20aWidget%20root%20asJQuery%20hide'),
-messageSends: ["add:", "tabs", "append:", "asJQuery", "hide", "root"],
+source: unescape('addTab%3A%20aWidget%0A%20%20%20%20self%20tabs%20add%3A%20aWidget.%0A%20%20%20%20%27%23jtalk%27%20asJQuery%20append%3A%20aWidget.%0A%20%20%20%20aWidget%20hide'),
+messageSends: ["add:", "tabs", "append:", "asJQuery", "hide"],
 referencedClasses: []
 }),
 smalltalk.TabManager);
@@ -239,7 +239,7 @@ smalltalk.send(self, "_selectTab_", [smalltalk.send(smalltalk.send(self, "_tabs"
 return self;},
 source: unescape('initialize%0A%20%20%20%20super%20initialize.%0A%20%20%20%20opened%20%3A%3D%20true.%0A%20%20%20%20%27body%27%20asJQuery%20%0A%09append%3A%20self%3B%0A%09append%3A%20%5B%3Ahtml%20%7C%20html%20div%20id%3A%20%27jtalk%27%5D%3B%0A%09addClass%3A%20%27jtalkBody%27.%0A%20%20%20%20self%20%0A%09addTab%3A%20Transcript%20current%3B%0A%09addTab%3A%20Workspace%20new.%0A%20%20%20%20self%20selectTab%3A%20self%20tabs%20last.%0A%20%20%20%20self%20%0A%09onResize%3A%20%5Bself%20updateBodyMargin%3B%20updatePosition%5D%3B%0A%09onWindowResize%3A%20%5Bself%20updatePosition%5D'),
 messageSends: ["initialize", "append:", "id:", "div", "addClass:", "asJQuery", "addTab:", "current", "new", "selectTab:", "last", "tabs", "onResize:", "updateBodyMargin", "updatePosition", "onWindowResize:"],
-referencedClasses: []
+referencedClasses: [smalltalk.nil,smalltalk.nil]
 }),
 smalltalk.TabManager);
 
@@ -250,10 +250,11 @@ selector: 'renderOn:',
 category: 'rendering',
 fn: function (html){
 var self=this;
-(function($rec){smalltalk.send($rec, "_id_", ["jtalkTabs"]);return smalltalk.send($rec, "_with_", [(function(){(function($rec){smalltalk.send($rec, "_class_", ["closeAll"]);smalltalk.send($rec, "_with_", ["x"]);return smalltalk.send($rec, "_onClick_", [(function(){return smalltalk.send(self, "_close", []);})]);})(smalltalk.send(html, "_li", []));smalltalk.send(smalltalk.send(self, "_tabs", []), "_do_", [(function(each){return smalltalk.send(self, "_renderTabFor_on_", [each, html]);})]);return (function($rec){smalltalk.send($rec, "_class_", ["newtab"]);smalltalk.send($rec, "_with_", [unescape("%20+%20")]);return smalltalk.send($rec, "_onClick_", [(function(){return smalltalk.send(self, "_newBrowserTab", []);})]);})(smalltalk.send(html, "_li", []));})]);})(smalltalk.send(html, "_ul", []));
+self['@ul']=(function($rec){smalltalk.send($rec, "_id_", ["jtalkTabs"]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(html, "_ul", []));
+smalltalk.send(self, "_renderTabs", []);
 return self;},
-source: unescape('renderOn%3A%20html%0A%20%20%20%20html%20ul%0A%09id%3A%20%27jtalkTabs%27%3B%0A%09with%3A%20%5B%0A%09%20%20%20%20html%20li%20%0A%09%09class%3A%20%27closeAll%27%3B%0A%09%09with%3A%20%27x%27%3B%0A%09%09onClick%3A%20%5Bself%20close%5D.%0A%09%20%20%20%20self%20tabs%20do%3A%20%5B%3Aeach%20%7C%0A%09%09self%20renderTabFor%3A%20each%20on%3A%20html%5D.%0A%09%20%20%20%20html%20li%0A%09%09class%3A%20%27newtab%27%3B%0A%09%09with%3A%20%27%20+%20%27%3B%0A%09%09onClick%3A%20%5Bself%20newBrowserTab%5D%5D'),
-messageSends: ["id:", "with:", "class:", "onClick:", "close", "li", "do:", "tabs", "renderTabFor:on:", "newBrowserTab", "ul"],
+source: unescape('renderOn%3A%20html%0A%09ul%20%3A%3D%20html%20ul%0A%09%09id%3A%20%27jtalkTabs%27%3B%0A%09%09yourself.%0A%09self%20renderTabs'),
+messageSends: ["id:", "yourself", "ul", "renderTabs"],
 referencedClasses: []
 }),
 smalltalk.TabManager);
@@ -276,6 +277,36 @@ referencedClasses: []
 }),
 smalltalk.TabManager);
 
+smalltalk.addMethod(
+'_renderTabs',
+smalltalk.method({
+selector: 'renderTabs',
+category: 'rendering',
+fn: function (){
+var self=this;
+smalltalk.send(self['@ul'], "_contents_", [(function(html){(function($rec){smalltalk.send($rec, "_class_", ["closeAll"]);smalltalk.send($rec, "_with_", ["x"]);return smalltalk.send($rec, "_onClick_", [(function(){return smalltalk.send(self, "_close", []);})]);})(smalltalk.send(html, "_li", []));smalltalk.send(smalltalk.send(self, "_tabs", []), "_do_", [(function(each){return smalltalk.send(self, "_renderTabFor_on_", [each, html]);})]);return (function($rec){smalltalk.send($rec, "_class_", ["newtab"]);smalltalk.send($rec, "_with_", [unescape("%20+%20")]);return smalltalk.send($rec, "_onClick_", [(function(){return smalltalk.send(self, "_newBrowserTab", []);})]);})(smalltalk.send(html, "_li", []));})]);
+return self;},
+source: unescape('renderTabs%0A%09ul%20contents%3A%20%5B%3Ahtml%20%7C%0A%09%20%20%20%20html%20li%20%0A%09%09class%3A%20%27closeAll%27%3B%0A%09%09with%3A%20%27x%27%3B%0A%09%09onClick%3A%20%5Bself%20close%5D.%0A%09%20%20%20%20self%20tabs%20do%3A%20%5B%3Aeach%20%7C%0A%09%09self%20renderTabFor%3A%20each%20on%3A%20html%5D.%0A%09%20%20%20%20html%20li%0A%09%09class%3A%20%27newtab%27%3B%0A%09%09with%3A%20%27%20+%20%27%3B%0A%09%09onClick%3A%20%5Bself%20newBrowserTab%5D%5D'),
+messageSends: ["contents:", "class:", "with:", "onClick:", "close", "li", "do:", "tabs", "renderTabFor:on:", "newBrowserTab"],
+referencedClasses: []
+}),
+smalltalk.TabManager);
+
+smalltalk.addMethod(
+'_update',
+smalltalk.method({
+selector: 'update',
+category: 'updating',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_renderTabs", []);
+return self;},
+source: unescape('update%0A%09self%20renderTabs'),
+messageSends: ["renderTabs"],
+referencedClasses: []
+}),
+smalltalk.TabManager);
+
 
 smalltalk.TabManager.klass.iVarNames = ['current'];
 smalltalk.addMethod(
@@ -309,7 +340,7 @@ referencedClasses: []
 smalltalk.TabManager.klass);
 
 
-smalltalk.addClass('TabWidget', smalltalk.Widget, [], 'IDE');
+smalltalk.addClass('TabWidget', smalltalk.Widget, ['div'], 'IDE');
 smalltalk.addMethod(
 '_label',
 smalltalk.method({
@@ -332,10 +363,11 @@ selector: 'open',
 category: 'actions',
 fn: function (){
 var self=this;
-(function($rec){smalltalk.send($rec, "_addTab_", [self]);return smalltalk.send($rec, "_selectTab_", [self]);})(smalltalk.send(smalltalk.TabManager, "_current", []));
+smalltalk.send(smalltalk.send(smalltalk.TabManager, "_current", []), "_addTab_", [self]);
+smalltalk.send(smalltalk.send(smalltalk.TabManager, "_current", []), "_selectTab_", [self]);
 return self;},
-source: unescape('open%0A%20%20%20%20TabManager%20current%0A%09addTab%3A%20self%3B%0A%09selectTab%3A%20self'),
-messageSends: ["addTab:", "selectTab:", "current"],
+source: unescape('open%0A%20%20%20%20TabManager%20current%20addTab%3A%20self.%0A%20%20%20%20TabManager%20current%20selectTab%3A%20self'),
+messageSends: ["addTab:", "current", "selectTab:"],
 referencedClasses: [smalltalk.TabManager]
 }),
 smalltalk.TabWidget);
@@ -347,10 +379,11 @@ selector: 'renderOn:',
 category: 'rendering',
 fn: function (html){
 var self=this;
-(function($rec){smalltalk.send($rec, "_class_", ["jtalkTool"]);return smalltalk.send($rec, "_with_", [(function(){(function($rec){smalltalk.send($rec, "_class_", ["jt_box"]);return smalltalk.send($rec, "_with_", [(function(){return smalltalk.send(self, "_renderBoxOn_", [html]);})]);})(smalltalk.send(html, "_div", []));return (function($rec){smalltalk.send($rec, "_class_", ["jt_buttons"]);return smalltalk.send($rec, "_with_", [(function(){return smalltalk.send(self, "_renderButtonsOn_", [html]);})]);})(smalltalk.send(html, "_div", []));})]);})(smalltalk.send(html, "_root", []));
+self['@div']=(function($rec){smalltalk.send($rec, "_class_", ["jtalkTool"]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(html, "_div", []));
+smalltalk.send(self, "_renderTab", []);
 return self;},
-source: unescape('renderOn%3A%20html%0A%20%20%20%20html%20root%0A%09class%3A%20%27jtalkTool%27%3B%0A%09with%3A%20%5B%0A%09%20%20%20%20html%20div%0A%09%09class%3A%20%27jt_box%27%3B%0A%09%09with%3A%20%5Bself%20renderBoxOn%3A%20html%5D.%0A%09%20%20%20%20html%20div%0A%09%09class%3A%20%27jt_buttons%27%3B%0A%09%09with%3A%20%5Bself%20renderButtonsOn%3A%20html%5D%5D'),
-messageSends: ["class:", "with:", "renderBoxOn:", "div", "renderButtonsOn:", "root"],
+source: unescape('renderOn%3A%20html%0A%09div%20%3A%3D%20html%20div%0A%09%09class%3A%20%27jtalkTool%27%3B%0A%09%09yourself.%0A%09self%20renderTab'),
+messageSends: ["class:", "yourself", "div", "renderTab"],
 referencedClasses: []
 }),
 smalltalk.TabWidget);
@@ -400,6 +433,81 @@ referencedClasses: []
 }),
 smalltalk.TabWidget);
 
+smalltalk.addMethod(
+'_show',
+smalltalk.method({
+selector: 'show',
+category: 'actions',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self['@div'], "_asJQuery", []), "_show", []);
+return self;},
+source: unescape('show%0A%09div%20asJQuery%20show'),
+messageSends: ["show", "asJQuery"],
+referencedClasses: []
+}),
+smalltalk.TabWidget);
+
+smalltalk.addMethod(
+'_hide',
+smalltalk.method({
+selector: 'hide',
+category: 'actions',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self['@div'], "_asJQuery", []), "_hide", []);
+return self;},
+source: unescape('hide%0A%09div%20asJQuery%20hide'),
+messageSends: ["hide", "asJQuery"],
+referencedClasses: []
+}),
+smalltalk.TabWidget);
+
+smalltalk.addMethod(
+'_update',
+smalltalk.method({
+selector: 'update',
+category: 'rendering',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_renderTab", []);
+return self;},
+source: unescape('update%0A%09self%20renderTab'),
+messageSends: ["renderTab"],
+referencedClasses: []
+}),
+smalltalk.TabWidget);
+
+smalltalk.addMethod(
+'_remove',
+smalltalk.method({
+selector: 'remove',
+category: 'actions',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.send(self['@div'], "_asJQuery", []), "_remove", []);
+return self;},
+source: unescape('remove%0A%09div%20asJQuery%20remove'),
+messageSends: ["remove", "asJQuery"],
+referencedClasses: []
+}),
+smalltalk.TabWidget);
+
+smalltalk.addMethod(
+'_renderTab',
+smalltalk.method({
+selector: 'renderTab',
+category: 'rendering',
+fn: function (){
+var self=this;
+smalltalk.send(self['@div'], "_contents_", [(function(html){(function($rec){smalltalk.send($rec, "_class_", ["jt_box"]);return smalltalk.send($rec, "_with_", [(function(){return smalltalk.send(self, "_renderBoxOn_", [html]);})]);})(smalltalk.send(html, "_div", []));return (function($rec){smalltalk.send($rec, "_class_", ["jt_buttons"]);return smalltalk.send($rec, "_with_", [(function(){return smalltalk.send(self, "_renderButtonsOn_", [html]);})]);})(smalltalk.send(html, "_div", []));})]);
+return self;},
+source: unescape('renderTab%0A%09div%20contents%3A%20%5B%3Ahtml%20%7C%0A%09%20%20%20%20html%20div%0A%09%09class%3A%20%27jt_box%27%3B%0A%09%09with%3A%20%5Bself%20renderBoxOn%3A%20html%5D.%0A%09%20%20%20%20html%20div%0A%09%09class%3A%20%27jt_buttons%27%3B%0A%09%09with%3A%20%5Bself%20renderButtonsOn%3A%20html%5D%5D'),
+messageSends: ["contents:", "class:", "with:", "renderBoxOn:", "div", "renderButtonsOn:"],
+referencedClasses: []
+}),
+smalltalk.TabWidget);
+
 
 smalltalk.addMethod(
 '_open',
@@ -1241,7 +1349,7 @@ smalltalk.send(self['@selectedProtocol'], "_ifNil_", [(function(){return self['@
 compiler=smalltalk.send(smalltalk.Compiler, "_new", []);
 node=smalltalk.send(compiler, "_parse_", [source]);
 smalltalk.send(smalltalk.send(node, "_isParseFailure", []), "_ifTrue_", [(function(){return (function(){throw({name: 'stReturn', selector: '_compileMethodDefinitionFor_', fn: function(){return smalltalk.send(self, "_alert_", [smalltalk.send(smalltalk.send(smalltalk.send("PARSE ERROR: ", "__comma", [smalltalk.send(node, "_reason", [])]), "__comma", [unescape("%2C%20position%3A%20")]), "__comma", [smalltalk.send(smalltalk.send(node, "_position", []), "_asString", [])])])}})})();})]);
-smalltalk.send(compiler, "_currentClass_", [self['@selectedClass']]);
+smalltalk.send(compiler, "_currentClass_", [aClass]);
 method=smalltalk.send(compiler, "_eval_", [smalltalk.send(compiler, "_compileNode_", [node])]);
 smalltalk.send(method, "_category_", [self['@selectedProtocol']]);
 smalltalk.send(smalltalk.send(compiler, "_unknownVariables", []), "_do_", [(function(each){return smalltalk.send(smalltalk.send(self, "_confirm_", [smalltalk.send(smalltalk.send(unescape("Declare%20%27"), "__comma", [each]), "__comma", [unescape("%27%20as%20instance%20variable%3F")])]), "_ifTrue_", [(function(){smalltalk.send(self, "_addInstanceVariableNamed_toClass_", [each, aClass]);return (function(){throw({name: 'stReturn', selector: '_compileMethodDefinitionFor_', fn: function(){return smalltalk.send(self, "_compileMethodDefinitionFor_", [aClass])}})})();})]);})]);
@@ -1251,7 +1359,7 @@ smalltalk.send(self, "_updateMethodsList", []);
 smalltalk.send(self, "_selectMethod_", [method]);
 return self;
 } catch(e) {if(e.name === 'stReturn' && e.selector === '_compileMethodDefinitionFor_'){return e.fn()} throw(e)}},
-source: unescape('compileMethodDefinitionFor%3A%20aClass%0A%20%20%20%20%7C%20compiler%20method%20source%20node%20%7C%0A%20%20%20%20source%20%3A%3D%20sourceTextarea%20asJQuery%20val.%0A%20%20%20%20selectedProtocol%20ifNil%3A%20%5BselectedProtocol%20%3A%3D%20selectedMethod%20category%5D.%0A%20%20%20%20compiler%20%3A%3D%20Compiler%20new.%0A%20%20%20%20node%20%3A%3D%20compiler%20parse%3A%20source.%0A%20%20%20%20node%20isParseFailure%20ifTrue%3A%20%5B%0A%09%5Eself%20alert%3A%20%27PARSE%20ERROR%3A%20%27%2C%20node%20reason%2C%20%27%2C%20position%3A%20%27%2C%20node%20position%20asString%5D.%0A%20%20%20%20compiler%20currentClass%3A%20selectedClass.%0A%20%20%20%20method%20%3A%3D%20compiler%20eval%3A%20%28compiler%20compileNode%3A%20node%29.%0A%20%20%20%20method%20category%3A%20selectedProtocol.%0A%20%20%20%20compiler%20unknownVariables%20do%3A%20%5B%3Aeach%20%7C%0A%09%28self%20confirm%3A%20%27Declare%20%27%27%27%2C%20each%2C%20%27%27%27%20as%20instance%20variable%3F%27%29%20ifTrue%3A%20%5B%0A%09%09self%20addInstanceVariableNamed%3A%20each%20toClass%3A%20aClass.%0A%09%09%5Eself%20compileMethodDefinitionFor%3A%20aClass%5D%5D.%0A%20%20%20%20aClass%20addCompiledMethod%3A%20method.%0A%20%20%20%20compiler%20setupClass%3A%20aClass.%0A%20%20%20%20self%20updateMethodsList.%0A%20%20%20%20self%20selectMethod%3A%20method'),
+source: unescape('compileMethodDefinitionFor%3A%20aClass%0A%20%20%20%20%7C%20compiler%20method%20source%20node%20%7C%0A%20%20%20%20source%20%3A%3D%20sourceTextarea%20asJQuery%20val.%0A%20%20%20%20selectedProtocol%20ifNil%3A%20%5BselectedProtocol%20%3A%3D%20selectedMethod%20category%5D.%0A%20%20%20%20compiler%20%3A%3D%20Compiler%20new.%0A%20%20%20%20node%20%3A%3D%20compiler%20parse%3A%20source.%0A%20%20%20%20node%20isParseFailure%20ifTrue%3A%20%5B%0A%09%5Eself%20alert%3A%20%27PARSE%20ERROR%3A%20%27%2C%20node%20reason%2C%20%27%2C%20position%3A%20%27%2C%20node%20position%20asString%5D.%0A%20%20%20%20compiler%20currentClass%3A%20aClass.%0A%20%20%20%20method%20%3A%3D%20compiler%20eval%3A%20%28compiler%20compileNode%3A%20node%29.%0A%20%20%20%20method%20category%3A%20selectedProtocol.%0A%20%20%20%20compiler%20unknownVariables%20do%3A%20%5B%3Aeach%20%7C%0A%09%28self%20confirm%3A%20%27Declare%20%27%27%27%2C%20each%2C%20%27%27%27%20as%20instance%20variable%3F%27%29%20ifTrue%3A%20%5B%0A%09%09self%20addInstanceVariableNamed%3A%20each%20toClass%3A%20aClass.%0A%09%09%5Eself%20compileMethodDefinitionFor%3A%20aClass%5D%5D.%0A%20%20%20%20aClass%20addCompiledMethod%3A%20method.%0A%20%20%20%20compiler%20setupClass%3A%20aClass.%0A%20%20%20%20self%20updateMethodsList.%0A%20%20%20%20self%20selectMethod%3A%20method'),
 messageSends: ["val", "asJQuery", "ifNil:", "category", "new", "parse:", "ifTrue:", "isParseFailure", "alert:", unescape("%2C"), "reason", "asString", "position", "currentClass:", "eval:", "compileNode:", "category:", "do:", "unknownVariables", "confirm:", "addInstanceVariableNamed:toClass:", "compileMethodDefinitionFor:", "addCompiledMethod:", "setupClass:", "updateMethodsList", "selectMethod:"],
 referencedClasses: [smalltalk.Compiler]
 }),
@@ -1285,7 +1393,7 @@ smalltalk.send(self['@selectedCategory'], "_ifNotNil_", [(function(){(function($
 return self;},
 source: unescape('commitCategory%0A%20%20%20%20selectedCategory%20ifNotNil%3A%20%5B%0A%09%28Ajax%20url%3A%20self%20class%20commitPathJs%2C%20%27/%27%2C%20selectedCategory%2C%20%27.js%27%29%0A%09%20%20%20%20at%3A%20%27type%27%20put%3A%20%27PUT%27%3B%0A%09%20%20%20%20at%3A%20%27data%27%20put%3A%20%28Exporter%20new%20exportCategory%3A%20selectedCategory%29%3B%0A%09%20%20%20%20at%3A%20%27error%27%20put%3A%20%5Bself%20alert%3A%20%27Commit%20failed%21%27%5D%3B%0A%09%20%20%20%20send.%0A%09%28Ajax%20url%3A%20self%20class%20commitPathSt%2C%20%27/%27%2C%20selectedCategory%2C%20%27.st%27%29%0A%09%20%20%20%20at%3A%20%27type%27%20put%3A%20%27PUT%27%3B%0A%09%20%20%20%20at%3A%20%27data%27%20put%3A%20%28ChunkExporter%20new%20exportCategory%3A%20selectedCategory%29%3B%0A%09%20%20%20%20at%3A%20%27error%27%20put%3A%20%5Bself%20alert%3A%20%27Commit%20failed%21%27%5D%3B%0A%09%20%20%20%20send%5D'),
 messageSends: ["ifNotNil:", "at:put:", "exportCategory:", "new", "alert:", "send", "url:", unescape("%2C"), "commitPathJs", "class", "commitPathSt"],
-referencedClasses: [smalltalk.Exporter,smalltalk.ChunkExporter]
+referencedClasses: [smalltalk.Exporter,smalltalk.Ajax,smalltalk.ChunkExporter]
 }),
 smalltalk.Browser);
 
@@ -1484,7 +1592,7 @@ smalltalk.send(smalltalk.ReferencesBrowser, "_search_", [aString]);
 return self;},
 source: unescape('searchReferencesOf%3A%20aString%0A%09ReferencesBrowser%20search%3A%20aString'),
 messageSends: ["search:"],
-referencedClasses: []
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.Browser);
 
@@ -1499,7 +1607,7 @@ smalltalk.send(smalltalk.ReferencesBrowser, "_search_", [smalltalk.send(self['@s
 return self;},
 source: unescape('searchClassReferences%0A%09ReferencesBrowser%20search%3A%20selectedClass%20name'),
 messageSends: ["search:", "name"],
-referencedClasses: []
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.Browser);
 
@@ -1726,7 +1834,7 @@ var self=this;
 self['@input']=(function($rec){smalltalk.send($rec, "_class_", ["implementors"]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(html, "_input", []));
 smalltalk.send(self['@input'], "_onKeyPress_", [(function(event){return smalltalk.send(smalltalk.send(smalltalk.send(event, "_keyCode", []), "__eq", [(13)]), "_ifTrue_", [(function(){return smalltalk.send(self, "_search_", [smalltalk.send(smalltalk.send(self['@input'], "_asJQuery", []), "_val", [])]);})]);})]);
 return self;},
-source: unescape('renderInputOn%3A%20html%0A%09input%20%3A%3D%20html%20input%20%0A%09%09class%3A%20%27implementors%27%3B%0A%09%09yourself.%0A%09input%20onKeyPress%3A%20%5B%3Aevent%20%7C%0A%09%09event%20keyCode%20%3D%2013%20ifTrue%3A%20%5B%0A%09%09%09self%20search%3A%20input%20asJQuery%20val%5D%5D'),
+source: unescape('renderInputOn%3A%20html%20%0A%09input%20%3A%3D%20html%20input%20%0A%09%09class%3A%20%27implementors%27%3B%0A%09%09yourself.%0A%09input%20onKeyPress%3A%20%5B%3Aevent%20%7C%0A%09%09event%20keyCode%20%3D%2013%20ifTrue%3A%20%5B%0A%09%09%09self%20search%3A%20input%20asJQuery%20val%5D%5D'),
 messageSends: ["class:", "yourself", "input", "onKeyPress:", "ifTrue:", unescape("%3D"), "keyCode", "search:", "val", "asJQuery"],
 referencedClasses: []
 }),
@@ -2491,11 +2599,11 @@ var self=this;
 var variables=nil;
 variables=smalltalk.send(smalltalk.Dictionary, "_new", []);
 smalltalk.send(variables, "_at_put_", [unescape("%23self"), self]);
-smalltalk.send(smalltalk.send(smalltalk.send(self, "_class", []), "_instanceVariableNames", []), "_do_", [(function(each){return smalltalk.send(variables, "_at_put_", [each, smalltalk.send(self, "_instVarAt_", [each])]);})]);
+smalltalk.send(smalltalk.send(smalltalk.send(self, "_class", []), "_allInstanceVariableNames", []), "_do_", [(function(each){return smalltalk.send(variables, "_at_put_", [each, smalltalk.send(self, "_instVarAt_", [each])]);})]);
 (function($rec){smalltalk.send($rec, "_setLabel_", [smalltalk.send(self, "_printString", [])]);return smalltalk.send($rec, "_setVariables_", [variables]);})(anInspector);
 return self;},
-source: unescape('inspectOn%3A%20anInspector%0A%09%7C%20variables%20%7C%0A%09variables%20%3A%3D%20Dictionary%20new.%0A%09variables%20at%3A%20%27%23self%27%20put%3A%20self.%0A%09self%20class%20instanceVariableNames%20do%3A%20%5B%3Aeach%20%7C%0A%09%09variables%20at%3A%20each%20put%3A%20%28self%20instVarAt%3A%20each%29%5D.%0A%09anInspector%20%0A%09%09setLabel%3A%20self%20printString%3B%0A%09%09setVariables%3A%20variables'),
-messageSends: ["new", "at:put:", "do:", "instanceVariableNames", "class", "instVarAt:", "setLabel:", "printString", "setVariables:"],
+source: unescape('inspectOn%3A%20anInspector%0A%09%7C%20variables%20%7C%0A%09variables%20%3A%3D%20Dictionary%20new.%0A%09variables%20at%3A%20%27%23self%27%20put%3A%20self.%0A%09self%20class%20allInstanceVariableNames%20do%3A%20%5B%3Aeach%20%7C%0A%09%09variables%20at%3A%20each%20put%3A%20%28self%20instVarAt%3A%20each%29%5D.%0A%09anInspector%20%0A%09%09setLabel%3A%20self%20printString%3B%0A%09%09setVariables%3A%20variables'),
+messageSends: ["new", "at:put:", "do:", "allInstanceVariableNames", "class", "instVarAt:", "setLabel:", "printString", "setVariables:"],
 referencedClasses: [smalltalk.Dictionary]
 }),
 smalltalk.Object);
@@ -2562,6 +2670,28 @@ referencedClasses: []
 }),
 smalltalk.String);
 
+smalltalk.addMethod(
+'_inspectOn_',
+smalltalk.method({
+selector: 'inspectOn:',
+category: '*IDE',
+fn: function (anInspector){
+var self=this;
+var variables=nil;
+variables=smalltalk.send(smalltalk.Dictionary, "_new", []);
+smalltalk.send(variables, "_at_put_", [unescape("%23self"), self]);
+smalltalk.send(variables, "_at_put_", [unescape("%23home"), smalltalk.send(self, "_home", [])]);
+smalltalk.send(variables, "_at_put_", [unescape("%23receiver"), smalltalk.send(self, "_receiver", [])]);
+smalltalk.send(variables, "_at_put_", [unescape("%23selector"), smalltalk.send(self, "_selector", [])]);
+smalltalk.send(smalltalk.send(smalltalk.send(self, "_class", []), "_instanceVariableNames", []), "_do_", [(function(each){return smalltalk.send(variables, "_at_put_", [each, smalltalk.send(self, "_instVarAt_", [each])]);})]);
+(function($rec){smalltalk.send($rec, "_setLabel_", [smalltalk.send(self, "_printString", [])]);return smalltalk.send($rec, "_setVariables_", [variables]);})(anInspector);
+return self;},
+source: unescape('inspectOn%3A%20anInspector%0A%09%7C%20variables%20%7C%0A%09variables%20%3A%3D%20Dictionary%20new.%0A%09variables%20at%3A%20%27%23self%27%20put%3A%20self.%0A%09variables%20at%3A%20%27%23home%27%20put%3A%20self%20home.%0A%09variables%20at%3A%20%27%23receiver%27%20put%3A%20self%20receiver.%0A%09variables%20at%3A%20%27%23selector%27%20put%3A%20self%20selector.%0A%09self%20class%20instanceVariableNames%20do%3A%20%5B%3Aeach%20%7C%0A%09%09variables%20at%3A%20each%20put%3A%20%28self%20instVarAt%3A%20each%29%5D.%0A%09anInspector%20%0A%09%09setLabel%3A%20self%20printString%3B%0A%09%09setVariables%3A%20variables'),
+messageSends: ["new", "at:put:", "home", "receiver", "selector", "do:", "instanceVariableNames", "class", "instVarAt:", "setLabel:", "printString", "setVariables:"],
+referencedClasses: [smalltalk.Dictionary]
+}),
+smalltalk.MethodContext);
+
 smalltalk.addMethod(
 '_inspectOn_',
 smalltalk.method({

+ 47 - 18
js/JQuery.js

@@ -75,6 +75,21 @@ referencedClasses: []
 }),
 smalltalk.JQuery);
 
+smalltalk.addMethod(
+'_jquery',
+smalltalk.method({
+selector: 'jquery',
+category: 'accessing',
+fn: function (){
+var self=this;
+return self['@jquery'];
+return self;},
+source: unescape('jquery%0A%09%5Ejquery'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.JQuery);
+
 smalltalk.addMethod(
 '_removeAttribute_',
 smalltalk.method({
@@ -144,7 +159,7 @@ fn: function (aString){
 var self=this;
 return self['@jquery'].css(aString);
 return self;},
-source: unescape('cssAt%3A%20aString%0A%09%7B%27return%20self%5B%27%27@jquery%27%27%5D.css%28aString%29%27%7D'),
+source: unescape('cssAt%3A%20aString%0A%09%3Creturn%20self%5B%27@jquery%27%5D.css%28aString%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -159,7 +174,7 @@ fn: function (aString, anotherString){
 var self=this;
 self['@jquery'].css(aString, anotherString);
 return self;},
-source: unescape('cssAt%3A%20aString%20put%3A%20anotherString%0A%20%20%20%20%7B%27self%5B%27%27@jquery%27%27%5D.css%28aString%2C%20anotherString%29%27%7D'),
+source: unescape('cssAt%3A%20aString%20put%3A%20anotherString%0A%20%20%20%20%3Cself%5B%27@jquery%27%5D.css%28aString%2C%20anotherString%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -519,7 +534,7 @@ fn: function (anEventString, aBlock){
 var self=this;
 self['@jquery'].bind(anEventString, function(e){aBlock(e, self)});
 return self;},
-source: unescape('on%3A%20anEventString%20do%3A%20aBlock%0A%20%20%20%20%22Attach%20aBlock%20for%20anEventString%20on%20the%20element%22%0A%20%20%20%20%7B%27self%5B%27%27@jquery%27%27%5D.bind%28anEventString%2C%20function%28e%29%7BaBlock%28e%2C%20self%29%7D%29%27%7D'),
+source: unescape('on%3A%20anEventString%20do%3A%20aBlock%0A%20%20%20%20%22Attach%20aBlock%20for%20anEventString%20on%20the%20element%22%0A%20%20%20%20%3Cself%5B%27@jquery%27%5D.bind%28anEventString%2C%20function%28e%29%7BaBlock%28e%2C%20self%29%7D%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -564,7 +579,7 @@ fn: function (aString){
 var self=this;
 return self['@jquery'][aString]();
 return self;},
-source: unescape('call%3A%20aString%0A%09%7B%27return%20self%5B%27%27@jquery%27%27%5D%5BaString%5D%28%29%27%7D'),
+source: unescape('call%3A%20aString%0A%09%3Creturn%20self%5B%27@jquery%27%5D%5BaString%5D%28%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -579,7 +594,7 @@ fn: function (aString, anObject){
 var self=this;
 return self['@jquery'][aString](anObject);
 return self;},
-source: unescape('call%3A%20aString%20withArgument%3A%20anObject%0A%20%20%20%20%7B%27return%20self%5B%27%27@jquery%27%27%5D%5BaString%5D%28anObject%29%27%7D'),
+source: unescape('call%3A%20aString%20withArgument%3A%20anObject%0A%20%20%20%20%3Creturn%20self%5B%27@jquery%27%5D%5BaString%5D%28anObject%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -612,7 +627,7 @@ var newJQuery=nil;
 newJQuery = jQuery(String(aString));
 return smalltalk.send(self, "_from_", [newJQuery]);
 return self;},
-source: unescape('fromString%3A%20aString%0A%20%20%20%20%7C%20newJQuery%20%7C%0A%20%20%20%20%7B%27newJQuery%20%3D%20jQuery%28String%28aString%29%29%27%7D.%0A%20%20%20%20%5Eself%20from%3A%20newJQuery'),
+source: unescape('fromString%3A%20aString%0A%20%20%20%20%7C%20newJQuery%20%7C%0A%20%20%20%20%3CnewJQuery%20%3D%20jQuery%28String%28aString%29%29%3E.%0A%20%20%20%20%5Eself%20from%3A%20newJQuery'),
 messageSends: ["from:"],
 referencedClasses: []
 }),
@@ -642,7 +657,7 @@ fn: function (){
 var self=this;
 return self._from_(jQuery(window));
 return self;},
-source: unescape('window%0A%09%7B%27return%20self._from_%28jQuery%28window%29%29%27%7D'),
+source: unescape('window%0A%09%3Creturn%20self._from_%28jQuery%28window%29%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -655,9 +670,9 @@ selector: 'body',
 category: 'instance creation',
 fn: function (){
 var self=this;
-return self._from_(jQuery(body));
+return self._from_(jQuery('body'));
 return self;},
-source: unescape('body%0A%09%7B%27return%20self._from_%28jQuery%28body%29%29%27%7D'),
+source: unescape('body%0A%09%3Creturn%20self._from_%28jQuery%28%27body%27%29%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -672,12 +687,29 @@ fn: function (){
 var self=this;
 return self._from_(jQuery(document));
 return self;},
-source: unescape('document%0A%09%7B%27return%20self._from_%28jQuery%28document%29%29%27%7D'),
+source: unescape('document%0A%09%3Creturn%20self._from_%28jQuery%28document%29%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
 smalltalk.JQuery.klass);
 
+smalltalk.addMethod(
+'_fromElement_',
+smalltalk.method({
+selector: 'fromElement:',
+category: 'instance creation',
+fn: function (anElement){
+var self=this;
+var newJQuery=nil;
+newJQuery = jQuery(anElement);
+return smalltalk.send(self, "_from_", [newJQuery]);
+return self;},
+source: unescape('fromElement%3A%20anElement%0A%20%20%20%20%7C%20newJQuery%20%7C%0A%20%20%20%20%3CnewJQuery%20%3D%20jQuery%28anElement%29%3E.%0A%20%20%20%20%5Eself%20from%3A%20newJQuery'),
+messageSends: ["from:"],
+referencedClasses: []
+}),
+smalltalk.JQuery.klass);
+
 
 smalltalk.addClass('Ajax', smalltalk.Object, ['settings'], 'JQuery');
 smalltalk.Ajax.comment=unescape('instance%20variable%20names%3A%0A-%20settings%20%20A%20set%20of%20key/value%20pairs%20that%20configure%20the%20Ajax%20request.%20All%20settings%20are%20optional.%0A%0AFull%20list%20of%20settings%20options%20at%20http%3A//api.jquery.com/jQuery.ajax/')
@@ -750,7 +782,7 @@ fn: function (){
 var self=this;
 jQuery.ajax(self['@settings']);
 return self;},
-source: unescape('send%0A%20%20%20%20%7B%27jQuery.ajax%28self%5B%27%27@settings%27%27%5D%29%27%7D'),
+source: unescape('send%0A%20%20%20%20%3CjQuery.ajax%28self%5B%27@settings%27%5D%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -796,13 +828,10 @@ selector: 'appendToJQuery:',
 category: '*JQuery',
 fn: function (aJQuery){
 var self=this;
-var canvas=nil;
-canvas=smalltalk.send(smalltalk.HTMLCanvas, "_new", []);
-smalltalk.send(self, "_value_", [canvas]);
-smalltalk.send(aJQuery, "_append_", [canvas]);
+smalltalk.send(self, "_value_", [smalltalk.send(smalltalk.HTMLCanvas, "_onJQuery_", [aJQuery])]);
 return self;},
-source: unescape('appendToJQuery%3A%20aJQuery%0A%09%7C%20canvas%20%7C%0A%09canvas%20%3A%3D%20HTMLCanvas%20new.%0A%09self%20value%3A%20canvas.%0A%09aJQuery%20append%3A%20canvas'),
-messageSends: ["new", "value:", "append:"],
+source: unescape('appendToJQuery%3A%20aJQuery%0A%09self%20value%3A%20%28HTMLCanvas%20onJQuery%3A%20aJQuery%29'),
+messageSends: ["value:", "onJQuery:"],
 referencedClasses: [smalltalk.HTMLCanvas]
 }),
 smalltalk.BlockClosure);
@@ -831,7 +860,7 @@ fn: function (aJQuery){
 var self=this;
 aJQuery._appendElement_(String(self));
 return self;},
-source: unescape('appendToJQuery%3A%20aJQuery%0A%20%20%20%20%7B%27aJQuery._appendElement_%28String%28self%29%29%27%7D'),
+source: unescape('appendToJQuery%3A%20aJQuery%0A%20%20%20%20%3CaJQuery._appendElement_%28String%28self%29%29%3E'),
 messageSends: [],
 referencedClasses: []
 }),

+ 286 - 4
js/Kernel.js

@@ -678,6 +678,21 @@ referencedClasses: [smalltalk.Object]
 }),
 smalltalk.Object);
 
+smalltalk.addMethod(
+'_halt',
+smalltalk.method({
+selector: 'halt',
+category: 'error handling',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_error_", ["Halt encountered"]);
+return self;},
+source: unescape('halt%0A%09self%20error%3A%20%27Halt%20encountered%27'),
+messageSends: ["error:"],
+referencedClasses: []
+}),
+smalltalk.Object);
+
 
 smalltalk.addMethod(
 '_initialize',
@@ -1092,6 +1107,24 @@ referencedClasses: [smalltalk.nil,smalltalk.Array]
 }),
 smalltalk.Behavior);
 
+smalltalk.addMethod(
+'_allInstanceVariableNames',
+smalltalk.method({
+selector: 'allInstanceVariableNames',
+category: 'accessing',
+fn: function (){
+var self=this;
+var result=nil;
+result=smalltalk.send(self, "_instanceVariableNames", []);
+smalltalk.send(smalltalk.send(self, "_superclass", []), "_ifNotNil_", [(function(){return smalltalk.send(result, "_addAll_", [smalltalk.send(smalltalk.send(self, "_superclass", []), "_allInstanceVariableNames", [])]);})]);
+return result;
+return self;},
+source: unescape('allInstanceVariableNames%0A%09%7C%20result%20%7C%0A%09result%20%3A%3D%20self%20instanceVariableNames.%0A%09self%20superclass%20ifNotNil%3A%20%5B%0A%09%20%20%20%20result%20addAll%3A%20self%20superclass%20allInstanceVariableNames%5D.%0A%09%5Eresult'),
+messageSends: ["instanceVariableNames", "ifNotNil:", "superclass", "addAll:", "allInstanceVariableNames"],
+referencedClasses: []
+}),
+smalltalk.Behavior);
+
 
 
 smalltalk.addClass('Class', smalltalk.Behavior, [], 'Kernel');
@@ -4738,9 +4771,9 @@ selector: 'exec:',
 category: 'evaluating',
 fn: function (aString){
 var self=this;
-return self.exec(aString);
+return self.exec(aString) || nil;
 return self;},
-source: unescape('exec%3A%20aString%0A%09%3Creturn%20self.exec%28aString%29%3E'),
+source: unescape('exec%3A%20aString%0A%09%3Creturn%20self.exec%28aString%29%20%7C%7C%20nil%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -4831,9 +4864,24 @@ selector: 'signal',
 category: 'signaling',
 fn: function (){
 var self=this;
-console.log(self._messageText()); throw(self);
+self.context = thisContext; self.smalltalkError = true; throw(self);
 return self;},
-source: unescape('signal%0A%09%3Cconsole.log%28self._messageText%28%29%29%3B%20throw%28self%29%3E'),
+source: unescape('signal%0A%09%3Cself.context%20%3D%20thisContext%3B%20self.smalltalkError%20%3D%20true%3B%20throw%28self%29%3E'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Error);
+
+smalltalk.addMethod(
+'_context',
+smalltalk.method({
+selector: 'context',
+category: 'accessing',
+fn: function (){
+var self=this;
+return self.context;
+return self;},
+source: unescape('context%0A%09%3Creturn%20self.context%3E'),
 messageSends: [],
 referencedClasses: []
 }),
@@ -4856,6 +4904,99 @@ referencedClasses: []
 smalltalk.Error.klass);
 
 
+smalltalk.addClass('MethodContext', smalltalk.Object, [], 'Kernel');
+smalltalk.addMethod(
+'_receiver',
+smalltalk.method({
+selector: 'receiver',
+category: 'accessing',
+fn: function (){
+var self=this;
+return self.receiver;
+return self;},
+source: unescape('receiver%0A%09%3Creturn%20self.receiver%3E'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
+smalltalk.addMethod(
+'_selector',
+smalltalk.method({
+selector: 'selector',
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.convertSelector(self.selector);
+return self;},
+source: unescape('selector%0A%09%3Creturn%20smalltalk.convertSelector%28self.selector%29%3E'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
+smalltalk.addMethod(
+'_home',
+smalltalk.method({
+selector: 'home',
+category: 'accessing',
+fn: function (){
+var self=this;
+return self.homeContext;
+return self;},
+source: unescape('home%0A%09%3Creturn%20self.homeContext%3E'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
+smalltalk.addMethod(
+'_temps',
+smalltalk.method({
+selector: 'temps',
+category: 'accessing',
+fn: function (){
+var self=this;
+return self.temps;
+return self;},
+source: unescape('temps%0A%09%3Creturn%20self.temps%3E'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
+smalltalk.addMethod(
+'_printString',
+smalltalk.method({
+selector: 'printString',
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self, "_printString", [], smalltalk.Object), "__comma", [unescape("%28")]), "__comma", [smalltalk.send(self, "_asString", [])]), "__comma", [unescape("%29")]);
+return self;},
+source: unescape('printString%0A%09%5Esuper%20printString%2C%20%27%28%27%2C%20self%20asString%2C%20%27%29%27'),
+messageSends: [unescape("%2C"), "printString", "asString"],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
+smalltalk.addMethod(
+'_asString',
+smalltalk.method({
+selector: 'asString',
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self, "_receiver", []), "_class", []), "_printString", []), "__comma", [unescape("%20%3E%3E%20")]), "__comma", [smalltalk.send(self, "_selector", [])]);
+return self;},
+source: unescape('asString%0A%09%5Eself%20receiver%20class%20printString%2C%20%27%20%3E%3E%20%27%2C%20self%20selector'),
+messageSends: [unescape("%2C"), "printString", "class", "receiver", "selector"],
+referencedClasses: []
+}),
+smalltalk.MethodContext);
+
+
+
 smalltalk.addClass('Association', smalltalk.Object, ['key', 'value'], 'Kernel');
 smalltalk.addMethod(
 '__eq',
@@ -6423,3 +6564,144 @@ smalltalk.MessageNotUnderstood);
 
 
 
+smalltalk.addClass('ErrorHandler', smalltalk.Object, [], 'Kernel');
+smalltalk.addMethod(
+'_handleError_',
+smalltalk.method({
+selector: 'handleError:',
+category: 'error handling',
+fn: function (anError){
+var self=this;
+smalltalk.send(smalltalk.send(anError, "_context", []), "_ifNotNil_", [(function(){return smalltalk.send(self, "_logErrorContext_", [smalltalk.send(anError, "_context", [])]);})]);
+smalltalk.send(self, "_logError_", [anError]);
+return self;},
+source: unescape('handleError%3A%20anError%0A%09anError%20context%20ifNotNil%3A%20%5Bself%20logErrorContext%3A%20anError%20context%5D.%0A%09self%20logError%3A%20anError'),
+messageSends: ["ifNotNil:", "context", "logErrorContext:", "logError:"],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler);
+
+smalltalk.addMethod(
+'_logContext_',
+smalltalk.method({
+selector: 'logContext:',
+category: 'private',
+fn: function (aContext){
+var self=this;
+smalltalk.send(smalltalk.send(aContext, "_home", []), "_ifNotNil_", [(function(){return smalltalk.send(self, "_logContext_", [smalltalk.send(aContext, "_home", [])]);})]);
+smalltalk.send(self, "_log_", [smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aContext, "_receiver", []), "_asString", []), "__comma", [unescape("%3E%3E")]), "__comma", [smalltalk.send(aContext, "_selector", [])])]);
+return self;},
+source: unescape('logContext%3A%20aContext%0A%09aContext%20home%20ifNotNil%3A%20%5B%0A%09%09self%20logContext%3A%20aContext%20home%5D.%0A%09self%20log%3A%20aContext%20receiver%20asString%2C%20%27%3E%3E%27%2C%20aContext%20selector'),
+messageSends: ["ifNotNil:", "home", "logContext:", "log:", unescape("%2C"), "asString", "receiver", "selector"],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler);
+
+smalltalk.addMethod(
+'_logErrorContext_',
+smalltalk.method({
+selector: 'logErrorContext:',
+category: 'private',
+fn: function (aContext){
+var self=this;
+smalltalk.send(aContext, "_ifNotNil_", [(function(){return smalltalk.send(smalltalk.send(aContext, "_home", []), "_ifNotNil_", [(function(){return smalltalk.send(self, "_logContext_", [smalltalk.send(aContext, "_home", [])]);})]);})]);
+return self;},
+source: unescape('logErrorContext%3A%20aContext%0A%09aContext%20ifNotNil%3A%20%5B%0A%09%09aContext%20home%20ifNotNil%3A%20%5B%0A%09%09%09self%20logContext%3A%20aContext%20home%5D%5D'),
+messageSends: ["ifNotNil:", "home", "logContext:"],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler);
+
+smalltalk.addMethod(
+'_logError_',
+smalltalk.method({
+selector: 'logError:',
+category: 'private',
+fn: function (anError){
+var self=this;
+smalltalk.send(self, "_log_", [smalltalk.send(anError, "_messageText", [])]);
+return self;},
+source: unescape('logError%3A%20anError%0A%09self%20log%3A%20anError%20messageText'),
+messageSends: ["log:", "messageText"],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler);
+
+smalltalk.addMethod(
+'_log_',
+smalltalk.method({
+selector: 'log:',
+category: 'private',
+fn: function (aString){
+var self=this;
+smalltalk.send(console, "_log_", [aString]);
+return self;},
+source: unescape('log%3A%20aString%0A%09console%20log%3A%20aString'),
+messageSends: ["log:"],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler);
+
+
+smalltalk.ErrorHandler.klass.iVarNames = ['current'];
+smalltalk.addMethod(
+'_current',
+smalltalk.method({
+selector: 'current',
+category: 'accessing',
+fn: function (){
+var self=this;
+return self['@current'];
+return self;},
+source: unescape('current%0A%09%5Ecurrent'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler.klass);
+
+smalltalk.addMethod(
+'_initialize',
+smalltalk.method({
+selector: 'initialize',
+category: 'initialization',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_register", []);
+return self;},
+source: unescape('initialize%0A%09self%20register'),
+messageSends: ["register"],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler.klass);
+
+smalltalk.addMethod(
+'_register',
+smalltalk.method({
+selector: 'register',
+category: 'initialization',
+fn: function (){
+var self=this;
+smalltalk.send(smalltalk.ErrorHandler, "_setCurrent_", [smalltalk.send(self, "_new", [])]);
+return self;},
+source: unescape('register%0A%09ErrorHandler%20setCurrent%3A%20self%20new'),
+messageSends: ["setCurrent:", "new"],
+referencedClasses: [smalltalk.ErrorHandler]
+}),
+smalltalk.ErrorHandler.klass);
+
+smalltalk.addMethod(
+'_setCurrent_',
+smalltalk.method({
+selector: 'setCurrent:',
+category: 'accessing',
+fn: function (anHandler){
+var self=this;
+self['@current']=anHandler;
+return self;},
+source: unescape('setCurrent%3A%20anHandler%0A%09current%20%3A%3D%20anHandler'),
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ErrorHandler.klass);
+
+

+ 16 - 16
js/Parser.js

@@ -40,7 +40,7 @@ return smalltalk.send(smalltalk.PPFlattenParser, "_on_", [self]);
 return self;},
 source: unescape('flatten%0A%09%5EPPFlattenParser%20on%3A%20self'),
 messageSends: ["on:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPFlattenParser]
 }),
 smalltalk.PPParser);
 
@@ -55,7 +55,7 @@ return smalltalk.send(smalltalk.PPSourceParser, "_on_", [self]);
 return self;},
 source: unescape('withSource%0A%09%5EPPSourceParser%20on%3A%20self'),
 messageSends: ["on:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPSourceParser]
 }),
 smalltalk.PPParser);
 
@@ -70,7 +70,7 @@ return smalltalk.send(smalltalk.PPActionParser, "_on_block_", [self, aBlock]);
 return self;},
 source: unescape('%3D%3D%3E%20aBlock%0A%09%5EPPActionParser%20on%3A%20self%20block%3A%20aBlock'),
 messageSends: ["on:block:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPActionParser]
 }),
 smalltalk.PPParser);
 
@@ -85,7 +85,7 @@ return smalltalk.send(smalltalk.PPSequenceParser, "_with_with_", [self, aParser]
 return self;},
 source: unescape('%2C%20aParser%0A%09%5EPPSequenceParser%20with%3A%20self%20with%3A%20aParser'),
 messageSends: ["with:with:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPSequenceParser]
 }),
 smalltalk.PPParser);
 
@@ -100,7 +100,7 @@ return smalltalk.send(smalltalk.PPChoiceParser, "_with_with_", [self, aParser]);
 return self;},
 source: unescape('/%20aParser%0A%09%5EPPChoiceParser%20with%3A%20self%20with%3A%20aParser'),
 messageSends: ["with:with:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPChoiceParser]
 }),
 smalltalk.PPParser);
 
@@ -115,7 +115,7 @@ return smalltalk.send(smalltalk.PPRepeatingParser, "_on_min_", [self, (1)]);
 return self;},
 source: unescape('plus%0A%09%5EPPRepeatingParser%20on%3A%20self%20min%3A%201'),
 messageSends: ["on:min:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPRepeatingParser]
 }),
 smalltalk.PPParser);
 
@@ -130,7 +130,7 @@ return smalltalk.send(smalltalk.PPRepeatingParser, "_on_min_", [self, (0)]);
 return self;},
 source: unescape('star%0A%09%5EPPRepeatingParser%20on%3A%20self%20min%3A%200'),
 messageSends: ["on:min:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPRepeatingParser]
 }),
 smalltalk.PPParser);
 
@@ -145,7 +145,7 @@ return smalltalk.send(smalltalk.PPNotParser, "_on_", [self]);
 return self;},
 source: unescape('not%0A%09%5EPPNotParser%20on%3A%20self'),
 messageSends: ["on:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPNotParser]
 }),
 smalltalk.PPParser);
 
@@ -160,7 +160,7 @@ return smalltalk.send(self, "__slash", [smalltalk.send(smalltalk.PPEpsilonParser
 return self;},
 source: unescape('optional%0A%09%5Eself%20/%20PPEpsilonParser%20new'),
 messageSends: [unescape("/"), "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPEpsilonParser]
 }),
 smalltalk.PPParser);
 
@@ -211,7 +211,7 @@ return smalltalk.send(smalltalk.send(result, "_isParseFailure", []), "_ifTrue_if
 return self;},
 source: unescape('parseAll%3A%20aStream%0A%09%7C%20result%20%7C%0A%09result%20%3A%3D%20%28PPSequenceParser%20with%3A%20self%20with%3A%20PPEOFParser%20new%29%20memoizedParse%3A%20aStream.%0A%09%5Eresult%20isParseFailure%20%0A%09%20%20%20%20ifTrue%3A%20%5Bself%20error%3A%20%28result%20messageFor%3A%20aStream%20contents%29%5D%0A%09%20%20%20%20ifFalse%3A%20%5Bresult%20first%5D'),
 messageSends: ["memoizedParse:", "with:with:", "new", "ifTrue:ifFalse:", "isParseFailure", "error:", "messageFor:", "contents", "first"],
-referencedClasses: [smalltalk.nil,smalltalk.nil]
+referencedClasses: [smalltalk.PPSequenceParser,smalltalk.PPEOFParser]
 }),
 smalltalk.PPParser);
 
@@ -229,7 +229,7 @@ return smalltalk.send(smalltalk.send(aStream, "_atEnd", []), "_ifFalse_ifTrue_",
 return self;},
 source: unescape('parse%3A%20aStream%0A%09%5EaStream%20atEnd%20%0A%09%20%20%20%20ifFalse%3A%20%5B%0A%09%09PPFailure%20new%20reason%3A%20aStream%20contents%2C%20String%20lf%2C%20%27---------------%27%2C%20String%20lf%2C%20%27EOF%20expected%27%20at%3A%20aStream%20position%5D%0A%09%20%20%20%20ifTrue%3A%20%5Bnil%5D'),
 messageSends: ["ifFalse:ifTrue:", "atEnd", "reason:at:", "new", unescape("%2C"), "contents", "lf", "position"],
-referencedClasses: [smalltalk.nil,smalltalk.String]
+referencedClasses: [smalltalk.PPFailure,smalltalk.String]
 }),
 smalltalk.PPEOFParser);
 
@@ -247,7 +247,7 @@ return smalltalk.send(smalltalk.send(aStream, "_atEnd", []), "_ifTrue_ifFalse_",
 return self;},
 source: unescape('parse%3A%20aStream%0A%09%5EaStream%20atEnd%0A%09%20%20%20%20ifTrue%3A%20%5BPPFailure%20new%0A%09%09%09%20reason%3A%20%27did%20not%20expect%20EOF%27%20at%3A%20aStream%20position%5D%0A%09%20%20%20%20ifFalse%3A%20%5BaStream%20next%5D'),
 messageSends: ["ifTrue:ifFalse:", "atEnd", "reason:at:", "new", "position", "next"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPFailure]
 }),
 smalltalk.PPAnyParser);
 
@@ -317,7 +317,7 @@ return smalltalk.send(smalltalk.send(result, "__eq", [smalltalk.send(self, "_str
 return self;},
 source: unescape('parse%3A%20aStream%0A%09%7C%20position%20result%20%7C%0A%09position%20%3A%3D%20aStream%20position.%0A%09result%20%3A%3D%20aStream%20next%3A%20self%20string%20size.%0A%09%5Eresult%20%3D%20self%20string%0A%09%20%20%20%20ifTrue%3A%20%5Bresult%5D%0A%09%20%20%20%20ifFalse%3A%20%5B%0A%09%09aStream%20position%3A%20position.%0A%09%09PPFailure%20new%20reason%3A%20%27Expected%20%27%2C%20self%20string%2C%20%27%20but%20got%20%27%2C%20%28result%20at%3A%20position%29%20printString%3B%20yourself%5D'),
 messageSends: ["position", "next:", "size", "string", "ifTrue:ifFalse:", unescape("%3D"), "position:", "reason:", unescape("%2C"), "printString", "at:", "yourself", "new"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPFailure]
 }),
 smalltalk.PPStringParser);
 
@@ -350,7 +350,7 @@ return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aStream, "_pe
 return self;},
 source: unescape('parse%3A%20aStream%0A%09%5E%28aStream%20peek%20notNil%20and%3A%20%5Bself%20match%3A%20aStream%20peek%5D%29%0A%09%20%20%20%20ifTrue%3A%20%5BaStream%20next%5D%0A%09%20%20%20%20ifFalse%3A%20%5BPPFailure%20new%20reason%3A%20%27Could%20not%20match%27%20at%3A%20aStream%20position%5D'),
 messageSends: ["ifTrue:ifFalse:", "and:", "notNil", "peek", "match:", "next", "reason:at:", "new", "position"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPFailure]
 }),
 smalltalk.PPCharacterParser);
 
@@ -638,7 +638,7 @@ return smalltalk.send(smalltalk.send(element, "_isParseFailure", []), "_ifTrue_i
 return self;},
 source: unescape('parse%3A%20aStream%0A%09%7C%20element%20%7C%0A%09element%20%3A%3D%20self%20basicParse%3A%20aStream.%0A%09%5Eelement%20isParseFailure%20%0A%09%20%20%20%20ifTrue%3A%20%5Bnil%5D%0A%09%20%20%20%20ifFalse%3A%20%5BPPFailure%20reason%3A%20element%20at%3A%20aStream%20position%5D'),
 messageSends: ["basicParse:", "ifTrue:ifFalse:", "isParseFailure", "reason:at:", "position"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.PPFailure]
 }),
 smalltalk.PPNotParser);
 
@@ -1342,7 +1342,7 @@ nextChunk=smalltalk.send(smalltalk.send(self, "_chunkParser", []), "_parse_", [a
 return self;},
 source: unescape('import%3A%20aStream%0A%09aStream%20atEnd%20ifFalse%3A%20%5B%0A%09%20%20%20%20%7C%20nextChunk%20%7C%0A%09%20%20%20%20nextChunk%20%3A%3D%20self%20chunkParser%20parse%3A%20aStream.%0A%09%20%20%20%20nextChunk%20ifNotNil%3A%20%5B%0A%09%09nextChunk%20isInstructionChunk%20%0A%09%09%20%20%20%20ifTrue%3A%20%5B%28Compiler%20new%20loadExpression%3A%20nextChunk%20contents%29%0A%09%09%09%09%09%20scanFrom%3A%20aStream%5D%0A%09%09%20%20%20%20ifFalse%3A%20%5BCompiler%20new%20loadExpression%3A%20nextChunk%20contents%5D.%0A%09%09self%20import%3A%20aStream%5D%5D'),
 messageSends: ["ifFalse:", "atEnd", "parse:", "chunkParser", "ifNotNil:", "ifTrue:ifFalse:", "isInstructionChunk", "scanFrom:", "loadExpression:", "new", "contents", "import:"],
-referencedClasses: [smalltalk.nil]
+referencedClasses: [smalltalk.Compiler]
 }),
 smalltalk.Importer);
 

+ 27 - 11
js/SUnit.js

@@ -55,7 +55,7 @@ var self=this;
 return self;},
 source: unescape('signalFailure%3A%20aString%0A%09TestFailure%20new%0A%09%09messageText%3A%20aString%3B%0A%09%09signal'),
 messageSends: ["messageText:", "signal", "new"],
-referencedClasses: []
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.TestCase);
 
@@ -132,7 +132,7 @@ smalltalk.send(smalltalk.send(self, "_methods", []), "_do_", [(function(each){sm
 return self;},
 source: unescape('performTestFor%3A%20aResult%0A%09self%20methods%20do%3A%20%5B%3Aeach%20%7C%20%0A%09%09%5B%5Bself%20perform%3A%20each%5D%0A%09%09%09on%3A%20TestFailure%20do%3A%20%5B%3Aex%20%7C%20aResult%20addFailure%3A%20self%20class%20name%2C%20%27%3E%3E%27%2C%20each%5D%5D%0A%09%09%09on%3A%20Error%20do%3A%20%5B%3Aex%20%7C%20aResult%20addError%3A%20self%20class%20name%2C%20%27%3E%3E%27%2C%20each%5D.%0A%09%09aResult%20increaseRuns%5D'),
 messageSends: ["do:", "methods", "on:do:", "perform:", "addFailure:", unescape("%2C"), "name", "class", "addError:", "increaseRuns"],
-referencedClasses: [smalltalk.Error]
+referencedClasses: [smalltalk.nil,smalltalk.Error]
 }),
 smalltalk.TestCase);
 
@@ -216,7 +216,7 @@ smalltalk.ExampleTest);
 
 
 
-smalltalk.addClass('ProgressBar', smalltalk.TabWidget, ['percent', 'progressDiv'], 'SUnit');
+smalltalk.addClass('ProgressBar', smalltalk.TabWidget, ['percent', 'progressDiv', 'div'], 'SUnit');
 smalltalk.addMethod(
 '_percent',
 smalltalk.method({
@@ -254,10 +254,11 @@ selector: 'renderOn:',
 category: 'rendering',
 fn: function (html){
 var self=this;
-(function($rec){smalltalk.send($rec, "_class_", ["progress_bar"]);return smalltalk.send($rec, "_with_", [(function(){return (function($rec){smalltalk.send($rec, "_class_", ["progress"]);return smalltalk.send($rec, "_style_", [smalltalk.send(smalltalk.send("width:", "__comma", [smalltalk.send(smalltalk.send(self, "_percent", []), "_asString", [])]), "__comma", [unescape("%25")])]);})(smalltalk.send(html, "_div", []));})]);})(smalltalk.send(html, "_div", []));
+self['@div']=(function($rec){smalltalk.send($rec, "_class_", ["progress_bar"]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(html, "_div", []));
+smalltalk.send(self, "_renderProgressBar", []);
 return self;},
-source: unescape('renderOn%3A%20html%20%0A%09html%20div%20%0A%09%09class%3A%20%27progress_bar%27%3B%0A%09%09with%3A%20%5B%0A%09%09%09html%20div%20%0A%09%09%09%09class%3A%20%27progress%27%3B%0A%09%09%09%09style%3A%20%27width%3A%27%2C%20self%20percent%20asString%2C%20%27%25%27%5D'),
-messageSends: ["class:", "with:", "style:", unescape("%2C"), "asString", "percent", "div"],
+source: unescape('renderOn%3A%20html%20%0A%09div%20%3A%3D%20html%20div%20%0A%09%09class%3A%20%27progress_bar%27%3B%0A%09%09yourself.%0A%09self%20renderProgressBar'),
+messageSends: ["class:", "yourself", "div", "renderProgressBar"],
 referencedClasses: []
 }),
 smalltalk.ProgressBar);
@@ -270,10 +271,25 @@ category: 'updating',
 fn: function (aNumber){
 var self=this;
 smalltalk.send(self, "_percent_", [aNumber]);
-smalltalk.send(self, "_update", []);
+smalltalk.send(self, "_renderProgressBar", []);
+return self;},
+source: unescape('updatePercent%3A%20aNumber%0A%09self%20percent%3A%20aNumber.%0A%09self%20renderProgressBar'),
+messageSends: ["percent:", "renderProgressBar"],
+referencedClasses: []
+}),
+smalltalk.ProgressBar);
+
+smalltalk.addMethod(
+'_renderProgressBar',
+smalltalk.method({
+selector: 'renderProgressBar',
+category: 'rendering',
+fn: function (){
+var self=this;
+smalltalk.send(self['@div'], "_contents_", [(function(html){return (function($rec){smalltalk.send($rec, "_class_", ["progress"]);return smalltalk.send($rec, "_style_", [smalltalk.send(smalltalk.send("width:", "__comma", [smalltalk.send(smalltalk.send(self, "_percent", []), "_asString", [])]), "__comma", [unescape("%25")])]);})(smalltalk.send(html, "_div", []));})]);
 return self;},
-source: unescape('updatePercent%3A%20aNumber%0A%09self%20percent%3A%20aNumber.%0A%09self%20update'),
-messageSends: ["percent:", "update"],
+source: unescape('renderProgressBar%0A%09div%20contents%3A%20%5B%3Ahtml%20%7C%0A%09%09html%20div%20%0A%09%09%09class%3A%20%27progress%27%3B%0A%09%09%09style%3A%20%27width%3A%27%2C%20self%20percent%20asString%2C%20%27%25%27%5D'),
+messageSends: ["contents:", "class:", "style:", unescape("%2C"), "asString", "percent", "div"],
 referencedClasses: []
 }),
 smalltalk.ProgressBar);
@@ -531,7 +547,7 @@ smalltalk.send(aCollection, "_do_", [(function(each){return smalltalk.send((func
 return self;},
 source: unescape('run%3A%20aCollection%0A%09result%20%3A%3D%20TestResult%20new.%0A%09self%20%0A%09%09updateStatusDiv%3B%0A%09%09updateMethodsList.%0A%09self%20progressBar%20updatePercent%3A%200.%0A%09result%20total%3A%20%28aCollection%20inject%3A%200%20into%3A%20%5B%3Aacc%20%3Aeach%20%7C%20acc%20+%20each%20methods%20size%5D%29.%0A%09aCollection%20do%3A%20%5B%3Aeach%20%7C%20%0A%09%09%5Beach%20runCaseFor%3A%20result.%0A%09%09self%20progressBar%20updatePercent%3A%20result%20runs%20/%20result%20total%20*%20100.%0A%09%09self%20updateStatusDiv.%0A%09%09self%20updateMethodsList%5D%20valueWithTimeout%3A%20100%5D.'),
 messageSends: ["new", "updateStatusDiv", "updateMethodsList", "updatePercent:", "progressBar", "total:", "inject:into:", unescape("+"), "size", "methods", "do:", "valueWithTimeout:", "runCaseFor:", unescape("*"), unescape("/"), "runs", "total"],
-referencedClasses: []
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.TestRunner);
 
@@ -547,7 +563,7 @@ self['@result']=smalltalk.send(smalltalk.TestResult, "_new", []);
 return self;},
 source: unescape('initialize%0A%09super%20initialize.%0A%09result%20%3A%3D%20TestResult%20new'),
 messageSends: ["initialize", "new"],
-referencedClasses: []
+referencedClasses: [smalltalk.nil]
 }),
 smalltalk.TestRunner);
 

+ 103 - 16
js/boot.js

@@ -221,7 +221,7 @@ function Smalltalk(){
     /* Handles Smalltalk message send. Automatically converts undefined to the nil object.
        If the receiver does not understand the selector, call its #doesNotUnderstand: method */
 
-    st.send = function(receiver, selector, args, klass) {
+    sendWithoutContext = function(receiver, selector, args, klass) {
 	if(typeof receiver === "undefined") {
 	    receiver = nil;
 	}
@@ -233,13 +233,67 @@ function Smalltalk(){
 	return messageNotUnderstood(receiver, selector, args);
     };
 
+
+    /* Handles unhandled errors during message sends */
+
+    sendWithContext = function(receiver, selector, args, klass) {
+	if(thisContext) {
+	     return withContextSend(receiver, selector, args, klass);
+	} else {
+	    try {return withContextSend(receiver, selector, args, klass)}
+	    catch(error) {
+		// Reset the context stack in any case
+		thisContext = undefined;
+		if(error.smalltalkError) {
+		    handleError(error);
+		} else {
+		    throw(error);
+		}
+	    }
+	}
+    };
+
+    /* Same as sendWithoutContext but creates a methodContext. */
+
+    withContextSend = function(receiver, selector, args, klass) {
+	var call, context;
+	if(typeof receiver === "undefined") {
+	    receiver = nil;
+	}
+	if(!klass && receiver.klass && receiver[selector]) {
+	    context = pushContext(receiver, selector, args);
+	    call = receiver[selector].apply(receiver, args);
+	    popContext(context);
+	    return call;
+	} else if(klass && klass.fn.prototype[selector]) {
+	    context = pushContext(receiver, selector, args);
+	    call = klass.fn.prototype[selector].apply(receiver, args);
+	    popContext(context);
+	    return call;
+	}
+	return messageNotUnderstood(receiver, selector, args);
+    };
+
+    /*  */
+
+    st.send = sendWithContext;
+
+
+    /* Handles Smalltalk errors. Triggers the registered ErrorHandler 
+       (See the Smalltalk class ErrorHandler and its subclasses */
+    
+    function handleError(error) {
+	thisContext = undefined;
+	smalltalk.ErrorHandler._current()._handleError_(error);
+    }
+
     /* Handles #dnu: *and* JavaScript method calls.
        if the receiver has no klass, we consider it a JS object (outside of the
        Jtalk system). Else assume that the receiver understands #doesNotUnderstand: */
 
     function messageNotUnderstood(receiver, selector, args) {
 	/* Handles JS method calls. */
-	if(receiver.klass === undefined) {
+	if(receiver.klass === undefined || receiver.allowJavaScriptCalls) {
 	    return callJavaScriptMethod(receiver, selector, args);
 	}
 
@@ -248,7 +302,7 @@ function Smalltalk(){
 	
 	return receiver._doesNotUnderstand_(
 	    st.Message._new()
-		._selector_(convertSelector(selector))
+		._selector_(st.convertSelector(selector))
 		._arguments_(args)
 	);
     };
@@ -272,15 +326,30 @@ function Smalltalk(){
 	    return jsProperty
 	}
 	smalltalk.Error._signal_(receiver + ' is not a Jtalk object and "' + jsSelector + '" is undefined')
-    }
+    };
 
 	
+    /* Handle thisContext pseudo variable */
+    
+    pushContext = function(receiver, selector, temps) {
+	if(thisContext) {
+	    return thisContext = thisContext.newContext({receiver: receiver, selector: selector, temps: temps});
+	} else {
+	    return thisContext = new SmalltalkMethodContext({receiver: receiver, selector: selector, temps: temps});
+	}
+    };
+
+    popContext = function(context) {
+	if(context) {
+	    context.removeYourself();
+	}
+    };
 
     /* Convert a string to a valid smalltalk selector.
        if you modify the following functions, also change String>>asSelector
        accordingly */
 
-    function convertSelector(selector) {
+    st.convertSelector = function(selector) {
 	if(selector.match(/__/)) {
 	    return convertBinarySelector(selector);
 	} else {
@@ -327,24 +396,41 @@ function Smalltalk(){
     };
 }
 
-function SmalltalkMethodContext() {
-    this.stack = [];
+function SmalltalkMethodContext(spec) {
+    var that = this;
+    spec = spec || {};
+    that.homeContext = spec.homeContext;
+    that.selector = spec.selector;
+    that.receiver = spec.receiver;
+    that.temps = spec.temps || {};
+
+    that.newContext = function(spec) {
+	spec = spec || {};
+	return new SmalltalkMethodContext({homeContext: that, receiver: spec.receiver, selector: spec.selector, temps: spec.temps});
+    }
 
-    this.push = function(context) {
-	stack.push(context);
-    };
-    
-    this.pop = function() {
-	stack.pop();
-    };
+    that.removeYourself = function() {
+	thisContext = that.homeContext;
+    }
 }
 
 /* Global Smalltalk objects. nil and thisContext shouldn't be globals. */
 
 var nil = new SmalltalkNil();
 var smalltalk = new Smalltalk();
-var thisContext = nil;
+var thisContext = undefined;
+
 
+/* Utilities */
+
+Array.prototype.remove = function(s){
+    var index = this.indexOf(s);
+    if(this.indexOf(s) != -1)this.splice(index, 1);
+}
+
+if(this.jQuery) {
+    this.jQuery.allowJavaScriptCalls = true;
+}
 
 /****************************************************************************************/
 
@@ -374,7 +460,8 @@ smalltalk.mapClassName("Array", "Kernel", Array, smalltalk.SequenceableCollectio
 smalltalk.mapClassName("RegularExpression", "Kernel", RegExp, smalltalk.String);
 
 smalltalk.mapClassName("Error", "Kernel", Error, smalltalk.Object);
+smalltalk.mapClassName("MethodContext", "Kernel", SmalltalkMethodContext, smalltalk.Object);
 
 if(this.CanvasRenderingContext2D) {
     smalltalk.mapClassName("CanvasRenderingContext", "Canvas", CanvasRenderingContext2D, smalltalk.Object);
-}
+}

+ 26 - 3
st/Canvas.st

@@ -94,7 +94,11 @@ with: anObject
 
 initialize
     super initialize.
-    root := TagBrush fromString: 'div' canvas: self
+    root ifNil: [root := TagBrush fromString: 'div' canvas: self]
+!
+
+initializeFromJQuery: aJQuery
+    root := TagBrush fromJQuery: aJQuery canvas: self
 ! !
 
 !HTMLCanvas methodsFor: 'tags'!
@@ -207,6 +211,15 @@ canvas
 	^self tag: 'canvas'
 ! !
 
+!HTMLCanvas class methodsFor: 'instance creation'!
+
+onJQuery: aJQuery
+	^self basicNew
+		initializeFromJQuery: aJQuery;
+		initialize;
+		yourself
+! !
+
 Object subclass: #TagBrush
 	instanceVariableNames: 'canvas element'
 	category: 'Canvas'!
@@ -336,6 +349,11 @@ onClick: aBlock
 initializeFromString: aString canvas: aCanvas
     element := self createElementFor: aString.
     canvas := aCanvas
+!
+
+initializeFromJQuery: aJQuery canvas: aCanvas
+    element := aJQuery jquery get: 0.
+    canvas := aCanvas
 ! !
 
 !TagBrush methodsFor: 'private'!
@@ -354,6 +372,12 @@ fromString: aString canvas: aCanvas
     ^self new
 	initializeFromString: aString canvas: aCanvas;
 	yourself
+!
+
+fromJQuery: aJQuery canvas: aCanvas
+    ^self new
+	initializeFromJQuery: aJQuery canvas: aCanvas;
+	yourself
 ! !
 
 Object subclass: #Widget
@@ -399,8 +423,7 @@ appendToBrush: aTagBrush
 !
 
 appendToJQuery: aJQuery
-    self render.
-    aJQuery append: self root asJQuery
+   self renderOn: (HTMLCanvas onJQuery: aJQuery)
 ! !
 
 !Widget methodsFor: 'rendering'!

+ 3 - 2
st/Compiler.st

@@ -461,7 +461,8 @@ recompile: aClass
 
 recompileAll
 	Smalltalk current classes do: [:each |
-		self recompile: each]
+		Transcript show: each; cr.
+		[self recompile: each] valueWithTimeout: 100]
 !
 
 setupClass: aClass
@@ -690,6 +691,6 @@ Object subclass: #DoIt
 
 !DoIt methodsFor: ''!
 
-doIt ^[<self["@"+'foo']>] value
+doIt ^[Compiler new recompileAll] value
 ! !
 

+ 86 - 37
st/IDE.st

@@ -1,5 +1,5 @@
 Widget subclass: #TabManager
-	instanceVariableNames: 'selectedTab tabs opened'
+	instanceVariableNames: 'selectedTab tabs opened ul'
 	category: 'IDE'!
 
 !TabManager methodsFor: 'accessing'!
@@ -40,18 +40,19 @@ onWindowResize: aBlock
 
 open
     opened ifFalse: [
-	self root asJQuery show.
 	'body' asJQuery addClass: 'jtalkBody'.
 	'#jtalk' asJQuery show.
+	ul asJQuery show.
 	self updateBodyMargin.
-	selectedTab root asJQuery show.
+	selectedTab show.
 	opened := true]
 !
 
 close
     opened ifTrue: [
-	self root asJQuery hide.
 	'#jtalk' asJQuery hide.
+	ul asJQuery hide.
+	selectedTab hide.
 	self removeBodyMargin.
 	'body' asJQuery removeClass: 'jtalkBody'.
 	opened := false]
@@ -65,15 +66,16 @@ selectTab: aWidget
     self open.
     selectedTab := aWidget.
     self tabs do: [:each |
-	each root asJQuery hide].
-    aWidget root asJQuery show.
+	each hide].
+    aWidget show.
+	
     self update
 !
 
 closeTab: aWidget
     self removeTab: aWidget.
     self selectTab: self tabs last.
-    aWidget root asJQuery remove.
+    aWidget remove.
     self update
 ! !
 
@@ -82,7 +84,7 @@ closeTab: aWidget
 addTab: aWidget
     self tabs add: aWidget.
     '#jtalk' asJQuery append: aWidget.
-    aWidget root asJQuery hide
+    aWidget hide
 !
 
 removeTab: aWidget
@@ -111,19 +113,10 @@ initialize
 !TabManager methodsFor: 'rendering'!
 
 renderOn: html
-    html ul
-	id: 'jtalkTabs';
-	with: [
-	    html li 
-		class: 'closeAll';
-		with: 'x';
-		onClick: [self close].
-	    self tabs do: [:each |
-		self renderTabFor: each on: html].
-	    html li
-		class: 'newtab';
-		with: ' + ';
-		onClick: [self newBrowserTab]]
+	ul := html ul
+		id: 'jtalkTabs';
+		yourself.
+	self renderTabs
 !
 
 renderTabFor: aWidget on: html
@@ -140,6 +133,26 @@ renderTabFor: aWidget on: html
 		class: 'close';
 		with: 'x';
 		onClick: [self closeTab: aWidget]]]
+!
+
+renderTabs
+	ul contents: [:html |
+	    html li 
+		class: 'closeAll';
+		with: 'x';
+		onClick: [self close].
+	    self tabs do: [:each |
+		self renderTabFor: each on: html].
+	    html li
+		class: 'newtab';
+		with: ' + ';
+		onClick: [self newBrowserTab]]
+! !
+
+!TabManager methodsFor: 'updating'!
+
+update
+	self renderTabs
 ! !
 
 TabManager class instanceVariableNames: 'current'!
@@ -155,7 +168,7 @@ new
 ! !
 
 Widget subclass: #TabWidget
-	instanceVariableNames: ''
+	instanceVariableNames: 'div'
 	category: 'IDE'!
 
 !TabWidget methodsFor: 'accessing'!
@@ -167,29 +180,49 @@ label
 !TabWidget methodsFor: 'actions'!
 
 open
-    TabManager current
-	addTab: self;
-	selectTab: self
+    TabManager current addTab: self.
+    TabManager current selectTab: self
+!
+
+show
+	div asJQuery show
+!
+
+hide
+	div asJQuery hide
+!
+
+remove
+	div asJQuery remove
 ! !
 
 !TabWidget methodsFor: 'rendering'!
 
 renderOn: html
-    html root
-	class: 'jtalkTool';
-	with: [
-	    html div
-		class: 'jt_box';
-		with: [self renderBoxOn: html].
-	    html div
-		class: 'jt_buttons';
-		with: [self renderButtonsOn: html]]
+	div := html div
+		class: 'jtalkTool';
+		yourself.
+	self renderTab
 !
 
 renderBoxOn: html
 !
 
 renderButtonsOn: html
+!
+
+update
+	self renderTab
+!
+
+renderTab
+	div contents: [:html |
+	    html div
+		class: 'jt_box';
+		with: [self renderBoxOn: html].
+	    html div
+		class: 'jt_buttons';
+		with: [self renderButtonsOn: html]]
 ! !
 
 !TabWidget methodsFor: 'testing'!
@@ -593,7 +626,7 @@ compileMethodDefinitionFor: aClass
     node := compiler parse: source.
     node isParseFailure ifTrue: [
 	^self alert: 'PARSE ERROR: ', node reason, ', position: ', node position asString].
-    compiler currentClass: selectedClass.
+    compiler currentClass: aClass.
     method := compiler eval: (compiler compileNode: node).
     method category: selectedProtocol.
     compiler unknownVariables do: [:each |
@@ -818,7 +851,7 @@ renderButtonsOn: html
     self updateSourceAndButtons
 !
 
-renderInputOn: html
+renderInputOn: html 
 	input := html input 
 		class: 'implementors';
 		yourself.
@@ -1301,7 +1334,7 @@ inspectOn: anInspector
 	| variables |
 	variables := Dictionary new.
 	variables at: '#self' put: self.
-	self class instanceVariableNames do: [:each |
+	self class allInstanceVariableNames do: [:each |
 		variables at: each put: (self instVarAt: each)].
 	anInspector 
 		setLabel: self printString;
@@ -1350,6 +1383,22 @@ inspectOn: anInspector
 	anInspector setLabel: label
 ! !
 
+!MethodContext methodsFor: '*IDE'!
+
+inspectOn: anInspector
+	| variables |
+	variables := Dictionary new.
+	variables at: '#self' put: self.
+	variables at: '#home' put: self home.
+	variables at: '#receiver' put: self receiver.
+	variables at: '#selector' put: self selector.
+	self class instanceVariableNames do: [:each |
+		variables at: each put: (self instVarAt: each)].
+	anInspector 
+		setLabel: self printString;
+		setVariables: variables
+! !
+
 !Dictionary methodsFor: '*IDE'!
 
 inspectOn: anInspector

+ 24 - 15
st/JQuery.st

@@ -28,6 +28,12 @@ empty
     ^self call: 'empty'
 ! !
 
+!JQuery methodsFor: 'accessing'!
+
+jquery
+	^jquery
+! !
+
 !JQuery methodsFor: 'attributes'!
 
 removeAttribute: aString
@@ -52,11 +58,11 @@ val: aString
 !JQuery methodsFor: 'css'!
 
 cssAt: aString
-	{'return self[''@jquery''].css(aString)'}
+	<return self['@jquery'].css(aString)>
 !
 
 cssAt: aString put: anotherString
-    {'self[''@jquery''].css(aString, anotherString)'}
+    <self['@jquery'].css(aString, anotherString)>
 !
 
 addClass: aString
@@ -170,7 +176,7 @@ remove
 
 on: anEventString do: aBlock
     "Attach aBlock for anEventString on the element"
-    {'self[''@jquery''].bind(anEventString, function(e){aBlock(e, self)})'}
+    <self['@jquery'].bind(anEventString, function(e){aBlock(e, self)})>
 !
 
 removeEvents: aString
@@ -187,11 +193,11 @@ initializeWithJQueryObject: anObject
 !JQuery methodsFor: 'private'!
 
 call: aString
-	{'return self[''@jquery''][aString]()'}
+	<return self['@jquery'][aString]()>
 !
 
 call: aString withArgument: anObject
-    {'return self[''@jquery''][aString](anObject)'}
+    <return self['@jquery'][aString](anObject)>
 ! !
 
 !JQuery methodsFor: 'testing'!
@@ -205,7 +211,7 @@ hasClass: aString
 
 fromString: aString
     | newJQuery |
-    {'newJQuery = jQuery(String(aString))'}.
+    <newJQuery = jQuery(String(aString))>.
     ^self from: newJQuery
 !
 
@@ -216,15 +222,21 @@ from: anObject
 !
 
 window
-	{'return self._from_(jQuery(window))'}
+	<return self._from_(jQuery(window))>
 !
 
 body
-	{'return self._from_(jQuery(body))'}
+	<return self._from_(jQuery('body'))>
 !
 
 document
-	{'return self._from_(jQuery(document))'}
+	<return self._from_(jQuery(document))>
+!
+
+fromElement: anElement
+    | newJQuery |
+    <newJQuery = jQuery(anElement)>.
+    ^self from: newJQuery
 ! !
 
 Object subclass: #Ajax
@@ -257,7 +269,7 @@ url: aString
 !Ajax methodsFor: 'actions'!
 
 send
-    {'jQuery.ajax(self[''@settings''])'}
+    <jQuery.ajax(self['@settings'])>
 ! !
 
 !Ajax methodsFor: 'initialization'!
@@ -278,10 +290,7 @@ url: aString
 !BlockClosure methodsFor: '*JQuery'!
 
 appendToJQuery: aJQuery
-	| canvas |
-	canvas := HTMLCanvas new.
-	self value: canvas.
-	aJQuery append: canvas
+	self value: (HTMLCanvas onJQuery: aJQuery)
 ! !
 
 !String methodsFor: '*JQuery'!
@@ -291,7 +300,7 @@ asJQuery
 !
 
 appendToJQuery: aJQuery
-    {'aJQuery._appendElement_(String(self))'}
+    <aJQuery._appendElement_(String(self))>
 ! !
 
 !HTMLCanvas methodsFor: '*JQuery'!

+ 103 - 2
st/Kernel.st

@@ -128,6 +128,10 @@ doesNotUnderstand: aMessage
 		receiver: self;
 		message: aMessage;
 		signal
+!
+
+halt
+	self error: 'Halt encountered'
 ! !
 
 !Object methodsFor: 'initialization'!
@@ -357,6 +361,14 @@ protocolsDo: aBlock
  			add: m]. 
 	self protocols do: [:category |
 		aBlock value: category value: (methodsByCategory at: category)]
+!
+
+allInstanceVariableNames
+	| result |
+	result := self instanceVariableNames.
+	self superclass ifNotNil: [
+	    result addAll: self superclass allInstanceVariableNames].
+	^result
 ! !
 
 !Behavior methodsFor: 'instance creation'!
@@ -1638,7 +1650,7 @@ compile: aString
 !
 
 exec: aString
-	<return self.exec(aString)>
+	<return self.exec(aString) || nil>
 !
 
 test: aString
@@ -1667,12 +1679,16 @@ messageText
 
 messageText: aString
 	messageText := aString
+!
+
+context
+	<return self.context>
 ! !
 
 !Error methodsFor: 'signaling'!
 
 signal
-	<console.log(self._messageText()); throw(self)>
+	<self.context = thisContext; self.smalltalkError = true; throw(self)>
 ! !
 
 !Error class methodsFor: 'instance creation'!
@@ -1683,6 +1699,36 @@ signal: aString
 		signal
 ! !
 
+Object subclass: #MethodContext
+	instanceVariableNames: ''
+	category: 'Kernel'!
+
+!MethodContext methodsFor: 'accessing'!
+
+receiver
+	<return self.receiver>
+!
+
+selector
+	<return smalltalk.convertSelector(self.selector)>
+!
+
+home
+	<return self.homeContext>
+!
+
+temps
+	<return self.temps>
+!
+
+printString
+	^super printString, '(', self asString, ')'
+!
+
+asString
+	^self receiver class printString, ' >> ', self selector
+! !
+
 Object subclass: #Association
 	instanceVariableNames: 'key value'
 	category: 'Kernel'!
@@ -2286,3 +2332,58 @@ messageText
 	^self receiver asString, ' does not understand #', self message selector
 ! !
 
+Object subclass: #ErrorHandler
+	instanceVariableNames: ''
+	category: 'Kernel'!
+
+!ErrorHandler methodsFor: 'error handling'!
+
+handleError: anError
+	anError context ifNotNil: [self logErrorContext: anError context].
+	self logError: anError
+! !
+
+!ErrorHandler methodsFor: 'private'!
+
+logContext: aContext
+	aContext home ifNotNil: [
+		self logContext: aContext home].
+	self log: aContext receiver asString, '>>', aContext selector
+!
+
+logErrorContext: aContext
+	aContext ifNotNil: [
+		aContext home ifNotNil: [
+			self logContext: aContext home]]
+!
+
+logError: anError
+	self log: anError messageText
+!
+
+log: aString
+	console log: aString
+! !
+
+ErrorHandler class instanceVariableNames: 'current'!
+
+!ErrorHandler class methodsFor: 'accessing'!
+
+current
+	^current
+!
+
+setCurrent: anHandler
+	current := anHandler
+! !
+
+!ErrorHandler class methodsFor: 'initialization'!
+
+initialize
+	self register
+!
+
+register
+	ErrorHandler setCurrent: self new
+! !
+

+ 12 - 7
st/SUnit.st

@@ -87,7 +87,7 @@ testError
 ! !
 
 TabWidget subclass: #ProgressBar
-	instanceVariableNames: 'percent progressDiv'
+	instanceVariableNames: 'percent progressDiv div'
 	category: 'SUnit'!
 
 !ProgressBar methodsFor: 'accessing'!
@@ -103,19 +103,24 @@ percent: aNumber
 !ProgressBar methodsFor: 'rendering'!
 
 renderOn: html 
-	html div 
+	div := html div 
 		class: 'progress_bar';
-		with: [
-			html div 
-				class: 'progress';
-				style: 'width:', self percent asString, '%']
+		yourself.
+	self renderProgressBar
+!
+
+renderProgressBar
+	div contents: [:html |
+		html div 
+			class: 'progress';
+			style: 'width:', self percent asString, '%']
 ! !
 
 !ProgressBar methodsFor: 'updating'!
 
 updatePercent: aNumber
 	self percent: aNumber.
-	self update
+	self renderProgressBar
 ! !
 
 Error subclass: #TestFailure