1
0
Kaynağa Gözat

Niladic #jsOverride: pragma - super sends.

Not in interpreter, yet.
Herby Vojčík 4 yıl önce
ebeveyn
işleme
a1e3134d30

+ 4 - 4
lang/src/Compiler-Core.js

@@ -417,11 +417,11 @@ selector: "transformersDictionary",
 protocol: "compiling",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "transformersDictionary\x0a\x09^ transformersDictionary ifNil: [ transformersDictionary := super transformersDictionary\x0a\x09\x09at: '5000-astToIr' put: self translator;\x0a\x09\x09at: '8000-irToJs' put: self irTranslator;\x0a\x09\x09at: '9000-latePragmas' put: self lateIRPragmator;\x0a\x09\x09yourself ]",
+source: "transformersDictionary\x0a\x09^ transformersDictionary ifNil: [ transformersDictionary := super transformersDictionary\x0a\x09\x09at: '5000-astToIr' put: self translator;\x0a\x09\x09at: '7000-irLatePragmas' put: self lateIRPragmator;\x0a\x09\x09at: '8000-irToJs' put: self irTranslator;\x0a\x09\x09yourself ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["ifNil:", "at:put:", "transformersDictionary", "translator", "irTranslator", "lateIRPragmator", "yourself"]
+messageSends: ["ifNil:", "at:put:", "transformersDictionary", "translator", "lateIRPragmator", "irTranslator", "yourself"]
 }, function ($methodClass){ return function (){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -444,12 +444,12 @@ $ctx1.supercall = true,
 ,$ctx1.sendIdx["at:put:"]=1
 //>>excludeEnd("ctx");
 ][0];
-[$recv($2)._at_put_("8000-irToJs",$self._irTranslator())
+[$recv($2)._at_put_("7000-irLatePragmas",$self._lateIRPragmator())
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["at:put:"]=2
 //>>excludeEnd("ctx");
 ][0];
-$recv($2)._at_put_("9000-latePragmas",$self._lateIRPragmator());
+$recv($2)._at_put_("8000-irToJs",$self._irTranslator());
 $self.transformersDictionary=$recv($2)._yourself();
 return $self.transformersDictionary;
 } else {

+ 1 - 1
lang/src/Compiler-Core.st

@@ -107,8 +107,8 @@ lateIRPragmator
 transformersDictionary
 	^ transformersDictionary ifNil: [ transformersDictionary := super transformersDictionary
 		at: '5000-astToIr' put: self translator;
+		at: '7000-irLatePragmas' put: self lateIRPragmator;
 		at: '8000-irToJs' put: self irTranslator;
-		at: '9000-latePragmas' put: self lateIRPragmator;
 		yourself ]
 !
 

+ 174 - 3
lang/src/Compiler-IR.js

@@ -3347,16 +3347,25 @@ selector: "jsOverride:",
 protocol: "pragmas",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aString"],
-source: "jsOverride: aString\x0a\x09self irMethod attachments\x0a\x09\x09at: aString\x0a\x09\x09put: (NativeFunction\x0a\x09\x09\x09constructorNamed: #Function\x0a\x09\x09\x09value: 'return this.', irMethod selector asJavaScriptMethodName, '()')",
-referencedClasses: ["NativeFunction"],
+source: "jsOverride: aString\x0a\x09(IRJSSuperSendVisitor new property: aString; yourself)\x0a\x09\x09visit: self irMethod.\x0a\x09self irMethod attachments\x0a\x09\x09at: aString\x0a\x09\x09put: (NativeFunction\x0a\x09\x09\x09constructorNamed: #Function\x0a\x09\x09\x09value: 'return this.', irMethod selector asJavaScriptMethodName, '()')",
+referencedClasses: ["IRJSSuperSendVisitor", "NativeFunction"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["at:put:", "attachments", "irMethod", "constructorNamed:value:", ",", "asJavaScriptMethodName", "selector"]
+messageSends: ["visit:", "property:", "new", "yourself", "irMethod", "at:put:", "attachments", "constructorNamed:value:", ",", "asJavaScriptMethodName", "selector"]
 }, function ($methodClass){ return function (aString){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
+var $1,$2;
+$1=$recv($globals.IRJSSuperSendVisitor)._new();
+$recv($1)._property_(aString);
+$2=$recv($1)._yourself();
+$recv($2)._visit_([$self._irMethod()
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+,$ctx1.sendIdx["irMethod"]=1
+//>>excludeEnd("ctx");
+][0]);
 $recv($recv($self._irMethod())._attachments())._at_put_(aString,$recv($globals.NativeFunction)._constructorNamed_value_("Function",[$recv("return this.".__comma($recv($recv($self.irMethod)._selector())._asJavaScriptMethodName())).__comma("()")
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx[","]=1
@@ -3765,6 +3774,168 @@ $globals.IRVisitor);
 
 
 
+$core.addClass("IRJSSuperSendVisitor", $globals.IRVisitor, ["selector", "property"], "Compiler-IR");
+$core.addMethod(
+$core.method({
+selector: "property",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "property\x0a\x09^ property",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return $self.property;
+
+}; }),
+$globals.IRJSSuperSendVisitor);
+
+$core.addMethod(
+$core.method({
+selector: "property:",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "property: anObject\x0a\x09property := anObject",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (anObject){
+var self=this,$self=this;
+$self.property=anObject;
+return self;
+
+}; }),
+$globals.IRJSSuperSendVisitor);
+
+$core.addMethod(
+$core.method({
+selector: "selector",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "selector\x0a\x09^ selector",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return $self.selector;
+
+}; }),
+$globals.IRJSSuperSendVisitor);
+
+$core.addMethod(
+$core.method({
+selector: "selector:",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "selector: anObject\x0a\x09selector := anObject",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (anObject){
+var self=this,$self=this;
+$self.selector=anObject;
+return self;
+
+}; }),
+$globals.IRJSSuperSendVisitor);
+
+$core.addMethod(
+$core.method({
+selector: "visitIRMethod:",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIRMethod"],
+source: "visitIRMethod: anIRMethod\x0a\x09self selector: anIRMethod selector.\x0a\x09^ super visitIRMethod: anIRMethod",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["selector:", "selector", "visitIRMethod:"]
+}, function ($methodClass){ return function (anIRMethod){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._selector_($recv(anIRMethod)._selector());
+return [(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($methodClass.superclass||$boot.nilAsClass).fn.prototype._visitIRMethod_.call($self,anIRMethod))
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+,$ctx1.supercall = false
+//>>excludeEnd("ctx");
+][0];
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"visitIRMethod:",{anIRMethod:anIRMethod})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.IRJSSuperSendVisitor);
+
+$core.addMethod(
+$core.method({
+selector: "visitIRSend:",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIRSend"],
+source: "visitIRSend: anIRSend\x0a\x09| receiver |\x0a\x09receiver := anIRSend receiver.\x0a\x09receiver isSuper ifTrue: [\x0a\x09\x09anIRSend selector = self selector ifTrue: [\x0a\x09\x09\x09| old |\x0a\x09\x09\x09old := receiver variable.\x0a\x09\x09\x09receiver variable: (\x0a\x09\x09\x09\x09JavaScriptSuperVar new\x0a\x09\x09\x09\x09\x09scope: old scope;\x0a\x09\x09\x09\x09\x09name: old name;\x0a\x09\x09\x09\x09\x09yourself ).\x0a\x09\x09\x09anIRSend javaScriptSelector: self property ] ].\x0a\x09^ super visitIRSend: anIRSend",
+referencedClasses: ["JavaScriptSuperVar"],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["receiver", "ifTrue:", "isSuper", "=", "selector", "variable", "variable:", "scope:", "new", "scope", "name:", "name", "yourself", "javaScriptSelector:", "property", "visitIRSend:"]
+}, function ($methodClass){ return function (anIRSend){
+var self=this,$self=this;
+var receiver;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$3,$4,$5;
+receiver=$recv(anIRSend)._receiver();
+$1=$recv(receiver)._isSuper();
+if($core.assert($1)){
+$2=$recv([$recv(anIRSend)._selector()
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+,$ctx1.sendIdx["selector"]=1
+//>>excludeEnd("ctx");
+][0]).__eq($self._selector());
+if($core.assert($2)){
+var old;
+old=$recv(receiver)._variable();
+$3=receiver;
+$4=$recv($globals.JavaScriptSuperVar)._new();
+$recv($4)._scope_($recv(old)._scope());
+$recv($4)._name_($recv(old)._name());
+$5=$recv($4)._yourself();
+$recv($3)._variable_($5);
+$recv(anIRSend)._javaScriptSelector_($self._property());
+}
+}
+return [(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true,
+//>>excludeEnd("ctx");
+($methodClass.superclass||$boot.nilAsClass).fn.prototype._visitIRSend_.call($self,anIRSend))
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+,$ctx1.supercall = false
+//>>excludeEnd("ctx");
+][0];
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"visitIRSend:",{anIRSend:anIRSend,receiver:receiver})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.IRJSSuperSendVisitor);
+
+
+
 $core.addClass("IRJSTranslator", $globals.IRVisitor, ["stream", "currentClass"], "Compiler-IR");
 $core.addMethod(
 $core.method({

+ 45 - 0
lang/src/Compiler-IR.st

@@ -871,6 +871,8 @@ IRPragmator subclass: #IRLatePragmator
 !IRLatePragmator methodsFor: 'pragmas'!
 
 jsOverride: aString
+	(IRJSSuperSendVisitor new property: aString; yourself)
+		visit: self irMethod.
 	self irMethod attachments
 		at: aString
 		put: (NativeFunction
@@ -952,6 +954,49 @@ visitIRVerbatim: anIRVerbatim
 	^ self visitDagNode: anIRVerbatim
 ! !
 
+IRVisitor subclass: #IRJSSuperSendVisitor
+	slots: {#selector. #property}
+	package: 'Compiler-IR'!
+
+!IRJSSuperSendVisitor methodsFor: 'accessing'!
+
+property
+	^ property
+!
+
+property: anObject
+	property := anObject
+!
+
+selector
+	^ selector
+!
+
+selector: anObject
+	selector := anObject
+!
+
+visitIRMethod: anIRMethod
+	self selector: anIRMethod selector.
+	^ super visitIRMethod: anIRMethod
+!
+
+visitIRSend: anIRSend
+	| receiver |
+	receiver := anIRSend receiver.
+	receiver isSuper ifTrue: [
+		anIRSend selector = self selector ifTrue: [
+			| old |
+			old := receiver variable.
+			receiver variable: (
+				JavaScriptSuperVar new
+					scope: old scope;
+					name: old name;
+					yourself ).
+			anIRSend javaScriptSelector: self property ] ].
+	^ super visitIRSend: anIRSend
+! !
+
 IRVisitor subclass: #IRJSTranslator
 	slots: {#stream. #currentClass}
 	package: 'Compiler-IR'!

+ 21 - 0
lang/src/Compiler-Semantic.js

@@ -1591,6 +1591,27 @@ $globals.SuperVar);
 
 
 
+$core.addClass("JavaScriptSuperVar", $globals.SuperVar, [], "Compiler-Semantic");
+$core.addMethod(
+$core.method({
+selector: "lookupAsJavaScriptSource",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "lookupAsJavaScriptSource\x0a\x09^ 'Object.getPrototypeOf($methodClass.fn.prototype)'",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return "Object.getPrototypeOf($methodClass.fn.prototype)";
+
+}; }),
+$globals.JavaScriptSuperVar);
+
+
+
 $core.addClass("ThisContextVar", $globals.PseudoVar, [], "Compiler-Semantic");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.ThisContextVar.comment="I am a 'thisContext' pseudo variable.";

+ 10 - 0
lang/src/Compiler-Semantic.st

@@ -381,6 +381,16 @@ isSuper
 	^ true
 ! !
 
+SuperVar subclass: #JavaScriptSuperVar
+	slots: {}
+	package: 'Compiler-Semantic'!
+
+!JavaScriptSuperVar methodsFor: 'accessing'!
+
+lookupAsJavaScriptSource
+	^ 'Object.getPrototypeOf($methodClass.fn.prototype)'
+! !
+
 PseudoVar subclass: #ThisContextVar
 	slots: {}
 	package: 'Compiler-Semantic'!

+ 198 - 1
lang/src/Compiler-Tests.js

@@ -1,4 +1,4 @@
-define(["amber/boot", "require", "amber/core/SUnit"], function($boot,requirejs){"use strict";
+define(["amber/boot", "require", "amber/core/Kernel-Tests", "amber/core/SUnit"], function($boot,requirejs){"use strict";
 var $core=$boot.api,nil=$boot.nilAsValue,$nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals;
 var $pkg = $core.addPackage("Compiler-Tests");
 $pkg.innerEval = function (expr) { return eval(expr); };
@@ -1836,6 +1836,200 @@ $core.addClass("CodeGeneratorTest", $globals.AbstractCompilerTest, [], "Compiler
 $core.addClass("InliningCodeGeneratorTest", $globals.AbstractCompilerTest, [], "Compiler-Tests");
 
 
+$core.addClass("AbstractJavaScriptGatewayTest", $globals.ASTMethodRunningTest, ["theClass"], "Compiler-Tests");
+$core.addMethod(
+$core.method({
+selector: "jsConstructor",
+protocol: "running",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "jsConstructor\x0a\x09<inlineJS: '\x0a\x09\x09var ctr = function () {};\x0a\x09\x09ctr.prototype.foo = function (a,b) {return a+\x22,\x22+b};\x0a\x09\x09return ctr;\x0a\x09'>",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [["inlineJS:", ["\x0a\x09\x09var ctr = function () {};\x0a\x09\x09ctr.prototype.foo = function (a,b) {return a+\x22,\x22+b};\x0a\x09\x09return ctr;\x0a\x09"]]],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+
+		var ctr = function () {};
+		ctr.prototype.foo = function (a,b) {return a+","+b};
+		return ctr;
+	;
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"jsConstructor",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.AbstractJavaScriptGatewayTest);
+
+$core.addMethod(
+$core.method({
+selector: "testNiladicSuper",
+protocol: "tests",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testNiladicSuper\x0a\x09theClass := ObjectMock subclass: #ObjectMock2 slots: #() package: 'Compiler-Tests'.\x0a\x09theClass beJavaScriptSubclassOf: self jsConstructor.\x0a\x09self\x0a\x09\x09should: 'foo <jsOverride: #foo> ^ super foo'\x0a\x09\x09receiver: (ObjectMock2 new foo: 'should be shadowed'; yourself)\x0a\x09\x09return: 'undefined,undefined'",
+referencedClasses: ["ObjectMock", "ObjectMock2"],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["subclass:slots:package:", "beJavaScriptSubclassOf:", "jsConstructor", "should:receiver:return:", "foo:", "new", "yourself"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$1;
+$self.theClass=$recv($globals.ObjectMock)._subclass_slots_package_("ObjectMock2",[],"Compiler-Tests");
+$recv($self.theClass)._beJavaScriptSubclassOf_($self._jsConstructor());
+$2=$recv($globals.ObjectMock2)._new();
+$recv($2)._foo_("should be shadowed");
+$1=$recv($2)._yourself();
+$self._should_receiver_return_("foo <jsOverride: #foo> ^ super foo",$1,"undefined,undefined");
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testNiladicSuper",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.AbstractJavaScriptGatewayTest);
+
+$core.addMethod(
+$core.method({
+selector: "testNiladicSuperDifferentNames",
+protocol: "tests",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testNiladicSuperDifferentNames\x0a\x09theClass := ObjectMock subclass: #ObjectMock2 slots: #() package: 'Compiler-Tests'.\x0a\x09theClass beJavaScriptSubclassOf: self jsConstructor.\x0a\x09receiver := ObjectMock2 new foo: 'should be shadowed'; yourself.\x0a\x09self while: 'bar <jsOverride: #foo> ^ super bar' should: [\x0a\x09\x09self shouldnt: [ receiver bar ] raise: Error.\x0a\x09\x09self assert: receiver bar equals: 'undefined,undefined' ]",
+referencedClasses: ["ObjectMock", "ObjectMock2", "Error"],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["subclass:slots:package:", "beJavaScriptSubclassOf:", "jsConstructor", "foo:", "new", "yourself", "while:should:", "shouldnt:raise:", "bar", "assert:equals:"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+$self.theClass=$recv($globals.ObjectMock)._subclass_slots_package_("ObjectMock2",[],"Compiler-Tests");
+$recv($self.theClass)._beJavaScriptSubclassOf_($self._jsConstructor());
+$1=$recv($globals.ObjectMock2)._new();
+$recv($1)._foo_("should be shadowed");
+$self.receiver=$recv($1)._yourself();
+$self._while_should_("bar <jsOverride: #foo> ^ super bar",(function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+$self._shouldnt_raise_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+return [$recv($self.receiver)._bar()
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+,$ctx3.sendIdx["bar"]=1
+//>>excludeEnd("ctx");
+][0];
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)});
+//>>excludeEnd("ctx");
+}),$globals.Error);
+return $self._assert_equals_($recv($self.receiver)._bar(),"undefined,undefined");
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testNiladicSuperDifferentNames",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.AbstractJavaScriptGatewayTest);
+
+$core.addMethod(
+$core.method({
+selector: "testNiladicSuperNested",
+protocol: "tests",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testNiladicSuperNested\x0a\x09theClass := ObjectMock subclass: #ObjectMock2 slots: #() package: 'Compiler-Tests'.\x0a\x09theClass beJavaScriptSubclassOf: self jsConstructor.\x0a\x09self\x0a\x09\x09should: 'foo <jsOverride: #foo> ^ [ super foo ] value'\x0a\x09\x09receiver: (ObjectMock2 new foo: 'should be shadowed'; yourself)\x0a\x09\x09return: 'undefined,undefined'",
+referencedClasses: ["ObjectMock", "ObjectMock2"],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["subclass:slots:package:", "beJavaScriptSubclassOf:", "jsConstructor", "should:receiver:return:", "foo:", "new", "yourself"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2;
+$self.theClass=$recv($globals.ObjectMock)._subclass_slots_package_("ObjectMock2",[],"Compiler-Tests");
+$recv($self.theClass)._beJavaScriptSubclassOf_($self._jsConstructor());
+$1=$recv($globals.ObjectMock2)._new();
+$recv($1)._foo_("should be shadowed");
+$2=$recv($1)._yourself();
+$self._should_receiver_return_("foo <jsOverride: #foo> ^ [ super foo ] value",$2,"undefined,undefined");
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testNiladicSuperNested",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.AbstractJavaScriptGatewayTest);
+
+$core.addMethod(
+$core.method({
+selector: "theClass",
+protocol: "accessing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "theClass\x0a\x09^ theClass",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return $self.theClass;
+
+}; }),
+$globals.AbstractJavaScriptGatewayTest);
+
+
+$core.addMethod(
+$core.method({
+selector: "isAbstract",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAbstract\x0a\x09^ self name = AbstractJavaScriptGatewayTest name",
+referencedClasses: ["AbstractJavaScriptGatewayTest"],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["=", "name"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+$1=$self._name();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["name"]=1;
+//>>excludeEnd("ctx");
+return $recv($1).__eq($recv($globals.AbstractJavaScriptGatewayTest)._name());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isAbstract",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.AbstractJavaScriptGatewayTest.a$cls);
+
+
+$core.addClass("InlinedJSGTest", $globals.AbstractJavaScriptGatewayTest, [], "Compiler-Tests");
+
+
+$core.addClass("PlainJSGTest", $globals.AbstractJavaScriptGatewayTest, [], "Compiler-Tests");
+
+
 $core.addClass("ASTPCNodeVisitorTest", $globals.TestCase, [], "Compiler-Tests");
 $core.addMethod(
 $core.method({
@@ -3995,6 +4189,9 @@ $core.setTraitComposition([{trait: $globals.TCTNonInlined}, {trait: $globals.TCT
 $core.setTraitComposition([{trait: $globals.TCTNonInlined}, {trait: $globals.TCTInterpreted}], $globals.ASTInterpreterTest);
 $core.setTraitComposition([{trait: $globals.TCTNonInlined}, {trait: $globals.TCTExecuted}], $globals.CodeGeneratorTest);
 $core.setTraitComposition([{trait: $globals.TCTInlined}, {trait: $globals.TCTExecuted}], $globals.InliningCodeGeneratorTest);
+$core.setTraitComposition([{trait: $globals.TClassBuildingTest}], $globals.AbstractJavaScriptGatewayTest);
+$core.setTraitComposition([{trait: $globals.TCTInlined}, {trait: $globals.TCTExecuted}], $globals.InlinedJSGTest);
+$core.setTraitComposition([{trait: $globals.TCTNonInlined}, {trait: $globals.TCTExecuted}], $globals.PlainJSGTest);
 $core.setTraitComposition([{trait: $globals.TASTParsingTest}], $globals.ASTPCNodeVisitorTest);
 $core.setTraitComposition([{trait: $globals.TASTParsingTest}], $globals.ASTPositionTest);
 $core.setTraitComposition([{trait: $globals.TASTCompilingTest}], $globals.AbstractCodeGeneratorInstallTest);

+ 66 - 0
lang/src/Compiler-Tests.st

@@ -463,6 +463,69 @@ AbstractCompilerTest subclass: #InliningCodeGeneratorTest
 	slots: {}
 	package: 'Compiler-Tests'!
 
+ASTMethodRunningTest subclass: #AbstractJavaScriptGatewayTest
+	slots: {#theClass}
+	package: 'Compiler-Tests'!
+
+!AbstractJavaScriptGatewayTest methodsFor: 'accessing'!
+
+theClass
+	^ theClass
+! !
+
+!AbstractJavaScriptGatewayTest methodsFor: 'running'!
+
+jsConstructor
+	<inlineJS: '
+		var ctr = function () {};
+		ctr.prototype.foo = function (a,b) {return a+","+b};
+		return ctr;
+	'>
+! !
+
+!AbstractJavaScriptGatewayTest methodsFor: 'tests'!
+
+testNiladicSuper
+	theClass := ObjectMock subclass: #ObjectMock2 slots: #() package: 'Compiler-Tests'.
+	theClass beJavaScriptSubclassOf: self jsConstructor.
+	self
+		should: 'foo <jsOverride: #foo> ^ super foo'
+		receiver: (ObjectMock2 new foo: 'should be shadowed'; yourself)
+		return: 'undefined,undefined'
+!
+
+testNiladicSuperDifferentNames
+	theClass := ObjectMock subclass: #ObjectMock2 slots: #() package: 'Compiler-Tests'.
+	theClass beJavaScriptSubclassOf: self jsConstructor.
+	receiver := ObjectMock2 new foo: 'should be shadowed'; yourself.
+	self while: 'bar <jsOverride: #foo> ^ super bar' should: [
+		self shouldnt: [ receiver bar ] raise: Error.
+		self assert: receiver bar equals: 'undefined,undefined' ]
+!
+
+testNiladicSuperNested
+	theClass := ObjectMock subclass: #ObjectMock2 slots: #() package: 'Compiler-Tests'.
+	theClass beJavaScriptSubclassOf: self jsConstructor.
+	self
+		should: 'foo <jsOverride: #foo> ^ [ super foo ] value'
+		receiver: (ObjectMock2 new foo: 'should be shadowed'; yourself)
+		return: 'undefined,undefined'
+! !
+
+!AbstractJavaScriptGatewayTest class methodsFor: 'testing'!
+
+isAbstract
+	^ self name = AbstractJavaScriptGatewayTest name
+! !
+
+AbstractJavaScriptGatewayTest subclass: #InlinedJSGTest
+	slots: {}
+	package: 'Compiler-Tests'!
+
+AbstractJavaScriptGatewayTest subclass: #PlainJSGTest
+	slots: {}
+	package: 'Compiler-Tests'!
+
 TestCase subclass: #ASTPCNodeVisitorTest
 	slots: {}
 	package: 'Compiler-Tests'!
@@ -1054,6 +1117,9 @@ ASTDebuggerTest setTraitComposition: {TCTNonInlined. TCTDebugged} asTraitComposi
 ASTInterpreterTest setTraitComposition: {TCTNonInlined. TCTInterpreted} asTraitComposition!
 CodeGeneratorTest setTraitComposition: {TCTNonInlined. TCTExecuted} asTraitComposition!
 InliningCodeGeneratorTest setTraitComposition: {TCTInlined. TCTExecuted} asTraitComposition!
+AbstractJavaScriptGatewayTest setTraitComposition: {TClassBuildingTest} asTraitComposition!
+InlinedJSGTest setTraitComposition: {TCTInlined. TCTExecuted} asTraitComposition!
+PlainJSGTest setTraitComposition: {TCTNonInlined. TCTExecuted} asTraitComposition!
 ASTPCNodeVisitorTest setTraitComposition: {TASTParsingTest} asTraitComposition!
 ASTPositionTest setTraitComposition: {TASTParsingTest} asTraitComposition!
 AbstractCodeGeneratorInstallTest setTraitComposition: {TASTCompilingTest} asTraitComposition!