From 151af564bbd9d995ec14526d5dccd12ec6cfd417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Mon, 26 Nov 2018 11:43:22 +0100 Subject: [PATCH 1/2] chore: Add compliance test around #320 This test covers the behavior of the JSII runtimes when a method is declared to return an interface type, and returns an instance of a private (un-exported) type that implements the interface while extending an exported type. This has been seen to cause issues in the Java runtime, for example, as the JSII kernel will return an ObjID with a type fragment that refers to the exported super-class, and not the interface type. --- packages/jsii-build-tools/package-lock.json | 4 +- packages/jsii-calc/lib/compliance.ts | 25 ++++ packages/jsii-calc/test/assembly.jsii | 67 ++++++++++- .../ComplianceTests.cs | 6 + .../jsii-java-runtime-test/package-lock.json | 7 +- .../amazon/jsii/testing/ComplianceTest.java | 9 ++ packages/jsii-java-runtime/pom.xml.t.js | 2 +- packages/jsii-kernel/lib/kernel.ts | 7 +- packages/jsii-pacmak/lib/targets/java.ts | 2 +- .../.jsii | 67 ++++++++++- .../CalculatorNamespace/ExportedBaseClass.cs | 26 +++++ .../IIPrivatelyImplemented.cs | 14 +++ .../IPrivatelyImplementedProxy.cs | 18 +++ ...ReturnsPrivateImplementationOfInterface.cs | 31 +++++ .../amazon/jsii/tests/calculator/$Module.java | 3 + .../tests/calculator/ExportedBaseClass.java | 17 +++ .../calculator/IPrivatelyImplemented.java | 20 ++++ ...turnsPrivateImplementationOfInterface.java | 23 ++++ .../expected.jsii-calc/sphinx/jsii-calc.rst | 108 ++++++++++++++++++ packages/jsii-ruby-runtime/package-lock.json | 10 +- 20 files changed, 455 insertions(+), 11 deletions(-) create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ExportedBaseClass.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIPrivatelyImplemented.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IPrivatelyImplementedProxy.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ReturnsPrivateImplementationOfInterface.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExportedBaseClass.java create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IPrivatelyImplemented.java create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ReturnsPrivateImplementationOfInterface.java diff --git a/packages/jsii-build-tools/package-lock.json b/packages/jsii-build-tools/package-lock.json index d759dd7498..666210c7a3 100644 --- a/packages/jsii-build-tools/package-lock.json +++ b/packages/jsii-build-tools/package-lock.json @@ -1,6 +1,8 @@ { - "requires": true, + "name": "jsii-build-tools", + "version": "0.7.11", "lockfileVersion": 1, + "requires": true, "dependencies": { "fs-extra": { "version": "7.0.0", diff --git a/packages/jsii-calc/lib/compliance.ts b/packages/jsii-calc/lib/compliance.ts index 792004301c..d32412c066 100644 --- a/packages/jsii-calc/lib/compliance.ts +++ b/packages/jsii-calc/lib/compliance.ts @@ -1196,3 +1196,28 @@ export interface LoadBalancedFargateServiceProps { */ publicTasks?: boolean; } + +/** + * Helps ensure the JSII kernel & runtime cooperate correctly when an un-exported instance of a class is returned with + * a declared type that is an exported interface, and the instance inherits from an exported class. + * + * @returns an instance of an un-exported class that extends ``ExportedBaseClass``, declared as ``IPrivatelyImplemented``. + * + * @see https://github.com/awslabs/jsii/issues/320 + */ +export class ReturnsPrivateImplementationOfInterface { + public get privateImplementation(): IPrivatelyImplemented { + return new PrivateImplementation(); + } +} +export interface IPrivatelyImplemented { + readonly success: boolean; +} +export class ExportedBaseClass { + constructor(public readonly success: boolean) {} +} +class PrivateImplementation extends ExportedBaseClass implements IPrivatelyImplemented { + constructor() { + super(true); + } +} diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index d8f179f83d..af67585627 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -1410,6 +1410,32 @@ ], "name": "DoubleTrouble" }, + "jsii-calc.ExportedBaseClass": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.ExportedBaseClass", + "initializer": { + "initializer": true, + "parameters": [ + { + "name": "success", + "type": { + "primitive": "boolean" + } + } + ] + }, + "kind": "class", + "name": "ExportedBaseClass", + "properties": [ + { + "immutable": true, + "name": "success", + "type": { + "primitive": "boolean" + } + } + ] + }, "jsii-calc.GiveMeStructs": { "assembly": "jsii-calc", "fqn": "jsii-calc.GiveMeStructs", @@ -1633,6 +1659,22 @@ ], "name": "IInterfaceWithOptionalMethodArguments" }, + "jsii-calc.IPrivatelyImplemented": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.IPrivatelyImplemented", + "kind": "interface", + "name": "IPrivatelyImplemented", + "properties": [ + { + "abstract": true, + "immutable": true, + "name": "success", + "type": { + "primitive": "boolean" + } + } + ] + }, "jsii-calc.IRandomNumberGenerator": { "assembly": "jsii-calc", "docs": { @@ -2825,6 +2867,29 @@ } ] }, + "jsii-calc.ReturnsPrivateImplementationOfInterface": { + "assembly": "jsii-calc", + "docs": { + "comment": "Helps ensure the JSII kernel & runtime cooperate correctly when an un-exported instance of a class is returned with\na declared type that is an exported interface, and the instance inherits from an exported class.", + "return": "an instance of an un-exported class that extends ``ExportedBaseClass``, declared as ``IPrivatelyImplemented``.", + "see": "https://github.com/awslabs/jsii/issues/320" + }, + "fqn": "jsii-calc.ReturnsPrivateImplementationOfInterface", + "initializer": { + "initializer": true + }, + "kind": "class", + "name": "ReturnsPrivateImplementationOfInterface", + "properties": [ + { + "immutable": true, + "name": "privateImplementation", + "type": { + "fqn": "jsii-calc.IPrivatelyImplemented" + } + } + ] + }, "jsii-calc.RuntimeTypeChecking": { "assembly": "jsii-calc", "fqn": "jsii-calc.RuntimeTypeChecking", @@ -3671,5 +3736,5 @@ } }, "version": "0.7.11", - "fingerprint": "2o7FtEirv0LpuaJ1G+wAxoHTW7FHr4U1taZ5GcVYt2o=" + "fingerprint": "Nw3vyHfzec4IFe674buqsgL3x8QgvKP0lUC3csRIW7g=" } diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs index 2b2504e61e..b609ce9148 100644 --- a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs +++ b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs @@ -862,6 +862,12 @@ public void NullShouldBeTreatedAsUndefined() obj.VerifyPropertyIsUndefined(); } + [Fact(DisplayName = Prefix + nameof(ReceiveInstanceOfPrivateClass))] + public void ReceiveInstanceOfPrivateClass() + { + Assert.True(new ReturnsPrivateImplementationOfInterface().PrivateImplementation.Success); + } + class NumberReturner : DeputyBase, IIReturnsNumber { public NumberReturner(double number) diff --git a/packages/jsii-java-runtime-test/package-lock.json b/packages/jsii-java-runtime-test/package-lock.json index 30bbd91f53..8c9d4e0638 100644 --- a/packages/jsii-java-runtime-test/package-lock.json +++ b/packages/jsii-java-runtime-test/package-lock.json @@ -1,11 +1,14 @@ { - "requires": true, + "name": "jsii-java-runtime-test", + "version": "0.7.11", "lockfileVersion": 1, + "requires": true, "dependencies": { "@types/node": { "version": "8.10.37", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.37.tgz", - "integrity": "sha512-Jp39foY8Euv/PG4OGPyzxis82mnjcUtXLEMA8oFMCE4ilmuJgZPdV2nZNV1moz+99EJTtcpOSgDCgATUwABKig==" + "integrity": "sha512-Jp39foY8Euv/PG4OGPyzxis82mnjcUtXLEMA8oFMCE4ilmuJgZPdV2nZNV1moz+99EJTtcpOSgDCgATUwABKig==", + "dev": true } } } diff --git a/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java b/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java index cf9c8d0d9b..e95a930d31 100644 --- a/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java +++ b/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java @@ -32,6 +32,7 @@ import software.amazon.jsii.tests.calculator.Polymorphism; import software.amazon.jsii.tests.calculator.Power; import software.amazon.jsii.tests.calculator.ReferenceEnumFromScopedPackage; +import software.amazon.jsii.tests.calculator.ReturnsPrivateImplementationOfInterface; import software.amazon.jsii.tests.calculator.Statics; import software.amazon.jsii.tests.calculator.Sum; import software.amazon.jsii.tests.calculator.SyncVirtualMethods; @@ -953,6 +954,14 @@ public void nullShouldBeTreatedAsUndefined() { obj.verifyPropertyIsUndefined(); } + /** + * @see https://github.com/awslabs/jsii/issues/320 + */ + @Test + public void receiveInstanceOfPrivateClass() { + assertTrue(new ReturnsPrivateImplementationOfInterface().getPrivateImplementation().getSuccess()); + } + static class MulTen extends Multiply { public MulTen(final int value) { super(new Number(value), new Number(10)); diff --git a/packages/jsii-java-runtime/pom.xml.t.js b/packages/jsii-java-runtime/pom.xml.t.js index 9244b61944..caf8095b48 100644 --- a/packages/jsii-java-runtime/pom.xml.t.js +++ b/packages/jsii-java-runtime/pom.xml.t.js @@ -80,7 +80,7 @@ process.stdout.write(` javax.annotation javax.annotation-api - [1.2,) + [1.3.2,) provided diff --git a/packages/jsii-kernel/lib/kernel.ts b/packages/jsii-kernel/lib/kernel.ts index c508e34599..5aa9027450 100644 --- a/packages/jsii-kernel/lib/kernel.ts +++ b/packages/jsii-kernel/lib/kernel.ts @@ -435,7 +435,12 @@ export class Kernel { case spec.TypeKind.Class: case spec.TypeKind.Enum: const constructor = this._findSymbol(fqn); - constructor.__jsii__ = { fqn }; + Object.defineProperty(constructor, '__jsii__', { + configurable: false, + enumerable: false, + writable: false, + value: { fqn } + }); } } } diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index 173a53b3e0..fa47044ad3 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -389,7 +389,7 @@ class JavaGenerator extends Generator { 'properties': { 'project.build.sourceEncoding': 'UTF-8' }, - 'dependencies': { dependency: mavenDependencies() }, + 'dependencies': { dependency: mavenDependencies() }, 'build': { plugins: { diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii index d8f179f83d..af67585627 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii @@ -1410,6 +1410,32 @@ ], "name": "DoubleTrouble" }, + "jsii-calc.ExportedBaseClass": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.ExportedBaseClass", + "initializer": { + "initializer": true, + "parameters": [ + { + "name": "success", + "type": { + "primitive": "boolean" + } + } + ] + }, + "kind": "class", + "name": "ExportedBaseClass", + "properties": [ + { + "immutable": true, + "name": "success", + "type": { + "primitive": "boolean" + } + } + ] + }, "jsii-calc.GiveMeStructs": { "assembly": "jsii-calc", "fqn": "jsii-calc.GiveMeStructs", @@ -1633,6 +1659,22 @@ ], "name": "IInterfaceWithOptionalMethodArguments" }, + "jsii-calc.IPrivatelyImplemented": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.IPrivatelyImplemented", + "kind": "interface", + "name": "IPrivatelyImplemented", + "properties": [ + { + "abstract": true, + "immutable": true, + "name": "success", + "type": { + "primitive": "boolean" + } + } + ] + }, "jsii-calc.IRandomNumberGenerator": { "assembly": "jsii-calc", "docs": { @@ -2825,6 +2867,29 @@ } ] }, + "jsii-calc.ReturnsPrivateImplementationOfInterface": { + "assembly": "jsii-calc", + "docs": { + "comment": "Helps ensure the JSII kernel & runtime cooperate correctly when an un-exported instance of a class is returned with\na declared type that is an exported interface, and the instance inherits from an exported class.", + "return": "an instance of an un-exported class that extends ``ExportedBaseClass``, declared as ``IPrivatelyImplemented``.", + "see": "https://github.com/awslabs/jsii/issues/320" + }, + "fqn": "jsii-calc.ReturnsPrivateImplementationOfInterface", + "initializer": { + "initializer": true + }, + "kind": "class", + "name": "ReturnsPrivateImplementationOfInterface", + "properties": [ + { + "immutable": true, + "name": "privateImplementation", + "type": { + "fqn": "jsii-calc.IPrivatelyImplemented" + } + } + ] + }, "jsii-calc.RuntimeTypeChecking": { "assembly": "jsii-calc", "fqn": "jsii-calc.RuntimeTypeChecking", @@ -3671,5 +3736,5 @@ } }, "version": "0.7.11", - "fingerprint": "2o7FtEirv0LpuaJ1G+wAxoHTW7FHr4U1taZ5GcVYt2o=" + "fingerprint": "Nw3vyHfzec4IFe674buqsgL3x8QgvKP0lUC3csRIW7g=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ExportedBaseClass.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ExportedBaseClass.cs new file mode 100644 index 0000000000..9e237990ac --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ExportedBaseClass.cs @@ -0,0 +1,26 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiClass(typeof(ExportedBaseClass), "jsii-calc.ExportedBaseClass", "[{\"name\":\"success\",\"type\":{\"primitive\":\"boolean\"}}]")] + public class ExportedBaseClass : DeputyBase + { + public ExportedBaseClass(bool success): base(new DeputyProps(new object[]{success})) + { + } + + protected ExportedBaseClass(ByRefValue reference): base(reference) + { + } + + protected ExportedBaseClass(DeputyProps props): base(props) + { + } + + [JsiiProperty("success", "{\"primitive\":\"boolean\"}")] + public virtual bool Success + { + get => GetInstanceProperty(); + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIPrivatelyImplemented.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIPrivatelyImplemented.cs new file mode 100644 index 0000000000..4c74db5675 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IIPrivatelyImplemented.cs @@ -0,0 +1,14 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiInterface(typeof(IIPrivatelyImplemented), "jsii-calc.IPrivatelyImplemented")] + public interface IIPrivatelyImplemented + { + [JsiiProperty("success", "{\"primitive\":\"boolean\"}")] + bool Success + { + get; + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IPrivatelyImplementedProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IPrivatelyImplementedProxy.cs new file mode 100644 index 0000000000..7c904b0328 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IPrivatelyImplementedProxy.cs @@ -0,0 +1,18 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiTypeProxy(typeof(IIPrivatelyImplemented), "jsii-calc.IPrivatelyImplemented")] + internal sealed class IPrivatelyImplementedProxy : DeputyBase, IIPrivatelyImplemented + { + private IPrivatelyImplementedProxy(ByRefValue reference): base(reference) + { + } + + [JsiiProperty("success", "{\"primitive\":\"boolean\"}")] + public bool Success + { + get => GetInstanceProperty(); + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ReturnsPrivateImplementationOfInterface.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ReturnsPrivateImplementationOfInterface.cs new file mode 100644 index 0000000000..db3a2fd5b5 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ReturnsPrivateImplementationOfInterface.cs @@ -0,0 +1,31 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + /// + /// Helps ensure the JSII kernel & runtime cooperate correctly when an un-exported instance of a class is returned with + /// a declared type that is an exported interface, and the instance inherits from an exported class. + /// + /// see: https://github.com/awslabs/jsii/issues/320 + [JsiiClass(typeof(ReturnsPrivateImplementationOfInterface), "jsii-calc.ReturnsPrivateImplementationOfInterface", "[]")] + public class ReturnsPrivateImplementationOfInterface : DeputyBase + { + public ReturnsPrivateImplementationOfInterface(): base(new DeputyProps(new object[]{})) + { + } + + protected ReturnsPrivateImplementationOfInterface(ByRefValue reference): base(reference) + { + } + + protected ReturnsPrivateImplementationOfInterface(DeputyProps props): base(props) + { + } + + [JsiiProperty("privateImplementation", "{\"fqn\":\"jsii-calc.IPrivatelyImplemented\"}")] + public virtual IIPrivatelyImplemented PrivateImplementation + { + get => GetInstanceProperty(); + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java index 2278ed93d0..97f534fd5b 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java @@ -39,6 +39,7 @@ protected Class resolveClass(final String fqn) throws ClassNotFoundException case "jsii-calc.DoNotRecognizeAnyAsOptional": return software.amazon.jsii.tests.calculator.DoNotRecognizeAnyAsOptional.class; case "jsii-calc.DontComplainAboutVariadicAfterOptional": return software.amazon.jsii.tests.calculator.DontComplainAboutVariadicAfterOptional.class; case "jsii-calc.DoubleTrouble": return software.amazon.jsii.tests.calculator.DoubleTrouble.class; + case "jsii-calc.ExportedBaseClass": return software.amazon.jsii.tests.calculator.ExportedBaseClass.class; case "jsii-calc.GiveMeStructs": return software.amazon.jsii.tests.calculator.GiveMeStructs.class; case "jsii-calc.GreetingAugmenter": return software.amazon.jsii.tests.calculator.GreetingAugmenter.class; case "jsii-calc.IFriendlier": return software.amazon.jsii.tests.calculator.IFriendlier.class; @@ -46,6 +47,7 @@ protected Class resolveClass(final String fqn) throws ClassNotFoundException case "jsii-calc.IInterfaceThatShouldNotBeADataType": return software.amazon.jsii.tests.calculator.IInterfaceThatShouldNotBeADataType.class; case "jsii-calc.IInterfaceWithMethods": return software.amazon.jsii.tests.calculator.IInterfaceWithMethods.class; case "jsii-calc.IInterfaceWithOptionalMethodArguments": return software.amazon.jsii.tests.calculator.IInterfaceWithOptionalMethodArguments.class; + case "jsii-calc.IPrivatelyImplemented": return software.amazon.jsii.tests.calculator.IPrivatelyImplemented.class; case "jsii-calc.IRandomNumberGenerator": return software.amazon.jsii.tests.calculator.IRandomNumberGenerator.class; case "jsii-calc.IReturnsNumber": return software.amazon.jsii.tests.calculator.IReturnsNumber.class; case "jsii-calc.ImplictBaseOfBase": return software.amazon.jsii.tests.calculator.ImplictBaseOfBase.class; @@ -73,6 +75,7 @@ protected Class resolveClass(final String fqn) throws ClassNotFoundException case "jsii-calc.Polymorphism": return software.amazon.jsii.tests.calculator.Polymorphism.class; case "jsii-calc.Power": return software.amazon.jsii.tests.calculator.Power.class; case "jsii-calc.ReferenceEnumFromScopedPackage": return software.amazon.jsii.tests.calculator.ReferenceEnumFromScopedPackage.class; + case "jsii-calc.ReturnsPrivateImplementationOfInterface": return software.amazon.jsii.tests.calculator.ReturnsPrivateImplementationOfInterface.class; case "jsii-calc.RuntimeTypeChecking": return software.amazon.jsii.tests.calculator.RuntimeTypeChecking.class; case "jsii-calc.Statics": return software.amazon.jsii.tests.calculator.Statics.class; case "jsii-calc.StringEnum": return software.amazon.jsii.tests.calculator.StringEnum.class; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExportedBaseClass.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExportedBaseClass.java new file mode 100644 index 0000000000..def65ce5f3 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExportedBaseClass.java @@ -0,0 +1,17 @@ +package software.amazon.jsii.tests.calculator; + +@javax.annotation.Generated(value = "jsii-pacmak") +@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.ExportedBaseClass") +public class ExportedBaseClass extends software.amazon.jsii.JsiiObject { + protected ExportedBaseClass(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + public ExportedBaseClass(final java.lang.Boolean success) { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this, java.util.stream.Stream.of(java.util.Objects.requireNonNull(success, "success is required")).toArray()); + } + + public java.lang.Boolean getSuccess() { + return this.jsiiGet("success", java.lang.Boolean.class); + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IPrivatelyImplemented.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IPrivatelyImplemented.java new file mode 100644 index 0000000000..948d23584a --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/IPrivatelyImplemented.java @@ -0,0 +1,20 @@ +package software.amazon.jsii.tests.calculator; + +@javax.annotation.Generated(value = "jsii-pacmak") +public interface IPrivatelyImplemented extends software.amazon.jsii.JsiiSerializable { + java.lang.Boolean getSuccess(); + + /** + * A proxy class which represents a concrete javascript instance of this type. + */ + final static class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements software.amazon.jsii.tests.calculator.IPrivatelyImplemented { + protected Jsii$Proxy(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + + @Override + public java.lang.Boolean getSuccess() { + return this.jsiiGet("success", java.lang.Boolean.class); + } + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ReturnsPrivateImplementationOfInterface.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ReturnsPrivateImplementationOfInterface.java new file mode 100644 index 0000000000..4c72f28bb3 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ReturnsPrivateImplementationOfInterface.java @@ -0,0 +1,23 @@ +package software.amazon.jsii.tests.calculator; + +/** + * Helps ensure the JSII kernel & runtime cooperate correctly when an un-exported instance of a class is returned with + * a declared type that is an exported interface, and the instance inherits from an exported class. + * @return an instance of an un-exported class that extends ``ExportedBaseClass``, declared as ``IPrivatelyImplemented``. + * @see https://github.com/awslabs/jsii/issues/320 + */ +@javax.annotation.Generated(value = "jsii-pacmak") +@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.ReturnsPrivateImplementationOfInterface") +public class ReturnsPrivateImplementationOfInterface extends software.amazon.jsii.JsiiObject { + protected ReturnsPrivateImplementationOfInterface(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + public ReturnsPrivateImplementationOfInterface() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } + + public software.amazon.jsii.tests.calculator.IPrivatelyImplemented getPrivateImplementation() { + return this.jsiiGet("privateImplementation", software.amazon.jsii.tests.calculator.IPrivatelyImplemented.class); + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst b/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst index 593d110506..55285fbeab 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst +++ b/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst @@ -1506,6 +1506,41 @@ DoubleTrouble :rtype: number +ExportedBaseClass +^^^^^^^^^^^^^^^^^ + +.. py:class:: ExportedBaseClass(success) + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.ExportedBaseClass; + + .. code-tab:: javascript + + const { ExportedBaseClass } = require('jsii-calc'); + + .. code-tab:: typescript + + import { ExportedBaseClass } from 'jsii-calc'; + + + + :param success: + :type success: boolean + + .. py:attribute:: success + + :type: boolean *(readonly)* + + GiveMeStructs ^^^^^^^^^^^^^ @@ -1868,6 +1903,40 @@ IInterfaceWithOptionalMethodArguments (interface) :abstract: Yes +IPrivatelyImplemented (interface) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:class:: IPrivatelyImplemented + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.IPrivatelyImplemented; + + .. code-tab:: javascript + + // IPrivatelyImplemented is an interface + + .. code-tab:: typescript + + import { IPrivatelyImplemented } from 'jsii-calc'; + + + + + + .. py:attribute:: success + + :type: boolean *(readonly)* + + IRandomNumberGenerator (interface) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -3572,6 +3641,45 @@ ReferenceEnumFromScopedPackage :type: :py:class:`@scope/jsii-calc-lib.EnumFromScopedModule`\ *(optional)* +ReturnsPrivateImplementationOfInterface +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:class:: ReturnsPrivateImplementationOfInterface() + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.ReturnsPrivateImplementationOfInterface; + + .. code-tab:: javascript + + const { ReturnsPrivateImplementationOfInterface } = require('jsii-calc'); + + .. code-tab:: typescript + + import { ReturnsPrivateImplementationOfInterface } from 'jsii-calc'; + + + + Helps ensure the JSII kernel & runtime cooperate correctly when an un-exported instance of a class is returned with + + a declared type that is an exported interface, and the instance inherits from an exported class. + + + + + .. py:attribute:: privateImplementation + + :type: :py:class:`~jsii-calc.IPrivatelyImplemented`\ *(readonly)* + + RuntimeTypeChecking ^^^^^^^^^^^^^^^^^^^ diff --git a/packages/jsii-ruby-runtime/package-lock.json b/packages/jsii-ruby-runtime/package-lock.json index 8cade153a7..0375ee6296 100644 --- a/packages/jsii-ruby-runtime/package-lock.json +++ b/packages/jsii-ruby-runtime/package-lock.json @@ -1,16 +1,20 @@ { - "requires": true, + "name": "jsii-ruby-runtime", + "version": "0.7.11", "lockfileVersion": 1, + "requires": true, "dependencies": { "@types/node": { "version": "8.10.37", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.37.tgz", - "integrity": "sha512-Jp39foY8Euv/PG4OGPyzxis82mnjcUtXLEMA8oFMCE4ilmuJgZPdV2nZNV1moz+99EJTtcpOSgDCgATUwABKig==" + "integrity": "sha512-Jp39foY8Euv/PG4OGPyzxis82mnjcUtXLEMA8oFMCE4ilmuJgZPdV2nZNV1moz+99EJTtcpOSgDCgATUwABKig==", + "dev": true }, "typescript": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", - "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==" + "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", + "dev": true } } } From fb46f02e05c6c8353387d0f3434eee82f51d7c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Mon, 26 Nov 2018 12:01:42 +0100 Subject: [PATCH 2/2] fix(kernel): Correctly return instances of un-exported types When an un-exported type that extends an exported type is returned with an interface as the declared type, the JSII kernel used to return a ref with the FQN of the exported supertype, instead of correctly wrapping the instance in a proxy of the interface type as it should have. Fixes #302 --- packages/jsii-kernel/lib/kernel.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/jsii-kernel/lib/kernel.ts b/packages/jsii-kernel/lib/kernel.ts index 5aa9027450..f12933c7a5 100644 --- a/packages/jsii-kernel/lib/kernel.ts +++ b/packages/jsii-kernel/lib/kernel.ts @@ -961,7 +961,9 @@ export class Kernel { // have an object id, so we need to allocate one for it. this._debug('creating objref for', v); const fqn = this._fqnForObject(v); - return this._createObjref(v, fqn); + if (!targetType || !spec.isNamedTypeReference(targetType) || fqn === targetType.fqn) { + return this._createObjref(v, fqn); + } } // if the method/property returns an object literal and the return type