Browse Source

Merge branch 'traits-in-core'

Herbert Vojčík 7 years ago
parent
commit
665bb3d359

+ 8 - 0
API-CHANGES.txt

@@ -1,3 +1,11 @@
+0.19.0:
+
+* Remove class Thenable, add trait TThenable.
+
++ NativeFunction class >>
+  + isNativeFunction:
+
+
 0.18.6:
 
 + IRInstructions >>

+ 9 - 0
CHANGELOG

@@ -1,3 +1,12 @@
+?? March 2017 - Release 0.19.0
+===================================
+
+* Removed BehaviorBody in favour of traits TBehaviorDefaults and TBehaviorProvider.
+* Move Thenable class to TThenable trait.
+
+Commits: https://lolg.it/amber/amber/commits/0.19.0.
+
+
 ? April 2017 - Release 0.18.6
 ===================================
 

+ 2 - 1
Gruntfile.js

@@ -44,7 +44,8 @@ module.exports = function (grunt) {
             },
             amber: {
                 output_dir: 'src',
-                src: ['src/Kernel-Objects.st', 'src/Kernel-Classes.st', 'src/Kernel-Methods.st', 'src/Kernel-Collections.st',
+                src: ['src/Kernel-Helpers.st',
+                    'src/Kernel-Objects.st', 'src/Kernel-Classes.st', 'src/Kernel-Methods.st', 'src/Kernel-Collections.st',
                     'src/Kernel-Infrastructure.st', 'src/Kernel-Promises.st', 'src/Kernel-Exceptions.st', 'src/Kernel-Announcements.st',
                     'src/Platform-Services.st', 'src/Platform-ImportExport.st', 'src/Platform-Browser.st', 'src/Platform-Node.st',
                     'src/Platform-DOM.st',

File diff suppressed because it is too large
+ 569 - 452
src/Kernel-Classes.js


File diff suppressed because it is too large
+ 495 - 572
src/Kernel-Classes.st


+ 243 - 0
src/Kernel-Helpers.js

@@ -0,0 +1,243 @@
+define(["amber/boot"], function($boot){"use strict";
+if(!$boot.nilAsReceiver)$boot.nilAsReceiver=$boot.nil;
+var $core=$boot.api,nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
+if(!$boot.nilAsClass)$boot.nilAsClass=$boot.dnu;
+$core.addPackage("Kernel-Helpers");
+$core.packages["Kernel-Helpers"].innerEval = function (expr) { return eval(expr); };
+$core.packages["Kernel-Helpers"].transport = {"type":"amd","amdNamespace":"amber_core"};
+
+$core.addTrait("TSubclassable", "Kernel-Helpers");
+$core.addMethod(
+$core.method({
+selector: "subclass:",
+protocol: "class creation",
+fn: function (aString){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_instanceVariableNames_package_(aString,"",nil);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:",{aString:aString},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString"],
+source: "subclass: aString \x0a\x09\x22Kept for file-in compatibility.\x22\x0a\x09^ self subclass: aString instanceVariableNames: '' package: nil",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:instanceVariableNames:",
+protocol: "class creation",
+fn: function (aString,anotherString){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_instanceVariableNames_package_(aString,anotherString,nil);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:instanceVariableNames:",{aString:aString,anotherString:anotherString},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "anotherString"],
+source: "subclass: aString instanceVariableNames: anotherString\x0a\x09\x22Kept for file-in compatibility.\x22\x0a\x09^ self subclass: aString instanceVariableNames: anotherString package: nil",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:instanceVariableNames:category:",
+protocol: "class creation",
+fn: function (aString,aString2,aString3){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_instanceVariableNames_package_(aString,aString2,aString3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:instanceVariableNames:category:",{aString:aString,aString2:aString2,aString3:aString3},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aString2", "aString3"],
+source: "subclass: aString instanceVariableNames: aString2 category: aString3\x0a\x09\x22Kept for file-in compatibility.\x22\x0a\x09^ self subclass: aString instanceVariableNames: aString2 package: aString3",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:",
+protocol: "class creation",
+fn: function (aString,aString2,classVars,pools,aString3){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_instanceVariableNames_package_(aString,aString2,aString3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:",{aString:aString,aString2:aString2,classVars:classVars,pools:pools,aString3:aString3},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aString2", "classVars", "pools", "aString3"],
+source: "subclass: aString instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3\x0a\x09\x22Kept for file-in compatibility. ignores class variables and pools.\x22\x0a\x09^ self subclass: aString instanceVariableNames: aString2 package: aString3",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:instanceVariableNames:package:",
+protocol: "class creation",
+fn: function (aString,aString2,aString3){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($recv($globals.ClassBuilder)._new())._superclass_subclass_instanceVariableNames_package_(self,$recv(aString)._asString(),aString2,aString3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:instanceVariableNames:package:",{aString:aString,aString2:aString2,aString3:aString3},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aString2", "aString3"],
+source: "subclass: aString instanceVariableNames: aString2 package: aString3\x0a\x09^ ClassBuilder new\x0a\x09\x09superclass: self subclass: aString asString instanceVariableNames: aString2 package: aString3",
+referencedClasses: ["ClassBuilder"],
+//>>excludeEnd("ide");
+messageSends: ["superclass:subclass:instanceVariableNames:package:", "new", "asString"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:uses:",
+protocol: "class creation",
+fn: function (aString,aTraitCompositionDescription){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_uses_instanceVariableNames_package_(aString,aTraitCompositionDescription,"",nil);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:uses:",{aString:aString,aTraitCompositionDescription:aTraitCompositionDescription},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aTraitCompositionDescription"],
+source: "subclass: aString uses: aTraitCompositionDescription \x0a\x09\x22Kept for file-in compatibility.\x22\x0a\x09^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: '' package: nil",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:uses:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:uses:instanceVariableNames:",
+protocol: "class creation",
+fn: function (aString,aTraitCompositionDescription,anotherString){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_uses_instanceVariableNames_package_(aString,aTraitCompositionDescription,anotherString,nil);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:uses:instanceVariableNames:",{aString:aString,aTraitCompositionDescription:aTraitCompositionDescription,anotherString:anotherString},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aTraitCompositionDescription", "anotherString"],
+source: "subclass: aString uses: aTraitCompositionDescription instanceVariableNames: anotherString\x0a\x09\x22Kept for file-in compatibility.\x22\x0a\x09^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: anotherString package: nil",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:uses:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:uses:instanceVariableNames:category:",
+protocol: "class creation",
+fn: function (aString,aTraitCompositionDescription,aString2,aString3){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_uses_instanceVariableNames_package_(aString,aTraitCompositionDescription,aString2,aString3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:uses:instanceVariableNames:category:",{aString:aString,aTraitCompositionDescription:aTraitCompositionDescription,aString2:aString2,aString3:aString3},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aTraitCompositionDescription", "aString2", "aString3"],
+source: "subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 category: aString3\x0a\x09\x22Kept for file-in compatibility.\x22\x0a\x09^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 package: aString3",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:uses:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:uses:instanceVariableNames:classVariableNames:poolDictionaries:category:",
+protocol: "class creation",
+fn: function (aString,aTraitCompositionDescription,aString2,classVars,pools,aString3){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._subclass_uses_instanceVariableNames_package_(aString,aTraitCompositionDescription,aString2,aString3);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:uses:instanceVariableNames:classVariableNames:poolDictionaries:category:",{aString:aString,aTraitCompositionDescription:aTraitCompositionDescription,aString2:aString2,classVars:classVars,pools:pools,aString3:aString3},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aTraitCompositionDescription", "aString2", "classVars", "pools", "aString3"],
+source: "subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3\x0a\x09\x22Kept for file-in compatibility. ignores class variables and pools.\x22\x0a\x09^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 package: aString3",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:uses:instanceVariableNames:package:"]
+}),
+$globals.TSubclassable);
+
+$core.addMethod(
+$core.method({
+selector: "subclass:uses:instanceVariableNames:package:",
+protocol: "class creation",
+fn: function (aString,aTraitCompositionDescription,aString2,aString3){
+var self=this,$self=this;
+var cls;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+cls=$self._subclass_instanceVariableNames_package_(aString,aString2,aString3);
+$recv(cls)._setTraitComposition_($recv(aTraitCompositionDescription)._asTraitComposition());
+return cls;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"subclass:uses:instanceVariableNames:package:",{aString:aString,aTraitCompositionDescription:aTraitCompositionDescription,aString2:aString2,aString3:aString3,cls:cls},$globals.TSubclassable)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aTraitCompositionDescription", "aString2", "aString3"],
+source: "subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 package: aString3\x0a\x09| cls |\x0a\x09cls := self subclass: aString instanceVariableNames: aString2 package: aString3.\x0a\x09cls setTraitComposition: aTraitCompositionDescription asTraitComposition.\x0a\x09^ cls",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["subclass:instanceVariableNames:package:", "setTraitComposition:", "asTraitComposition"]
+}),
+$globals.TSubclassable);
+
+});

+ 58 - 0
src/Kernel-Helpers.st

@@ -0,0 +1,58 @@
+Smalltalk createPackage: 'Kernel-Helpers'!
+Trait named: #TSubclassable
+	package: 'Kernel-Helpers'!
+
+!TSubclassable methodsFor: 'class creation'!
+
+subclass: aString 
+	"Kept for file-in compatibility."
+	^ self subclass: aString instanceVariableNames: '' package: nil
+!
+
+subclass: aString instanceVariableNames: anotherString
+	"Kept for file-in compatibility."
+	^ self subclass: aString instanceVariableNames: anotherString package: nil
+!
+
+subclass: aString instanceVariableNames: aString2 category: aString3
+	"Kept for file-in compatibility."
+	^ self subclass: aString instanceVariableNames: aString2 package: aString3
+!
+
+subclass: aString instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3
+	"Kept for file-in compatibility. ignores class variables and pools."
+	^ self subclass: aString instanceVariableNames: aString2 package: aString3
+!
+
+subclass: aString instanceVariableNames: aString2 package: aString3
+	^ ClassBuilder new
+		superclass: self subclass: aString asString instanceVariableNames: aString2 package: aString3
+!
+
+subclass: aString uses: aTraitCompositionDescription 
+	"Kept for file-in compatibility."
+	^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: '' package: nil
+!
+
+subclass: aString uses: aTraitCompositionDescription instanceVariableNames: anotherString
+	"Kept for file-in compatibility."
+	^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: anotherString package: nil
+!
+
+subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 category: aString3
+	"Kept for file-in compatibility."
+	^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 package: aString3
+!
+
+subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 classVariableNames: classVars poolDictionaries: pools category: aString3
+	"Kept for file-in compatibility. ignores class variables and pools."
+	^ self subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 package: aString3
+!
+
+subclass: aString uses: aTraitCompositionDescription instanceVariableNames: aString2 package: aString3
+	| cls |
+	cls := self subclass: aString instanceVariableNames: aString2 package: aString3.
+	cls setTraitComposition: aTraitCompositionDescription asTraitComposition.
+	^ cls
+! !
+

+ 117 - 1
src/Kernel-Infrastructure.js

@@ -1,4 +1,4 @@
-define(["amber/boot", "amber_core/Kernel-Collections", "amber_core/Kernel-Exceptions", "amber_core/Kernel-Objects"], function($boot){"use strict";
+define(["amber/boot", "amber_core/Kernel-Collections", "amber_core/Kernel-Exceptions", "amber_core/Kernel-Objects", "amber_core/Kernel-Promises"], function($boot){"use strict";
 if(!$boot.nilAsReceiver)$boot.nilAsReceiver=$boot.nil;
 var $core=$boot.api,nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
 if(!$boot.nilAsClass)$boot.nilAsClass=$boot.dnu;
@@ -189,6 +189,44 @@ messageSends: []
 }),
 $globals.JSObjectProxy);
 
+$core.addMethod(
+$core.method({
+selector: "catch:",
+protocol: "promises",
+fn: function (aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2;
+$1=$recv($globals.NativeFunction)._isNativeFunction_($self._at_("then"));
+if($core.assert($1)){
+return $recv($recv($globals.TThenable).__gt_gt("catch:"))._sendTo_arguments_($self["@jsObject"],[aBlock]);
+} else {
+$2=(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($globals.JSObjectProxy.superclass||$boot.nilAsClass).fn.prototype._catch_.apply($self, [aBlock]));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+return $2;
+}
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"catch:",{aBlock:aBlock},$globals.JSObjectProxy)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aBlock"],
+source: "catch: aBlock\x0a(NativeFunction isNativeFunction: (self at: #then))\x0a\x09ifTrue: [ ^ (TThenable >> #catch:) sendTo: jsObject arguments: {aBlock} ]\x0a\x09ifFalse: [ ^ super catch: aBlock ]",
+referencedClasses: ["NativeFunction", "TThenable"],
+//>>excludeEnd("ide");
+messageSends: ["ifTrue:ifFalse:", "isNativeFunction:", "at:", "sendTo:arguments:", ">>", "catch:"]
+}),
+$globals.JSObjectProxy);
+
 $core.addMethod(
 $core.method({
 selector: "doesNotUnderstand:",
@@ -297,6 +335,44 @@ messageSends: []
 }),
 $globals.JSObjectProxy);
 
+$core.addMethod(
+$core.method({
+selector: "on:do:",
+protocol: "promises",
+fn: function (aClass,aBlock){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2;
+$1=$recv($globals.NativeFunction)._isNativeFunction_($self._at_("then"));
+if($core.assert($1)){
+return $recv($recv($globals.TThenable).__gt_gt("on:do:"))._sendTo_arguments_($self["@jsObject"],[aClass,aBlock]);
+} else {
+$2=(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($globals.JSObjectProxy.superclass||$boot.nilAsClass).fn.prototype._on_do_.apply($self, [aClass,aBlock]));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+return $2;
+}
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"on:do:",{aClass:aClass,aBlock:aBlock},$globals.JSObjectProxy)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aClass", "aBlock"],
+source: "on: aClass do: aBlock\x0a(NativeFunction isNativeFunction: (self at: #then))\x0a\x09ifTrue: [ ^ (TThenable >> #on:do:) sendTo: jsObject arguments: {aClass. aBlock} ]\x0a\x09ifFalse: [ ^ super on: aClass do: aBlock ]",
+referencedClasses: ["NativeFunction", "TThenable"],
+//>>excludeEnd("ide");
+messageSends: ["ifTrue:ifFalse:", "isNativeFunction:", "at:", "sendTo:arguments:", ">>", "on:do:"]
+}),
+$globals.JSObjectProxy);
+
 $core.addMethod(
 $core.method({
 selector: "printOn:",
@@ -374,6 +450,44 @@ messageSends: ["nextPutJSObject:"]
 }),
 $globals.JSObjectProxy);
 
+$core.addMethod(
+$core.method({
+selector: "then:",
+protocol: "promises",
+fn: function (aBlockOrArray){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2;
+$1=$recv($globals.NativeFunction)._isNativeFunction_($self._at_("then"));
+if($core.assert($1)){
+return $recv($recv($globals.TThenable).__gt_gt("then:"))._sendTo_arguments_($self["@jsObject"],[aBlockOrArray]);
+} else {
+$2=(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($globals.JSObjectProxy.superclass||$boot.nilAsClass).fn.prototype._then_.apply($self, [aBlockOrArray]));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+return $2;
+}
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"then:",{aBlockOrArray:aBlockOrArray},$globals.JSObjectProxy)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aBlockOrArray"],
+source: "then: aBlockOrArray\x0a(NativeFunction isNativeFunction: (self at: #then))\x0a\x09ifTrue: [ ^ (TThenable >> #then:) sendTo: jsObject arguments: {aBlockOrArray} ]\x0a\x09ifFalse: [ ^ super then: aBlockOrArray ]",
+referencedClasses: ["NativeFunction", "TThenable"],
+//>>excludeEnd("ide");
+messageSends: ["ifTrue:ifFalse:", "isNativeFunction:", "at:", "sendTo:arguments:", ">>", "then:"]
+}),
+$globals.JSObjectProxy);
+
 
 $core.addMethod(
 $core.method({
@@ -3491,6 +3605,8 @@ messageSends: ["shouldNotImplement"]
 }),
 $globals.SmalltalkImage.a$cls);
 
+$core.setTraitComposition([{trait: $globals.TThenable}], $globals.JSObjectProxy);
+
 $core.addMethod(
 $core.method({
 selector: "nextPutJSObject:",

+ 23 - 0
src/Kernel-Infrastructure.st

@@ -111,6 +111,26 @@ printString
 	'>
 ! !
 
+!JSObjectProxy methodsFor: 'promises'!
+
+catch: aBlock
+(NativeFunction isNativeFunction: (self at: #then))
+	ifTrue: [ ^ (TThenable >> #catch:) sendTo: jsObject arguments: {aBlock} ]
+	ifFalse: [ ^ super catch: aBlock ]
+!
+
+on: aClass do: aBlock
+(NativeFunction isNativeFunction: (self at: #then))
+	ifTrue: [ ^ (TThenable >> #on:do:) sendTo: jsObject arguments: {aClass. aBlock} ]
+	ifFalse: [ ^ super on: aClass do: aBlock ]
+!
+
+then: aBlockOrArray
+(NativeFunction isNativeFunction: (self at: #then))
+	ifTrue: [ ^ (TThenable >> #then:) sendTo: jsObject arguments: {aBlockOrArray} ]
+	ifFalse: [ ^ super then: aBlockOrArray ]
+! !
+
 !JSObjectProxy methodsFor: 'proxy'!
 
 doesNotUnderstand: aMessage
@@ -946,6 +966,9 @@ new
 	self shouldNotImplement
 ! !
 
+JSObjectProxy setTraitComposition: {TThenable} asTraitComposition!
+! !
+
 !ProtoStream methodsFor: '*Kernel-Infrastructure'!
 
 nextPutJSObject: aJSObject

+ 24 - 0
src/Kernel-Methods.js

@@ -3142,6 +3142,30 @@ messageSends: []
 }),
 $globals.NativeFunction.a$cls);
 
+$core.addMethod(
+$core.method({
+selector: "isNativeFunction:",
+protocol: "testing",
+fn: function (anObject){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return typeof anObject === "function";
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isNativeFunction:",{anObject:anObject},$globals.NativeFunction.a$cls)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "isNativeFunction: anObject\x0a\x09<inlineJS: 'return typeof anObject === \x22function\x22'>",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.NativeFunction.a$cls);
+
 $core.addMethod(
 $core.method({
 selector: "methodOf:this:",

+ 4 - 0
src/Kernel-Methods.st

@@ -854,6 +854,10 @@ methodOf: nativeFunc this: thisObject valueWithArgs: args
 
 exists: aString
 	^ Smalltalk existsJsGlobal: aString
+!
+
+isNativeFunction: anObject
+	<inlineJS: 'return typeof anObject === "function"'>
 ! !
 
 Object subclass: #Timeout

+ 3 - 1
src/Kernel-Objects.js

@@ -1,4 +1,4 @@
-define(["amber/boot"], function($boot){"use strict";
+define(["amber/boot", "amber_core/Kernel-Helpers"], function($boot){"use strict";
 if(!$boot.nilAsReceiver)$boot.nilAsReceiver=$boot.nil;
 var $core=$boot.api,nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
 if(!$boot.nilAsClass)$boot.nilAsClass=$boot.dnu;
@@ -5840,4 +5840,6 @@ messageSends: ["error:"]
 }),
 $globals.UndefinedObject.a$cls);
 
+$core.setTraitComposition([{trait: $globals.TSubclassable}], $globals.UndefinedObject);
+
 });

+ 3 - 0
src/Kernel-Objects.st

@@ -1384,3 +1384,6 @@ new
 		self error: 'You cannot create new instances of UndefinedObject. Use nil'
 ! !
 
+UndefinedObject setTraitComposition: {TSubclassable} asTraitComposition!
+! !
+

+ 64 - 294
src/Kernel-Promises.js

@@ -1,4 +1,4 @@
-define(["amber/boot", "amber_core/Kernel-Infrastructure", "amber_core/Kernel-Objects"], function($boot){"use strict";
+define(["amber/boot", "amber_core/Kernel-Objects"], function($boot){"use strict";
 if(!$boot.nilAsReceiver)$boot.nilAsReceiver=$boot.nil;
 var $core=$boot.api,nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
 if(!$boot.nilAsClass)$boot.nilAsClass=$boot.dnu;
@@ -6,201 +6,7 @@ $core.addPackage("Kernel-Promises");
 $core.packages["Kernel-Promises"].innerEval = function (expr) { return eval(expr); };
 $core.packages["Kernel-Promises"].transport = {"type":"amd","amdNamespace":"amber_core"};
 
-$core.addClass("Thenable", $globals.Object, [], "Kernel-Promises");
-//>>excludeStart("ide", pragmas.excludeIdeData);
-$globals.Thenable.comment="I am the abstract base class for Promises.\x0a\x0aMy subclasses should wrap existing JS implementations.\x0a\x0aI contain methods that wrap Promises/A+ `.then` behaviour.";
-//>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "catch:",
-protocol: "promises",
-fn: function (aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return self.then(null, function (err) {return $core.seamless(function () {
-    return aBlock._value_(err);
-})});
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"catch:",{aBlock:aBlock},$globals.Thenable)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlock"],
-source: "catch: aBlock\x0a<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {\x0a    return aBlock._value_(err);\x0a})})'>",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.Thenable);
-
-$core.addMethod(
-$core.method({
-selector: "on:do:",
-protocol: "promises",
-fn: function (aClass,aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return self.then(null, function (err) {return $core.seamless(function () {
-    if (err._isKindOf_(aClass)) return aBlock._value_(err);
-    else throw err;
-})});
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"on:do:",{aClass:aClass,aBlock:aBlock},$globals.Thenable)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aClass", "aBlock"],
-source: "on: aClass do: aBlock\x0a<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {\x0a    if (err._isKindOf_(aClass)) return aBlock._value_(err);\x0a    else throw err;\x0a})})'>",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.Thenable);
-
-$core.addMethod(
-$core.method({
-selector: "on:do:catch:",
-protocol: "promises",
-fn: function (aClass,aBlock,anotherBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return self.then(null, function (err) {return $core.seamless(function () {
-    try { if (err._isKindOf_(aClass)) return aBlock._value_(err); } catch (e) { err = e; }
-    return anotherBlock._value_(err);
-})});
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"on:do:catch:",{aClass:aClass,aBlock:aBlock,anotherBlock:anotherBlock},$globals.Thenable)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aClass", "aBlock", "anotherBlock"],
-source: "on: aClass do: aBlock catch: anotherBlock\x0a<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {\x0a    try { if (err._isKindOf_(aClass)) return aBlock._value_(err); } catch (e) { err = e; }\x0a    return anotherBlock._value_(err);\x0a})})'>",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.Thenable);
-
-$core.addMethod(
-$core.method({
-selector: "then:",
-protocol: "promises",
-fn: function (aBlockOrArray){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-
-var array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];
-return array.reduce(function (soFar, aBlock) {
-    return soFar.then(typeof aBlock === "function" && aBlock.length > 1 ?
-        function (result) {return $core.seamless(function () {
-            if (Array.isArray(result)) {
-                return aBlock._valueWithPossibleArguments_([result].concat(result.slice(0, aBlock.length-1)));
-            } else {
-                return aBlock._value_(result);
-            }
-        })} :
-        function (result) {return $core.seamless(function () {
-            return aBlock._value_(result);
-        })}
-    );
-}, self);
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:",{aBlockOrArray:aBlockOrArray},$globals.Thenable)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlockOrArray"],
-source: "then: aBlockOrArray\x0a\x22Accepts a block or array of blocks.\x0aEach of blocks in the array or the singleton one is\x0aused in .then call to a promise, to accept a result\x0aand transform it to the result for the next one.\x0aIn case a block has more than one argument\x0aand result is an array, first n-1 elements of the array\x0aare put into additional arguments beyond the first.\x0aThe first argument always contains the result as-is.\x22\x0a<inlineJS: '\x0avar array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];\x0areturn array.reduce(function (soFar, aBlock) {\x0a    return soFar.then(typeof aBlock === \x22function\x22 && aBlock.length > 1 ?\x0a        function (result) {return $core.seamless(function () {\x0a            if (Array.isArray(result)) {\x0a                return aBlock._valueWithPossibleArguments_([result].concat(result.slice(0, aBlock.length-1)));\x0a            } else {\x0a                return aBlock._value_(result);\x0a            }\x0a        })} :\x0a        function (result) {return $core.seamless(function () {\x0a            return aBlock._value_(result);\x0a        })}\x0a    );\x0a}, self)'>",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.Thenable);
-
-$core.addMethod(
-$core.method({
-selector: "then:catch:",
-protocol: "promises",
-fn: function (aBlockOrArray,anotherBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($self._then_(aBlockOrArray))._catch_(anotherBlock);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:catch:",{aBlockOrArray:aBlockOrArray,anotherBlock:anotherBlock},$globals.Thenable)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlockOrArray", "anotherBlock"],
-source: "then: aBlockOrArray catch: anotherBlock\x0a\x09^ (self then: aBlockOrArray) catch: anotherBlock",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["catch:", "then:"]
-}),
-$globals.Thenable);
-
-$core.addMethod(
-$core.method({
-selector: "then:on:do:",
-protocol: "promises",
-fn: function (aBlockOrArray,aClass,aBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($self._then_(aBlockOrArray))._on_do_(aClass,aBlock);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:on:do:",{aBlockOrArray:aBlockOrArray,aClass:aClass,aBlock:aBlock},$globals.Thenable)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlockOrArray", "aClass", "aBlock"],
-source: "then: aBlockOrArray on: aClass do: aBlock\x0a\x09^ (self then: aBlockOrArray) on: aClass do: aBlock",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["on:do:", "then:"]
-}),
-$globals.Thenable);
-
-$core.addMethod(
-$core.method({
-selector: "then:on:do:catch:",
-protocol: "promises",
-fn: function (aBlockOrArray,aClass,aBlock,anotherBlock){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($recv($self._then_(aBlockOrArray))._on_do_(aClass,aBlock))._catch_(anotherBlock);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:on:do:catch:",{aBlockOrArray:aBlockOrArray,aClass:aClass,aBlock:aBlock,anotherBlock:anotherBlock},$globals.Thenable)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aBlockOrArray", "aClass", "aBlock", "anotherBlock"],
-source: "then: aBlockOrArray on: aClass do: aBlock catch: anotherBlock\x0a\x09^ ((self then: aBlockOrArray) on: aClass do: aBlock) catch: anotherBlock",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["catch:", "on:do:", "then:"]
-}),
-$globals.Thenable);
-
-
-
-$core.addClass("Promise", $globals.Thenable, [], "Kernel-Promises");
+$core.addClass("Promise", $globals.Object, [], "Kernel-Promises");
 
 $core.addMethod(
 $core.method({
@@ -372,228 +178,192 @@ messageSends: []
 }),
 $globals.Promise.a$cls);
 
+
+$core.addTrait("TThenable", "Kernel-Promises");
 $core.addMethod(
 $core.method({
 selector: "catch:",
-protocol: "*Kernel-Promises",
+protocol: "promises",
 fn: function (aBlock){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._catch_.call(js, aBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("catch:")
-            ._arguments_([aBlock])
-    );
+return self.then(null, function (err) {return $core.seamless(function () {
+    return aBlock._value_(err);
+})});
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"catch:",{aBlock:aBlock},$globals.JSObjectProxy)});
+}, function($ctx1) {$ctx1.fill(self,"catch:",{aBlock:aBlock},$globals.TThenable)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlock"],
-source: "catch: aBlock\x0a<inlineJS: 'var js = $self[\x22@jsObject\x22];\x0aif (typeof js.then === \x22function\x22)\x0a    return $globals.Thenable.fn.prototype._catch_.call(js, aBlock);\x0aelse\x0a    return self._doesNotUnderstand_(\x0a        $globals.Message._new()\x0a            ._selector_(\x22catch:\x22)\x0a            ._arguments_([aBlock])\x0a    )'>",
+source: "catch: aBlock\x0a<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {\x0a    return aBlock._value_(err);\x0a})})'>",
 referencedClasses: [],
 //>>excludeEnd("ide");
 messageSends: []
 }),
-$globals.JSObjectProxy);
+$globals.TThenable);
 
 $core.addMethod(
 $core.method({
 selector: "on:do:",
-protocol: "*Kernel-Promises",
+protocol: "promises",
 fn: function (aClass,aBlock){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._on_do_.call(js, aClass, aBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("on:do:")
-            ._arguments_([aClass, aBlock])
-    );
+return self.then(null, function (err) {return $core.seamless(function () {
+    if (err._isKindOf_(aClass)) return aBlock._value_(err);
+    else throw err;
+})});
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"on:do:",{aClass:aClass,aBlock:aBlock},$globals.JSObjectProxy)});
+}, function($ctx1) {$ctx1.fill(self,"on:do:",{aClass:aClass,aBlock:aBlock},$globals.TThenable)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aClass", "aBlock"],
-source: "on: aClass do: aBlock\x0a<inlineJS: 'var js = $self[\x22@jsObject\x22];\x0aif (typeof js.then === \x22function\x22)\x0a    return $globals.Thenable.fn.prototype._on_do_.call(js, aClass, aBlock);\x0aelse\x0a    return self._doesNotUnderstand_(\x0a        $globals.Message._new()\x0a            ._selector_(\x22on:do:\x22)\x0a            ._arguments_([aClass, aBlock])\x0a    )'>",
+source: "on: aClass do: aBlock\x0a<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {\x0a    if (err._isKindOf_(aClass)) return aBlock._value_(err);\x0a    else throw err;\x0a})})'>",
 referencedClasses: [],
 //>>excludeEnd("ide");
 messageSends: []
 }),
-$globals.JSObjectProxy);
+$globals.TThenable);
 
 $core.addMethod(
 $core.method({
 selector: "on:do:catch:",
-protocol: "*Kernel-Promises",
+protocol: "promises",
 fn: function (aClass,aBlock,anotherBlock){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._on_do_catch_.call(js, aClass, aBlock, anotherBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("on:do:catch:")
-            ._arguments_([aClass, aBlock, anotherBlock])
-    );
-return self;
+return $recv($self._on_do_(aClass,aBlock))._catch_(anotherBlock);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"on:do:catch:",{aClass:aClass,aBlock:aBlock,anotherBlock:anotherBlock},$globals.JSObjectProxy)});
+}, function($ctx1) {$ctx1.fill(self,"on:do:catch:",{aClass:aClass,aBlock:aBlock,anotherBlock:anotherBlock},$globals.TThenable)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aClass", "aBlock", "anotherBlock"],
-source: "on: aClass do: aBlock catch: anotherBlock\x0a<inlineJS: 'var js = $self[\x22@jsObject\x22];\x0aif (typeof js.then === \x22function\x22)\x0a    return $globals.Thenable.fn.prototype._on_do_catch_.call(js, aClass, aBlock, anotherBlock);\x0aelse\x0a    return self._doesNotUnderstand_(\x0a        $globals.Message._new()\x0a            ._selector_(\x22on:do:catch:\x22)\x0a            ._arguments_([aClass, aBlock, anotherBlock])\x0a    )'>",
+source: "on: aClass do: aBlock catch: anotherBlock\x0a\x09^ (self on: aClass do: aBlock) catch: anotherBlock",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: []
+messageSends: ["catch:", "on:do:"]
 }),
-$globals.JSObjectProxy);
+$globals.TThenable);
 
 $core.addMethod(
 $core.method({
 selector: "then:",
-protocol: "*Kernel-Promises",
+protocol: "promises",
 fn: function (aBlockOrArray){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_.call(js, aBlockOrArray);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:")
-            ._arguments_([aBlockOrArray])
+
+var array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];
+return array.reduce(function (soFar, aBlock) {
+    return soFar.then(typeof aBlock === "function" && aBlock.length > 1 ?
+        function (result) {return $core.seamless(function () {
+            if (Array.isArray(result)) {
+                return aBlock._valueWithPossibleArguments_([result].concat(result.slice(0, aBlock.length-1)));
+            } else {
+                return aBlock._value_(result);
+            }
+        })} :
+        function (result) {return $core.seamless(function () {
+            return aBlock._value_(result);
+        })}
     );
+}, self);
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:",{aBlockOrArray:aBlockOrArray},$globals.JSObjectProxy)});
+}, function($ctx1) {$ctx1.fill(self,"then:",{aBlockOrArray:aBlockOrArray},$globals.TThenable)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlockOrArray"],
-source: "then: aBlockOrArray\x0a<inlineJS: 'var js = $self[\x22@jsObject\x22];\x0aif (typeof js.then === \x22function\x22)\x0a    return $globals.Thenable.fn.prototype._then_.call(js, aBlockOrArray);\x0aelse\x0a    return self._doesNotUnderstand_(\x0a        $globals.Message._new()\x0a            ._selector_(\x22then:\x22)\x0a            ._arguments_([aBlockOrArray])\x0a    )'>",
+source: "then: aBlockOrArray\x0a\x22Accepts a block or array of blocks.\x0aEach of blocks in the array or the singleton one is\x0aused in .then call to a promise, to accept a result\x0aand transform it to the result for the next one.\x0aIn case a block has more than one argument\x0aand result is an array, first n-1 elements of the array\x0aare put into additional arguments beyond the first.\x0aThe first argument always contains the result as-is.\x22\x0a<inlineJS: '\x0avar array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];\x0areturn array.reduce(function (soFar, aBlock) {\x0a    return soFar.then(typeof aBlock === \x22function\x22 && aBlock.length > 1 ?\x0a        function (result) {return $core.seamless(function () {\x0a            if (Array.isArray(result)) {\x0a                return aBlock._valueWithPossibleArguments_([result].concat(result.slice(0, aBlock.length-1)));\x0a            } else {\x0a                return aBlock._value_(result);\x0a            }\x0a        })} :\x0a        function (result) {return $core.seamless(function () {\x0a            return aBlock._value_(result);\x0a        })}\x0a    );\x0a}, self)'>",
 referencedClasses: [],
 //>>excludeEnd("ide");
 messageSends: []
 }),
-$globals.JSObjectProxy);
+$globals.TThenable);
 
 $core.addMethod(
 $core.method({
 selector: "then:catch:",
-protocol: "*Kernel-Promises",
+protocol: "promises",
 fn: function (aBlockOrArray,anotherBlock){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_catch_.call(js, aBlockOrArray, anotherBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:catch:")
-            ._arguments_([aBlockOrArray, anotherBlock])
-    );
-return self;
+return $recv($self._then_(aBlockOrArray))._catch_(anotherBlock);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:catch:",{aBlockOrArray:aBlockOrArray,anotherBlock:anotherBlock},$globals.JSObjectProxy)});
+}, function($ctx1) {$ctx1.fill(self,"then:catch:",{aBlockOrArray:aBlockOrArray,anotherBlock:anotherBlock},$globals.TThenable)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlockOrArray", "anotherBlock"],
-source: "then: aBlockOrArray catch: anotherBlock\x0a<inlineJS: 'var js = $self[\x22@jsObject\x22];\x0aif (typeof js.then === \x22function\x22)\x0a    return $globals.Thenable.fn.prototype._then_catch_.call(js, aBlockOrArray, anotherBlock);\x0aelse\x0a    return self._doesNotUnderstand_(\x0a        $globals.Message._new()\x0a            ._selector_(\x22then:catch:\x22)\x0a            ._arguments_([aBlockOrArray, anotherBlock])\x0a    )'>",
+source: "then: aBlockOrArray catch: anotherBlock\x0a\x09^ (self then: aBlockOrArray) catch: anotherBlock",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: []
+messageSends: ["catch:", "then:"]
 }),
-$globals.JSObjectProxy);
+$globals.TThenable);
 
 $core.addMethod(
 $core.method({
 selector: "then:on:do:",
-protocol: "*Kernel-Promises",
+protocol: "promises",
 fn: function (aBlockOrArray,aClass,aBlock){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_on_do_.call(js, aBlockOrArray, aClass, aBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:on:do:")
-            ._arguments_([aBlockOrArray, aClass, aBlock])
-    );
-return self;
+return $recv($self._then_(aBlockOrArray))._on_do_(aClass,aBlock);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:on:do:",{aBlockOrArray:aBlockOrArray,aClass:aClass,aBlock:aBlock},$globals.JSObjectProxy)});
+}, function($ctx1) {$ctx1.fill(self,"then:on:do:",{aBlockOrArray:aBlockOrArray,aClass:aClass,aBlock:aBlock},$globals.TThenable)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlockOrArray", "aClass", "aBlock"],
-source: "then: aBlockOrArray on: aClass do: aBlock\x0a<inlineJS: 'var js = $self[\x22@jsObject\x22];\x0aif (typeof js.then === \x22function\x22)\x0a    return $globals.Thenable.fn.prototype._then_on_do_.call(js, aBlockOrArray, aClass, aBlock);\x0aelse\x0a    return self._doesNotUnderstand_(\x0a        $globals.Message._new()\x0a            ._selector_(\x22then:on:do:\x22)\x0a            ._arguments_([aBlockOrArray, aClass, aBlock])\x0a    )'>",
+source: "then: aBlockOrArray on: aClass do: aBlock\x0a\x09^ (self then: aBlockOrArray) on: aClass do: aBlock",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: []
+messageSends: ["on:do:", "then:"]
 }),
-$globals.JSObjectProxy);
+$globals.TThenable);
 
 $core.addMethod(
 $core.method({
 selector: "then:on:do:catch:",
-protocol: "*Kernel-Promises",
+protocol: "promises",
 fn: function (aBlockOrArray,aClass,aBlock,anotherBlock){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_on_do_catch_.call(js, aBlockOrArray, aClass, aBlock, anotherBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:on:do:catch:")
-            ._arguments_([aBlockOrArray, aClass, aBlock, anotherBlock])
-    );
-return self;
+return $recv($recv($self._then_(aBlockOrArray))._on_do_(aClass,aBlock))._catch_(anotherBlock);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"then:on:do:catch:",{aBlockOrArray:aBlockOrArray,aClass:aClass,aBlock:aBlock,anotherBlock:anotherBlock},$globals.JSObjectProxy)});
+}, function($ctx1) {$ctx1.fill(self,"then:on:do:catch:",{aBlockOrArray:aBlockOrArray,aClass:aClass,aBlock:aBlock,anotherBlock:anotherBlock},$globals.TThenable)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlockOrArray", "aClass", "aBlock", "anotherBlock"],
-source: "then: aBlockOrArray on: aClass do: aBlock catch: anotherBlock\x0a<inlineJS: 'var js = $self[\x22@jsObject\x22];\x0aif (typeof js.then === \x22function\x22)\x0a    return $globals.Thenable.fn.prototype._then_on_do_catch_.call(js, aBlockOrArray, aClass, aBlock, anotherBlock);\x0aelse\x0a    return self._doesNotUnderstand_(\x0a        $globals.Message._new()\x0a            ._selector_(\x22then:on:do:catch:\x22)\x0a            ._arguments_([aBlockOrArray, aClass, aBlock, anotherBlock])\x0a    )'>",
+source: "then: aBlockOrArray on: aClass do: aBlock catch: anotherBlock\x0a\x09^ ((self then: aBlockOrArray) on: aClass do: aBlock) catch: anotherBlock",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: []
+messageSends: ["catch:", "on:do:", "then:"]
 }),
-$globals.JSObjectProxy);
+$globals.TThenable);
+
+$core.setTraitComposition([{trait: $globals.TThenable}], $globals.Promise);
 
 });

+ 43 - 136
src/Kernel-Promises.st

@@ -1,76 +1,5 @@
 Smalltalk createPackage: 'Kernel-Promises'!
-Object subclass: #Thenable
-	instanceVariableNames: ''
-	package: 'Kernel-Promises'!
-!Thenable commentStamp!
-I am the abstract base class for Promises.
-
-My subclasses should wrap existing JS implementations.
-
-I contain methods that wrap Promises/A+ `.then` behaviour.!
-
-!Thenable methodsFor: 'promises'!
-
-catch: aBlock
-<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {
-    return aBlock._value_(err);
-})})'>
-!
-
-on: aClass do: aBlock
-<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {
-    if (err._isKindOf_(aClass)) return aBlock._value_(err);
-    else throw err;
-})})'>
-!
-
-on: aClass do: aBlock catch: anotherBlock
-<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {
-    try { if (err._isKindOf_(aClass)) return aBlock._value_(err); } catch (e) { err = e; }
-    return anotherBlock._value_(err);
-})})'>
-!
-
-then: aBlockOrArray
-"Accepts a block or array of blocks.
-Each of blocks in the array or the singleton one is
-used in .then call to a promise, to accept a result
-and transform it to the result for the next one.
-In case a block has more than one argument
-and result is an array, first n-1 elements of the array
-are put into additional arguments beyond the first.
-The first argument always contains the result as-is."
-<inlineJS: '
-var array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];
-return array.reduce(function (soFar, aBlock) {
-    return soFar.then(typeof aBlock === "function" && aBlock.length > 1 ?
-        function (result) {return $core.seamless(function () {
-            if (Array.isArray(result)) {
-                return aBlock._valueWithPossibleArguments_([result].concat(result.slice(0, aBlock.length-1)));
-            } else {
-                return aBlock._value_(result);
-            }
-        })} :
-        function (result) {return $core.seamless(function () {
-            return aBlock._value_(result);
-        })}
-    );
-}, self)'>
-!
-
-then: aBlockOrArray catch: anotherBlock
-	^ (self then: aBlockOrArray) catch: anotherBlock
-!
-
-then: aBlockOrArray on: aClass do: aBlock
-	^ (self then: aBlockOrArray) on: aClass do: aBlock
-!
-
-then: aBlockOrArray on: aClass do: aBlock catch: anotherBlock
-	^ ((self then: aBlockOrArray) on: aClass do: aBlock) catch: anotherBlock
-! !
-
-Thenable subclass: #Promise
+Object subclass: #Promise
 	instanceVariableNames: ''
 	package: 'Kernel-Promises'!
 
@@ -122,89 +51,67 @@ value: anObject
 <inlineJS: 'return $recv(anObject)._in_(function (x) {return Promise.resolve(x)})'>
 ! !
 
-!JSObjectProxy methodsFor: '*Kernel-Promises'!
+Trait named: #TThenable
+	package: 'Kernel-Promises'!
+
+!TThenable methodsFor: 'promises'!
 
 catch: aBlock
-<inlineJS: 'var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._catch_.call(js, aBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("catch:")
-            ._arguments_([aBlock])
-    )'>
+<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {
+    return aBlock._value_(err);
+})})'>
 !
 
 on: aClass do: aBlock
-<inlineJS: 'var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._on_do_.call(js, aClass, aBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("on:do:")
-            ._arguments_([aClass, aBlock])
-    )'>
+<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {
+    if (err._isKindOf_(aClass)) return aBlock._value_(err);
+    else throw err;
+})})'>
 !
 
 on: aClass do: aBlock catch: anotherBlock
-<inlineJS: 'var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._on_do_catch_.call(js, aClass, aBlock, anotherBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("on:do:catch:")
-            ._arguments_([aClass, aBlock, anotherBlock])
-    )'>
+	^ (self on: aClass do: aBlock) catch: anotherBlock
 !
 
 then: aBlockOrArray
-<inlineJS: 'var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_.call(js, aBlockOrArray);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:")
-            ._arguments_([aBlockOrArray])
-    )'>
+"Accepts a block or array of blocks.
+Each of blocks in the array or the singleton one is
+used in .then call to a promise, to accept a result
+and transform it to the result for the next one.
+In case a block has more than one argument
+and result is an array, first n-1 elements of the array
+are put into additional arguments beyond the first.
+The first argument always contains the result as-is."
+<inlineJS: '
+var array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];
+return array.reduce(function (soFar, aBlock) {
+    return soFar.then(typeof aBlock === "function" && aBlock.length > 1 ?
+        function (result) {return $core.seamless(function () {
+            if (Array.isArray(result)) {
+                return aBlock._valueWithPossibleArguments_([result].concat(result.slice(0, aBlock.length-1)));
+            } else {
+                return aBlock._value_(result);
+            }
+        })} :
+        function (result) {return $core.seamless(function () {
+            return aBlock._value_(result);
+        })}
+    );
+}, self)'>
 !
 
 then: aBlockOrArray catch: anotherBlock
-<inlineJS: 'var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_catch_.call(js, aBlockOrArray, anotherBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:catch:")
-            ._arguments_([aBlockOrArray, anotherBlock])
-    )'>
+	^ (self then: aBlockOrArray) catch: anotherBlock
 !
 
 then: aBlockOrArray on: aClass do: aBlock
-<inlineJS: 'var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_on_do_.call(js, aBlockOrArray, aClass, aBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:on:do:")
-            ._arguments_([aBlockOrArray, aClass, aBlock])
-    )'>
+	^ (self then: aBlockOrArray) on: aClass do: aBlock
 !
 
 then: aBlockOrArray on: aClass do: aBlock catch: anotherBlock
-<inlineJS: 'var js = $self["@jsObject"];
-if (typeof js.then === "function")
-    return $globals.Thenable.fn.prototype._then_on_do_catch_.call(js, aBlockOrArray, aClass, aBlock, anotherBlock);
-else
-    return self._doesNotUnderstand_(
-        $globals.Message._new()
-            ._selector_("then:on:do:catch:")
-            ._arguments_([aBlockOrArray, aClass, aBlock, anotherBlock])
-    )'>
+	^ ((self then: aBlockOrArray) on: aClass do: aBlock) catch: anotherBlock
+! !
+
+Promise setTraitComposition: {TThenable} asTraitComposition!
 ! !
 

+ 98 - 122
src/Platform-ImportExport.js

@@ -4269,128 +4269,6 @@ messageSends: []
 }),
 $globals.AmdPackageTransport.a$cls);
 
-$core.addMethod(
-$core.method({
-selector: "commentStamp",
-protocol: "*Platform-ImportExport",
-fn: function (){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1;
-$1=$recv($globals.ClassCommentReader)._new();
-$recv($1)._class_(self);
-return $recv($1)._yourself();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"commentStamp",{},$globals.BehaviorBody)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "commentStamp\x0a\x09^ ClassCommentReader new\x0a\x09class: self;\x0a\x09yourself",
-referencedClasses: ["ClassCommentReader"],
-//>>excludeEnd("ide");
-messageSends: ["class:", "new", "yourself"]
-}),
-$globals.BehaviorBody);
-
-$core.addMethod(
-$core.method({
-selector: "commentStamp:prior:",
-protocol: "*Platform-ImportExport",
-fn: function (aStamp,prior){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $self._commentStamp();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"commentStamp:prior:",{aStamp:aStamp,prior:prior},$globals.BehaviorBody)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aStamp", "prior"],
-source: "commentStamp: aStamp prior: prior\x0a\x09\x09^ self commentStamp",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["commentStamp"]
-}),
-$globals.BehaviorBody);
-
-$core.addMethod(
-$core.method({
-selector: "exportBehaviorDefinitionTo:using:",
-protocol: "*Platform-ImportExport",
-fn: function (aStream,anExporter){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-$self._subclassResponsibility();
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"exportBehaviorDefinitionTo:using:",{aStream:aStream,anExporter:anExporter},$globals.BehaviorBody)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aStream", "anExporter"],
-source: "exportBehaviorDefinitionTo: aStream using: anExporter\x0a\x09self subclassResponsibility",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["subclassResponsibility"]
-}),
-$globals.BehaviorBody);
-
-$core.addMethod(
-$core.method({
-selector: "methodsFor:",
-protocol: "*Platform-ImportExport",
-fn: function (aString){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-var $1;
-$1=$recv($globals.ClassProtocolReader)._new();
-$recv($1)._class_category_(self,aString);
-return $recv($1)._yourself();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"methodsFor:",{aString:aString},$globals.BehaviorBody)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aString"],
-source: "methodsFor: aString\x0a\x09^ ClassProtocolReader new\x0a\x09\x09class: self category: aString;\x0a\x09\x09yourself",
-referencedClasses: ["ClassProtocolReader"],
-//>>excludeEnd("ide");
-messageSends: ["class:category:", "new", "yourself"]
-}),
-$globals.BehaviorBody);
-
-$core.addMethod(
-$core.method({
-selector: "methodsFor:stamp:",
-protocol: "*Platform-ImportExport",
-fn: function (aString,aStamp){
-var self=this,$self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $self._methodsFor_(aString);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"methodsFor:stamp:",{aString:aString,aStamp:aStamp},$globals.BehaviorBody)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aString", "aStamp"],
-source: "methodsFor: aString stamp: aStamp\x0a\x09\x22Added for file-in compatibility, ignores stamp.\x22\x0a\x09^ self methodsFor: aString",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["methodsFor:"]
-}),
-$globals.BehaviorBody);
-
 $core.addMethod(
 $core.method({
 selector: "exportBehaviorDefinitionTo:using:",
@@ -4559,6 +4437,104 @@ messageSends: ["loadFromNamespace:", "named:"]
 }),
 $globals.Package.a$cls);
 
+$core.addMethod(
+$core.method({
+selector: "methodsFor:",
+protocol: "*Platform-ImportExport",
+fn: function (aString){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+$1=$recv($globals.ClassProtocolReader)._new();
+$recv($1)._class_category_(self,aString);
+return $recv($1)._yourself();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"methodsFor:",{aString:aString},$globals.TBehaviorProvider)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString"],
+source: "methodsFor: aString\x0a\x09^ ClassProtocolReader new\x0a\x09\x09class: self category: aString;\x0a\x09\x09yourself",
+referencedClasses: ["ClassProtocolReader"],
+//>>excludeEnd("ide");
+messageSends: ["class:category:", "new", "yourself"]
+}),
+$globals.TBehaviorProvider);
+
+$core.addMethod(
+$core.method({
+selector: "methodsFor:stamp:",
+protocol: "*Platform-ImportExport",
+fn: function (aString,aStamp){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._methodsFor_(aString);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"methodsFor:stamp:",{aString:aString,aStamp:aStamp},$globals.TBehaviorProvider)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aString", "aStamp"],
+source: "methodsFor: aString stamp: aStamp\x0a\x09\x22Added for file-in compatibility, ignores stamp.\x22\x0a\x09^ self methodsFor: aString",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["methodsFor:"]
+}),
+$globals.TBehaviorProvider);
+
+$core.addMethod(
+$core.method({
+selector: "commentStamp",
+protocol: "*Platform-ImportExport",
+fn: function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+$1=$recv($globals.ClassCommentReader)._new();
+$recv($1)._class_(self);
+return $recv($1)._yourself();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"commentStamp",{},$globals.TMasterBehavior)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "commentStamp\x0a\x09^ ClassCommentReader new\x0a\x09class: self;\x0a\x09yourself",
+referencedClasses: ["ClassCommentReader"],
+//>>excludeEnd("ide");
+messageSends: ["class:", "new", "yourself"]
+}),
+$globals.TMasterBehavior);
+
+$core.addMethod(
+$core.method({
+selector: "commentStamp:prior:",
+protocol: "*Platform-ImportExport",
+fn: function (aStamp,prior){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self._commentStamp();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"commentStamp:prior:",{aStamp:aStamp,prior:prior},$globals.TMasterBehavior)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aStamp", "prior"],
+source: "commentStamp: aStamp prior: prior\x0a\x09\x09^ self commentStamp",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["commentStamp"]
+}),
+$globals.TMasterBehavior);
+
 $core.addMethod(
 $core.method({
 selector: "exportBehaviorDefinitionTo:using:",

+ 25 - 27
src/Platform-ImportExport.st

@@ -1120,33 +1120,6 @@ namespace: aString
 		yourself
 ! !
 
-!BehaviorBody methodsFor: '*Platform-ImportExport'!
-
-commentStamp
-	^ ClassCommentReader new
-	class: self;
-	yourself
-!
-
-commentStamp: aStamp prior: prior
-		^ self commentStamp
-!
-
-exportBehaviorDefinitionTo: aStream using: anExporter
-	self subclassResponsibility
-!
-
-methodsFor: aString
-	^ ClassProtocolReader new
-		class: self category: aString;
-		yourself
-!
-
-methodsFor: aString stamp: aStamp
-	"Added for file-in compatibility, ignores stamp."
-	^ self methodsFor: aString
-! !
-
 !Class methodsFor: '*Platform-ImportExport'!
 
 exportBehaviorDefinitionTo: aStream using: anExporter
@@ -1185,6 +1158,31 @@ load: aPackageName fromNamespace: aString
 	(self named: aPackageName) loadFromNamespace: aString
 ! !
 
+!TBehaviorProvider methodsFor: '*Platform-ImportExport'!
+
+methodsFor: aString
+	^ ClassProtocolReader new
+		class: self category: aString;
+		yourself
+!
+
+methodsFor: aString stamp: aStamp
+	"Added for file-in compatibility, ignores stamp."
+	^ self methodsFor: aString
+! !
+
+!TMasterBehavior methodsFor: '*Platform-ImportExport'!
+
+commentStamp
+	^ ClassCommentReader new
+	class: self;
+	yourself
+!
+
+commentStamp: aStamp prior: prior
+		^ self commentStamp
+! !
+
 !Trait methodsFor: '*Platform-ImportExport'!
 
 exportBehaviorDefinitionTo: aStream using: anExporter

+ 18 - 18
src/SUnit.js

@@ -1767,24 +1767,6 @@ messageSends: ["suite:", "new"]
 }),
 $globals.TestSuiteRunner.a$cls);
 
-$core.addMethod(
-$core.method({
-selector: "isTestClass",
-protocol: "*SUnit",
-fn: function (){
-var self=this,$self=this;
-return false;
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isTestClass\x0a\x09^ false",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.BehaviorBody);
-
 $core.addMethod(
 $core.method({
 selector: "isTestPackage",
@@ -1816,4 +1798,22 @@ messageSends: ["anySatisfy:", "classes", "isTestClass"]
 }),
 $globals.Package);
 
+$core.addMethod(
+$core.method({
+selector: "isTestClass",
+protocol: "*SUnit",
+fn: function (){
+var self=this,$self=this;
+return false;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isTestClass\x0a\x09^ false",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.TBehaviorDefaults);
+
 });

+ 6 - 6
src/SUnit.st

@@ -446,15 +446,15 @@ on: aCollection
 	^ super new suite: aCollection
 ! !
 
-!BehaviorBody methodsFor: '*SUnit'!
-
-isTestClass
-	^ false
-! !
-
 !Package methodsFor: '*SUnit'!
 
 isTestPackage
 	^ self classes anySatisfy: [ :each | each isTestClass ]
 ! !
 
+!TBehaviorDefaults methodsFor: '*SUnit'!
+
+isTestClass
+	^ false
+! !
+

+ 1 - 0
support/deploy.js

@@ -5,6 +5,7 @@ define([
     './kernel-language', // pre-fetch, dep of ./boot
     './boot', // pre-fetch, dep of ./helpers
     // --- packages of the core Amber begin here ---
+    'amber_core/Kernel-Helpers',
     'amber_core/Kernel-Objects',
     'amber_core/Kernel-Classes',
     'amber_core/Kernel-Methods',

+ 0 - 7
support/kernel-fundamentals.js

@@ -200,13 +200,6 @@ define(['./compatibility'], function () {
         var addElement = brikz.arraySet.addElement;
         var removeElement = brikz.arraySet.removeElement;
 
-        function SmalltalkBehaviorBody () {
-        }
-
-        coreFns.BehaviorBody = inherits(SmalltalkBehaviorBody, SmalltalkObject);
-
-        this.BehaviorBody = SmalltalkBehaviorBody;
-
         /* Smalltalk classes */
 
         var classes = [];

+ 4 - 4
support/kernel-language.js

@@ -62,7 +62,7 @@ define(['./compatibility'], function () {
     TraitsBrik.deps = ["behaviors", "composition", "arraySet", "root"];
     function TraitsBrik (brikz, st) {
         var coreFns = brikz.root.coreFns;
-        var SmalltalkBehaviorBody = brikz.behaviors.BehaviorBody;
+        var SmalltalkObject = brikz.root.Object;
         var setupMethods = brikz.composition.setupMethods;
         var traitMethodChanged = brikz.composition.traitMethodChanged;
         var buildBehaviorBody = brikz.behaviors.buildBehaviorBody;
@@ -72,7 +72,7 @@ define(['./compatibility'], function () {
         function SmalltalkTrait () {
         }
 
-        coreFns.Trait = inherits(SmalltalkTrait, SmalltalkBehaviorBody);
+        coreFns.Trait = inherits(SmalltalkTrait, SmalltalkObject);
 
         SmalltalkTrait.prototype.trait = true;
 
@@ -133,7 +133,7 @@ define(['./compatibility'], function () {
         var SmalltalkRoot = brikz.root.Root;
         var coreFns = brikz.root.coreFns;
         var globals = brikz.smalltalkGlobals.globals;
-        var SmalltalkBehaviorBody = brikz.behaviors.BehaviorBody;
+        var SmalltalkObject = brikz.root.Object;
         var buildBehaviorBody = brikz.behaviors.buildBehaviorBody;
         var setupMethods = brikz.composition.setupMethods;
         var removeBehaviorBody = brikz.behaviors.removeBehaviorBody;
@@ -149,7 +149,7 @@ define(['./compatibility'], function () {
         function SmalltalkMetaclass () {
         }
 
-        coreFns.Behavior = inherits(SmalltalkBehavior, SmalltalkBehaviorBody);
+        coreFns.Behavior = inherits(SmalltalkBehavior, SmalltalkObject);
         coreFns.Class = inherits(SmalltalkClass, SmalltalkBehavior);
         coreFns.Metaclass = inherits(SmalltalkMetaclass, SmalltalkBehavior);
 

Some files were not shown because too many files changed in this diff