From 850f42bea4218f2563d221aff28926da16692f62 Mon Sep 17 00:00:00 2001 From: Romain Marcadier-Muller Date: Thu, 28 Mar 2019 11:51:01 +0100 Subject: [PATCH] fix(runtime): Passing 'this' to a callback from constructor (#395) In Javascript, a constructor is allowed to pass references to `this` to method calls (effectively passing a partially initialized instance). When done, the kernel will assign an Object ID to `this` on the spot in order to pass the reference through the JSII boundary. However, the `create` API before this change would have attempted to re-allocate an Object ID to the object (which is illegal and causes a crash). In addition, callbacks from at least Java and .NET runtimes could not receive JSII object references, for they would not turn them into native objects before passing them to the implementation, resulting in a class conversion error. --- .gitignore | 1 + packages/jsii-calc/lib/compliance.ts | 17 + packages/jsii-calc/package.json | 2 + packages/jsii-calc/test/assembly.jsii | 82 ++++- ...mazon.JSII.Runtime.IntegrationTests.csproj | 16 +- .../ComplianceTests.cs | 23 +- .../Amazon.JSII.Runtime/CallbackExtensions.cs | 25 +- .../Amazon.JSII.Runtime/Deputy/DeputyBase.cs | 2 +- .../Services/IReferenceMap.cs | 2 +- .../Services/ReferenceMap.cs | 4 +- .../amazon/jsii/testing/ComplianceTest.java | 24 ++ .../amazon/jsii/testing/JsiiClientTest.java | 9 +- packages/jsii-java-runtime/package.json | 2 +- packages/jsii-java-runtime/pom.xml.t.js | 34 ++ .../java/software/amazon/jsii/JsiiClient.java | 19 +- .../java/software/amazon/jsii/JsiiEngine.java | 35 +- .../java/software/amazon/jsii/JsiiObject.java | 64 +--- .../amazon/jsii/JsiiObjectMapper.java | 348 +++++++++++------- .../software/amazon/jsii/JsiiObjectRef.java | 17 + .../software/amazon/jsii/JsiiRuntime.java | 17 +- .../amazon/jsii/api/InvokeRequest.java | 7 +- .../software/amazon/jsii/api/SetRequest.java | 6 +- .../amazon/jsii/JsiiObjectMapperTest.java | 131 +++++++ .../org.mockito.plugins.MockMaker | 1 + .../amazon/jsii/complex-callback.json | 12 + packages/jsii-kernel/lib/kernel.ts | 4 +- packages/jsii-kernel/lib/objects.ts | 7 +- packages/jsii-kernel/test/test.kernel.ts | 22 ++ packages/jsii-pacmak/lib/generator.ts | 6 +- packages/jsii-pacmak/lib/targets/java.ts | 2 +- .../jsii/tests/calculator/base/Base.java | 4 + .../jsii/tests/calculator/base/BaseProps.java | 2 +- .../tests/calculator/lib/MyFirstStruct.java | 2 +- .../jsii/tests/calculator/lib/Operation.java | 4 + .../lib/StructWithOnlyOptionals.java | 2 +- .../jsii/tests/calculator/lib/Value.java | 4 + .../.jsii | 82 ++++- ...azon.JSII.Tests.CalculatorPackageId.csproj | 1 + .../ConstructorPassesThisOut.cs | 20 + .../Internal/DependencyResolution/Anchor.cs | 1 + .../PartiallyInitializedThisConsumer.cs | 24 ++ .../PartiallyInitializedThisConsumerProxy.cs | 19 + .../test/expected.jsii-calc/java/pom.xml | 4 +- .../amazon/jsii/tests/calculator/$Module.java | 4 +- .../jsii/tests/calculator/AbstractClass.java | 4 + .../tests/calculator/AbstractClassBase.java | 4 + .../tests/calculator/BinaryOperation.java | 9 + .../tests/calculator/CalculatorProps.java | 2 +- .../calculator/ConstructorPassesThisOut.java | 13 + .../jsii/tests/calculator/DerivedStruct.java | 2 +- .../EraseUndefinedHashValuesOptions.java | 2 +- .../calculator/ExtendsInternalInterface.java | 2 +- .../calculator/ExtendsPrivateInterface.java | 2 +- .../tests/calculator/ImplictBaseOfBase.java | 2 +- .../InterfaceImplementedByAbstractClass.java | 2 +- .../Hello.java | 2 +- .../Hello.java | 2 +- .../LoadBalancedFargateServiceProps.java | 2 +- .../NullShouldBeTreatedAsUndefinedData.java | 2 +- .../PartiallyInitializedThisConsumer.java | 29 ++ .../jsii/tests/calculator/UnaryOperation.java | 4 + .../tests/calculator/UnionProperties.java | 2 +- .../composition/CompositeOperation.java | 4 + .../test/expected.jsii-calc/python/setup.py | 1 + .../python/src/jsii_calc/__init__.py | 28 +- .../python/src/jsii_calc/_jsii/__init__.py | 1 + .../expected.jsii-calc/sphinx/jsii-calc.rst | 71 ++++ packages/jsii-python-runtime/.gitignore | 1 + .../tests/test_compliance.py | 13 + .../jsii-reflect/test/classes.expected.txt | 2 + .../test/jsii-tree.test.all.expected.txt | 22 ++ .../jsii-tree.test.inheritance.expected.txt | 2 + .../test/jsii-tree.test.members.expected.txt | 7 + .../test/jsii-tree.test.types.expected.txt | 2 + 74 files changed, 1069 insertions(+), 286 deletions(-) create mode 100644 packages/jsii-java-runtime/project/src/test/java/software/amazon/jsii/JsiiObjectMapperTest.java create mode 100644 packages/jsii-java-runtime/project/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 packages/jsii-java-runtime/project/src/test/resources/software/amazon/jsii/complex-callback.json create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ConstructorPassesThisOut.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/PartiallyInitializedThisConsumer.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/PartiallyInitializedThisConsumerProxy.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ConstructorPassesThisOut.java create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/PartiallyInitializedThisConsumer.java diff --git a/.gitignore b/.gitignore index 098af53bc4..b70cc9f0e6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules/ lerna-debug.log .DS_Store .idea +.vs /dist diff --git a/packages/jsii-calc/lib/compliance.ts b/packages/jsii-calc/lib/compliance.ts index 81e7c5739d..82a37aa5bb 100644 --- a/packages/jsii-calc/lib/compliance.ts +++ b/packages/jsii-calc/lib/compliance.ts @@ -1583,3 +1583,20 @@ export class ConsumersOfThisCrazyTypeSystem { return { a: obj.a, b: obj.b, c: obj.c }; } } + + +// +// Ensure the JSII kernel can pass "this" out to JSII remotes from within the constructor (this is dirty, but possible) +/// +export abstract class PartiallyInitializedThisConsumer { + public abstract consumePartiallyInitializedThis(obj: ConstructorPassesThisOut, dt: Date, ev: AllTypesEnum): string; +} + +export class ConstructorPassesThisOut { + constructor(consumer: PartiallyInitializedThisConsumer) { + const result = consumer.consumePartiallyInitializedThis(this, new Date(0), AllTypesEnum.ThisIsGreat); + if (result !== 'OK') { + throw new Error(`Expected OK but received ${result}`); + } + } +} diff --git a/packages/jsii-calc/package.json b/packages/jsii-calc/package.json index 0a9caf90ce..6c1019c133 100644 --- a/packages/jsii-calc/package.json +++ b/packages/jsii-calc/package.json @@ -36,11 +36,13 @@ ], "dependencies": { "@scope/jsii-calc-base": "^0.8.0", + "@scope/jsii-calc-base-of-base": "^0.8.0", "@scope/jsii-calc-lib": "^0.8.0", "jsii-calc-bundled": "^0.8.0" }, "peerDependencies": { "@scope/jsii-calc-base": "^0.8.0", + "@scope/jsii-calc-base-of-base": "^0.8.0", "@scope/jsii-calc-lib": "^0.8.0" }, "devDependencies": { diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index 20fac29cd7..dc9f5f0401 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -84,6 +84,30 @@ }, "version": "0.8.0" }, + "@scope/jsii-calc-base-of-base": { + "peer": true, + "targets": { + "dotnet": { + "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", + "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" + }, + "java": { + "maven": { + "artifactId": "calculator-base-of-base", + "groupId": "software.amazon.jsii.tests" + }, + "package": "software.amazon.jsii.tests.calculator.baseofbase" + }, + "js": { + "npm": "@scope/jsii-calc-base-of-base" + }, + "python": { + "distName": "scope.jsii-calc-base-of-base", + "module": "scope.jsii_calc_base_of_base" + } + }, + "version": "0.8.0" + }, "@scope/jsii-calc-lib": { "dependencies": { "@scope/jsii-calc-base": { @@ -1250,6 +1274,23 @@ } ] }, + "jsii-calc.ConstructorPassesThisOut": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.ConstructorPassesThisOut", + "initializer": { + "initializer": true, + "parameters": [ + { + "name": "consumer", + "type": { + "fqn": "jsii-calc.PartiallyInitializedThisConsumer" + } + } + ] + }, + "kind": "class", + "name": "ConstructorPassesThisOut" + }, "jsii-calc.Constructors": { "assembly": "jsii-calc", "fqn": "jsii-calc.Constructors", @@ -3327,6 +3368,45 @@ ], "name": "OverrideReturnsObject" }, + "jsii-calc.PartiallyInitializedThisConsumer": { + "abstract": true, + "assembly": "jsii-calc", + "fqn": "jsii-calc.PartiallyInitializedThisConsumer", + "initializer": { + "initializer": true + }, + "kind": "class", + "methods": [ + { + "abstract": true, + "name": "consumePartiallyInitializedThis", + "parameters": [ + { + "name": "obj", + "type": { + "fqn": "jsii-calc.ConstructorPassesThisOut" + } + }, + { + "name": "dt", + "type": { + "primitive": "date" + } + }, + { + "name": "ev", + "type": { + "fqn": "jsii-calc.AllTypesEnum" + } + } + ], + "returns": { + "primitive": "string" + } + } + ], + "name": "PartiallyInitializedThisConsumer" + }, "jsii-calc.Polymorphism": { "assembly": "jsii-calc", "fqn": "jsii-calc.Polymorphism", @@ -4500,5 +4580,5 @@ } }, "version": "0.8.0", - "fingerprint": "WIFIhqgEwUDjCsDr7gliujhqcKZQSkDP+NstBfmdvZU=" + "fingerprint": "J0bhm0cu1dlTAyMfBlAMWCVXZf6e8k2pHkmxye6P7Wk=" } diff --git a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj index bb130050b1..59dea45c8f 100644 --- a/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj +++ b/packages/jsii-dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/Amazon.JSII.Runtime.IntegrationTests.csproj @@ -7,20 +7,20 @@ - + - - - - - - + + + + + + - + 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 8b35565b87..7c3e510f5f 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 @@ -892,10 +892,31 @@ public void EraseUnsetDataValues() Assert.True(EraseUndefinedHashValues.DoesKeyExist(opts, "option1")); Assert.False(EraseUndefinedHashValues.DoesKeyExist(opts, "option2")); - + Assert.Equal(new Dictionary { ["prop2"] = "value2" }, EraseUndefinedHashValues.Prop1IsNull()); Assert.Equal(new Dictionary { [ "prop1"] = "value1" }, EraseUndefinedHashValues.Prop2IsUndefined()); } + + [Fact(DisplayName = Prefix + nameof(ObjectIdDoesNotGetReallocatedWhenTheConstructorPassesThisOut), Skip = "Currently broken")] + public void ObjectIdDoesNotGetReallocatedWhenTheConstructorPassesThisOut() + { + var reflector = new PartiallyInitializedThisConsumerImpl(); + var obj = new ConstructorPassesThisOut(reflector); + + Assert.NotNull(obj); + } + + class PartiallyInitializedThisConsumerImpl : PartiallyInitializedThisConsumer + { + public override String ConsumePartiallyInitializedThis(ConstructorPassesThisOut obj, DateTime dt, AllTypesEnum ev) + { + Assert.NotNull(obj); + Assert.Equal(new DateTime(0), dt); + Assert.Equal(AllTypesEnum.ThisIsGreat, ev); + + return "OK"; + } + } class NumberReturner : DeputyBase, IIReturnsNumber { public NumberReturner(double number) diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs index 8fe9067aae..fef3002435 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/CallbackExtensions.cs @@ -4,7 +4,9 @@ using Amazon.JSII.Runtime.Deputy; using Amazon.JSII.Runtime.Services; using Amazon.JSII.Runtime.Services.Converters; +using Newtonsoft.Json.Linq; using System; +using System.Linq; using System.Reflection; namespace Amazon.JSII.Runtime @@ -71,11 +73,11 @@ static CallbackResult InvokeMethod(InvokeRequest request, IReferenceMap referenc if (methodInfo == null) { - throw new InvalidOperationException($"Received callback for {deputy.GetType().Name}.{request.Method} getter, but this method does not exist"); + throw new InvalidOperationException($"Received callback for {deputy.GetType().Name}.{request.Method} method, but this method does not exist"); } JsiiMethodAttribute attribute = methodInfo.GetCustomAttribute(); - return new CallbackResult(attribute?.Returns, methodInfo.Invoke(deputy, request.Arguments)); + return new CallbackResult(attribute?.Returns, methodInfo.Invoke(deputy, request.Arguments.Select(arg => FromKernel(arg, referenceMap)).ToArray())); } static CallbackResult InvokeGetter(GetRequest request, IReferenceMap referenceMap) @@ -117,7 +119,24 @@ static void InvokeSetter(SetRequest request, IReferenceMap referenceMap) throw new InvalidOperationException($"Received callback for {deputy.GetType().Name}.{request.Property} setter, but this property does not have a setter"); } - methodInfo.Invoke(deputy, new object[] { request.Value }); + methodInfo.Invoke(deputy, new object[] { FromKernel(request.Value, referenceMap) }); + } + + /* + * This is a temporary workaround / hack to solve an immediate problem, but does not completely solve the + * problem to it's full extent. See https://github.com/awslabs/jsii/issues/404 for more information. + */ + private static object FromKernel(object obj, IReferenceMap referenceMap) + { + if (obj is JObject) + { + var prop = ((JObject)obj).Property("$jsii.byref"); + if (prop != null) + { + return referenceMap.GetOrCreateNativeReference(new ByRefValue(prop.Value.Value())); + } + } + return obj; } } diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/DeputyBase.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/DeputyBase.cs index c315018125..bf04054421 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/DeputyBase.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Deputy/DeputyBase.cs @@ -54,7 +54,7 @@ protected DeputyBase(DeputyProps props = null) Reference = new ByRefValue(response["$jsii.byref"]); IReferenceMap referenceMap = serviceProvider.GetRequiredService(); - referenceMap.AddNativeReference(Reference, this); + referenceMap.AddNativeReference(Reference, this, true); Override[] GetOverrides() { diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/IReferenceMap.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/IReferenceMap.cs index 3294f2de5f..48de5ea9db 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/IReferenceMap.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/IReferenceMap.cs @@ -5,7 +5,7 @@ namespace Amazon.JSII.Runtime.Services { public interface IReferenceMap { - void AddNativeReference(ByRefValue reference, DeputyBase nativeReference); + void AddNativeReference(ByRefValue reference, DeputyBase nativeReference, bool force = false); DeputyBase GetOrCreateNativeReference(ObjectReference reference); diff --git a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs index 609ab784fb..4ffaef5cc6 100644 --- a/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs +++ b/packages/jsii-dotnet-runtime/src/Amazon.JSII.Runtime/Services/ReferenceMap.cs @@ -16,9 +16,9 @@ public ReferenceMap(ITypeCache types) _types = types ?? throw new ArgumentNullException(nameof(types)); } - public void AddNativeReference(ByRefValue reference, DeputyBase nativeReference) + public void AddNativeReference(ByRefValue reference, DeputyBase nativeReference, bool force) { - if (_references.ContainsKey(reference.Value)) + if (_references.ContainsKey(reference.Value) && !force) { throw new ArgumentException( $"Cannot add reference for {reference.Value}: A reference with this name already exists", 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 b15956ab4c..9791cc269a 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 @@ -8,6 +8,7 @@ import software.amazon.jsii.tests.calculator.AbstractClassReturner; import software.amazon.jsii.tests.calculator.Add; import software.amazon.jsii.tests.calculator.AllTypes; +import software.amazon.jsii.tests.calculator.AllTypesEnum; import software.amazon.jsii.tests.calculator.AsyncVirtualMethods; import software.amazon.jsii.tests.calculator.Calculator; import software.amazon.jsii.tests.calculator.CalculatorProps; @@ -38,6 +39,7 @@ import software.amazon.jsii.tests.calculator.NullShouldBeTreatedAsUndefined; import software.amazon.jsii.tests.calculator.NullShouldBeTreatedAsUndefinedData; import software.amazon.jsii.tests.calculator.NumberGenerator; +import software.amazon.jsii.tests.calculator.PartiallyInitializedThisConsumer; import software.amazon.jsii.tests.calculator.Polymorphism; import software.amazon.jsii.tests.calculator.Power; import software.amazon.jsii.tests.calculator.PublicClass; @@ -55,6 +57,7 @@ import software.amazon.jsii.tests.calculator.lib.Number; import software.amazon.jsii.tests.calculator.lib.StructWithOnlyOptionals; import software.amazon.jsii.tests.calculator.lib.Value; +import software.amazon.jsii.tests.calculator.ConstructorPassesThisOut; import java.io.IOException; import java.time.Instant; @@ -1010,6 +1013,27 @@ public void eraseUnsetDataValues() { assertEquals("{prop1=value1}", EraseUndefinedHashValues.prop2IsUndefined().toString()); } + @Test + public void objectIdDoesNotGetReallocatedWhenTheConstructorPassesThisOut() { + final PartiallyInitializedThisConsumer reflector = new PartiallyInitializedThisConsumerImpl(); + final ConstructorPassesThisOut object = new ConstructorPassesThisOut(reflector); + + assertTrue(object != null); + } + + static class PartiallyInitializedThisConsumerImpl extends PartiallyInitializedThisConsumer { + @Override + public String consumePartiallyInitializedThis(final ConstructorPassesThisOut obj, + final Instant dt, + final AllTypesEnum en) { + assertNotNull(obj); + assertEquals(Instant.EPOCH, dt); + assertEquals(AllTypesEnum.ThisIsGreat, en); + + return "OK"; + } + } + static class MulTen extends Multiply { public MulTen(final int value) { super(new Number(value), new Number(10)); diff --git a/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/JsiiClientTest.java b/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/JsiiClientTest.java index 3c9da690e4..480383adbb 100644 --- a/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/JsiiClientTest.java +++ b/packages/jsii-java-runtime-test/project/src/test/java/software/amazon/jsii/testing/JsiiClientTest.java @@ -116,7 +116,7 @@ public void asyncMethodOverrides() { assertEquals("overrideMe", first.getInvoke().getMethod()); assertEquals("myCookie", first.getCookie()); assertEquals(1, first.getInvoke().getArgs().size()); - assertEquals(10, first.getInvoke().getArgs().get(0)); + assertEquals(JsiiObjectMapper.valueToTree(10), first.getInvoke().getArgs().get(0)); assertEquals(obj.getObjId(), JsiiObjectRef.parse(first.getInvoke().getObjref()).getObjId()); // now complete the callback with some override value @@ -146,7 +146,7 @@ public void asyncMethodOverridesThrow() { assertEquals("overrideMe", first.getInvoke().getMethod()); assertEquals("myCookie", first.getCookie()); assertEquals(1, first.getInvoke().getArgs().size()); - assertEquals(10, first.getInvoke().getArgs().get(0)); + assertEquals(JsiiObjectMapper.valueToTree(10), first.getInvoke().getArgs().get(0)); assertEquals(obj.getObjId(), JsiiObjectRef.parse(first.getInvoke().getObjref()).getObjId()); // now complete the callback with an error @@ -171,7 +171,7 @@ public void syncVirtualMethods() { jsiiRuntime.setCallbackHandler(callback -> { assertEquals(obj.getObjId(), JsiiObjectRef.parse(callback.getInvoke().getObjref()).getObjId()); assertEquals("virtualMethod", callback.getInvoke().getMethod()); - assertEquals(10, callback.getInvoke().getArgs().get(0)); + assertEquals(JsiiObjectMapper.valueToTree(10), callback.getInvoke().getArgs().get(0)); assertEquals("myCookie", callback.getCookie()); // interact with jsii from inside the callback @@ -226,8 +226,7 @@ public void staticMethods() { */ @Test public void serializeViaJsiiToJsonIfExists() { - JsiiObjectMapper om = JsiiObjectMapper.instance; - JsonNode result = om.valueToTree(new JsiiSerializable() { + JsonNode result = JsiiObjectMapper.INSTANCE.valueToTree(new JsiiSerializable() { public JsonNode $jsii$toJson() { ObjectNode node = JSON.objectNode(); node.set("foo", OM.valueToTree("bar")); diff --git a/packages/jsii-java-runtime/package.json b/packages/jsii-java-runtime/package.json index 5f6ddfcfbb..6c5509e8dd 100644 --- a/packages/jsii-java-runtime/package.json +++ b/packages/jsii-java-runtime/package.json @@ -8,7 +8,7 @@ "scripts": { "gen": "/bin/bash ./generate.sh", "build": "tsc && npm run gen && cd project && mvn deploy -D altDeploymentRepository=local::default::file://${PWD}/../maven-repo", - "test": "echo 'Tests are performed by jsii-java-runtime-test'", + "test": "echo 'Tests are run as part of the build target'", "package": "package-java" }, "devDependencies": { diff --git a/packages/jsii-java-runtime/pom.xml.t.js b/packages/jsii-java-runtime/pom.xml.t.js index 12eb2aed90..d77310c4d0 100644 --- a/packages/jsii-java-runtime/pom.xml.t.js +++ b/packages/jsii-java-runtime/pom.xml.t.js @@ -83,6 +83,30 @@ process.stdout.write(` [1.3.2,) provided + + + + org.junit.jupiter + junit-jupiter-api + 5.4.1 + test + + + + + org.junit.jupiter + junit-jupiter-engine + 5.4.1 + test + + + + + org.mockito + mockito-core + 2.25.1 + test + @@ -128,6 +152,16 @@ process.stdout.write(` protected + + + maven-surefire-plugin + 2.22.0 + + + + maven-failsafe-plugin + 2.22.0 + diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiClient.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiClient.java index 7f5b84d3db..bdd86f20cb 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiClient.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiClient.java @@ -5,7 +5,6 @@ import software.amazon.jsii.api.JsiiOverride; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -27,16 +26,6 @@ public final class JsiiClient { */ private static final JsonNodeFactory JSON = JsonNodeFactory.instance; - /** - * JSON object mapper. - */ - private static final ObjectMapper STD_OM = new ObjectMapper(); - - /** - * Jsii custom object mapper. - */ - private static final JsiiObjectMapper JSII_OM = JsiiObjectMapper.instance; - /** * TCP port to connect to (always "localhost"). */ @@ -95,7 +84,7 @@ public JsiiObjectRef createObject(final String fqn, request.setArgs(initializerArgs); request.setOverrides(overrides); - ObjectNode req = JSII_OM.valueToTree(request); + ObjectNode req = JsiiObjectMapper.valueToTree(request); req.put("api", "create"); JsonNode resp = this.runtime.requestResponse(req); @@ -245,11 +234,7 @@ public List pendingCallbacks() { List result = new ArrayList<>(); callbacksArray.forEach(node -> { - try { - result.add(STD_OM.treeToValue(node, Callback.class)); - } catch (JsonProcessingException e) { - throw new JsiiException(e); - } + result.add(JsiiObjectMapper.treeToValue(node, Callback.class)); }); return result; diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiEngine.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiEngine.java index 975d3a29f7..c957574a31 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiEngine.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiEngine.java @@ -5,7 +5,10 @@ import software.amazon.jsii.api.InvokeRequest; import software.amazon.jsii.api.JsiiOverride; import software.amazon.jsii.api.SetRequest; + +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.base.Throwables; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -45,11 +48,6 @@ public final class JsiiEngine implements JsiiCallbackHandler { */ private final JsiiRuntime runtime = new JsiiRuntime(); - /** - * JSON object mapper. - */ - private static final JsiiObjectMapper OM = JsiiObjectMapper.instance; - /** * The set of modules we already loaded into the VM. */ @@ -253,7 +251,7 @@ private JsiiObject createNative(final String fqn) { + e.getMessage(), e); } } catch (ClassNotFoundException e) { - System.err.println("WARNING: Cannot find the class: " + fqn + ". Defaulting to JsiiObject"); + this.log("WARNING: Cannot find the class: %s. Defaulting to JsiiObject", fqn); return new JsiiObject(JsiiObject.InitializationMode.Jsii); } } @@ -323,7 +321,7 @@ private JsonNode invokeCallbackGet(final GetRequest req) { String methodName = javaScriptPropertyToJavaPropertyName("get", req.getProperty()); try { Method getter = obj.getClass().getMethod(methodName); - return OM.valueToTree(invokeMethod(obj, getter)); + return JsiiObjectMapper.valueToTree(invokeMethod(obj, getter)); } catch (NoSuchMethodException e) { throw new JsiiException(e); } @@ -350,7 +348,8 @@ private JsonNode invokeCallbackSet(final SetRequest req) { throw new JsiiException("Unable to find property setter " + setterMethodName); } - return OM.valueToTree(invokeMethod(obj, setter, req.getValue())); + final Object arg = JsiiObjectMapper.treeToValue(req.getValue(), setter.getParameterTypes()[0]); + return JsiiObjectMapper.valueToTree(invokeMethod(obj, setter, arg)); } /** @@ -362,7 +361,14 @@ private JsonNode invokeCallbackSet(final SetRequest req) { private JsonNode invokeCallbackMethod(final InvokeRequest req, final String cookie) { Object obj = this.getObject(req.getObjref()); Method method = this.findCallbackMethod(obj.getClass(), cookie); - return OM.valueToTree(invokeMethod(obj, method, req.getArgs().toArray())); + + final Class[] argTypes = method.getParameterTypes(); + final Object[] args = new Object[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + args[i] = JsiiObjectMapper.treeToValue(req.getArgs().get(i), argTypes[i]); + } + + return JsiiObjectMapper.valueToTree(invokeMethod(obj, method, args)); } /** @@ -379,7 +385,12 @@ private Object invokeMethod(final Object obj, final Method method, final Object. method.setAccessible(true); try { - return method.invoke(obj, args); + try { + return method.invoke(obj, args); + } catch (Exception e) { + this.log("Error while invoking %s with %s: %s", method, Arrays.toString(args), Throwables.getStackTraceAsString(e)); + throw e; + } } catch (InvocationTargetException e) { throw new JsiiException(e.getTargetException()); } catch (IllegalAccessException e) { @@ -508,6 +519,10 @@ private static Collection discoverOverrides(final Class classTo return overrides.values(); } + private void log(final String format, final Object... args) { + System.err.println(String.format(format, args)); + } + /** * Attempts to find the @Jsii annotation from a type. * @param type The type. diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObject.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObject.java index d3f1afc2b8..d6cc888cf6 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObject.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObject.java @@ -11,11 +11,6 @@ */ public class JsiiObject implements JsiiSerializable { - /** - * JSON object mapper. - */ - private static final JsiiObjectMapper OM = JsiiObjectMapper.instance; - /** * The jsii engine used by this object. */ @@ -58,16 +53,11 @@ public enum InitializationMode { */ @Nullable protected final T jsiiCall(final String method, final Class returnType, @Nullable final Object... args) { - try { - return OM.treeToValue(JsiiObject.engine.getClient().callMethod( - this.objRef, - method, - OM.valueToTree(args)), - returnType); - - } catch (JsonProcessingException e) { - throw new JsiiException(e); - } + return JsiiObjectMapper.treeToValue(JsiiObject.engine.getClient() + .callMethod(this.objRef, + method, + JsiiObjectMapper.valueToTree(args)), + returnType); } /** @@ -82,16 +72,9 @@ protected final T jsiiCall(final String method, final Class returnType, @ @Nullable protected static T jsiiStaticCall(final Class nativeClass, final String method, final Class returnType, @Nullable final Object... args) { String fqn = engine.loadModuleForClass(nativeClass); - try { - return OM.treeToValue(engine.getClient().callStaticMethod( - fqn, - method, - OM.valueToTree(args)), - returnType); - - } catch (JsonProcessingException e) { - throw new JsiiException(e); - } + return JsiiObjectMapper.treeToValue(engine.getClient() + .callStaticMethod(fqn, method, JsiiObjectMapper.valueToTree(args)), + returnType); } /** @@ -104,17 +87,12 @@ protected static T jsiiStaticCall(final Class nativeClass, final String m */ @Nullable protected final T jsiiAsyncCall(final String method, final Class returnType, @Nullable final Object... args) { - try { - JsiiClient client = engine.getClient(); - JsiiPromise promise = client.beginAsyncMethod(this.objRef, method, OM.valueToTree(args)); + JsiiClient client = engine.getClient(); + JsiiPromise promise = client.beginAsyncMethod(this.objRef, method, JsiiObjectMapper.valueToTree(args)); - engine.processAllPendingCallbacks(); + engine.processAllPendingCallbacks(); - JsonNode ret = client.endAsyncMethod(promise); - return OM.treeToValue(ret, returnType); - } catch (JsonProcessingException e) { - throw new JsiiException(e); - } + return JsiiObjectMapper.treeToValue(client.endAsyncMethod(promise), returnType); } /** @@ -126,11 +104,7 @@ protected final T jsiiAsyncCall(final String method, final Class returnTy */ @Nullable protected final T jsiiGet(final String property, final Class type) { - try { - return OM.treeToValue(engine.getClient().getPropertyValue(this.objRef, property), type); - } catch (JsonProcessingException e) { - throw new JsiiException(e); - } + return JsiiObjectMapper.treeToValue(engine.getClient().getPropertyValue(this.objRef, property), type); } /** @@ -143,12 +117,8 @@ protected final T jsiiGet(final String property, final Class type) { */ @Nullable protected static T jsiiStaticGet(final Class nativeClass, final String property, final Class type) { - try { - String fqn = engine.loadModuleForClass(nativeClass); - return OM.treeToValue(engine.getClient().getStaticPropertyValue(fqn, property), type); - } catch (JsonProcessingException e) { - throw new JsiiException(e); - } + String fqn = engine.loadModuleForClass(nativeClass); + return JsiiObjectMapper.treeToValue(engine.getClient().getStaticPropertyValue(fqn, property), type); } /** @@ -157,7 +127,7 @@ protected static T jsiiStaticGet(final Class nativeClass, final String pr * @param value The property value. */ protected final void jsiiSet(final String property, @Nullable final Object value) { - engine.getClient().setPropertyValue(this.objRef, property, OM.valueToTree(value)); + engine.getClient().setPropertyValue(this.objRef, property, JsiiObjectMapper.valueToTree(value)); } /** @@ -168,7 +138,7 @@ protected final void jsiiSet(final String property, @Nullable final Object value */ protected static void jsiiStaticSet(final Class nativeClass, final String property, @Nullable final Object value) { String fqn = engine.loadModuleForClass(nativeClass); - engine.getClient().setStaticPropertyValue(fqn, property, OM.valueToTree(value)); + engine.getClient().setStaticPropertyValue(fqn, property, JsiiObjectMapper.valueToTree(value)); } /** diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectMapper.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectMapper.java index 15bfcf4dfc..f562de697d 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectMapper.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectMapper.java @@ -1,186 +1,250 @@ package software.amazon.jsii; -import com.fasterxml.jackson.annotation.JsonInclude; +import java.io.IOException; +import java.time.Instant; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; +import com.fasterxml.jackson.databind.deser.ResolvableDeserializer; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import java.io.IOException; -import java.time.Instant; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -import static software.amazon.jsii.JsiiEngine.tryGetJsiiAnnotation; +import com.fasterxml.jackson.databind.type.MapLikeType; +import com.fasterxml.jackson.databind.type.MapType; +import com.google.common.annotations.VisibleForTesting; /** - * Implements serialization/deserialization of jsii data. + * Provides a correctly configured JSON processor for handling JSII requests and responses. */ public final class JsiiObjectMapper { - /** - * Singleton instance of the object mapper. - */ - public static JsiiObjectMapper instance = new JsiiObjectMapper(); + public static final long serialVersionUID = 1L; + + /** + * An ObjectMapper that can be used to serialize and deserialize JSII requests and responses. + */ + public static final ObjectMapper INSTANCE = new JsiiObjectMapper().getObjectMapper(); + + /** + * Similar to calling JsiiObjectMapper.INSTANCE.treeToValue, but handles a null JsonNode argument + * well, and throws JsiiException instead of JsonProcessingException. + */ + public static T treeToValue(final JsonNode tree, final Class valueType) { + if (tree == null) { + return null; + } + try { + return INSTANCE.treeToValue(tree, valueType); + } catch (final JsonProcessingException jpe) { + throw new JsiiException(jpe); + } + } + + /** + * Similar to calling JsiiObjectMapper.INSTANCE.valueToTree, but handles a null argument well by + * returning null. + */ + public static T valueToTree(final Object value) { + if (value == null) { + return null; + } + return INSTANCE.valueToTree(value); + } - /** - * JSON token that represents an object reference. - */ - private static final String TOKEN_REF = JsiiObjectRef.TOKEN_REF; + private static final String TOKEN_REF = JsiiObjectRef.TOKEN_REF; - /** - * JSON token to represent a date. - */ - private static final String TOKEN_DATE = "$jsii.date"; + private static final String TOKEN_DATE = "$jsii.date"; - /** - * JSON token to represent an enum. - */ - private static final String TOKEN_ENUM = "$jsii.enum"; + private static final String TOKEN_ENUM = "$jsii.enum"; - /** - * The standard JSON mapper. - */ - private static ObjectMapper standardMapper = new ObjectMapper(); + private final ObjectMapper objectMapper; - /** - * Object mapper configured for jsii serialization. - */ - private ObjectMapper serializer; + private final JsiiEngine jsiiEngine; - /** - * Creates an object mapper. - */ - private JsiiObjectMapper() { - this.serializer = new ObjectMapper(); - this.serializer.setSerializationInclusion(JsonInclude.Include.NON_NULL); + private JsiiObjectMapper() { + this(JsiiEngine.getInstance()); + } - SimpleModule module = new SimpleModule(); - module.addSerializer(JsiiSerializable.class, new JsiiSerializer()); - module.addSerializer(Instant.class, new DateSerializer()); - module.addSerializer(Enum.class, new EnumSerializer()); + @VisibleForTesting + JsiiObjectMapper(final JsiiEngine jsiiEngine) { + this.jsiiEngine = jsiiEngine; + this.objectMapper = new ObjectMapper(); + this.objectMapper.setSerializationInclusion(Include.NON_NULL); - this.serializer.registerModule(module); - } + final SimpleModule module = new SimpleModule("JSII", Version.unknownVersion()); + module.setDeserializerModifier(new JsiiDeserializerModifier()); + module.addSerializer(Enum.class, new EnumSerializer()); + module.addSerializer(Instant.class, new Instanterializer()); + module.addSerializer(JsiiSerializable.class, new JsiiSerializer()); - /** - * Converts a local value to a jsii JSON representation. - * - * @param value The local java value. - * @param The return type. - * @return A JSON tree. - */ - public T valueToTree(final Object value) { - if (value == null) { - return null; - } + this.objectMapper.findAndRegisterModules(); + this.objectMapper.registerModule(module); + } - return this.serializer.valueToTree(value); - } + @VisibleForTesting + ObjectMapper getObjectMapper() { + return this.objectMapper; + } + + /** + * A JsonDeserializer designed to correctly handle JSII "magic objects" that are used to remodel "pass-by-reference" + * values, dates, and enum constants. + */ + private final class JsiiDeserializer extends StdDeserializer implements ContextualDeserializer, ResolvableDeserializer{ + public static final long serialVersionUID = 1L; + + private final JsonDeserializer standardDeserializer; /** - * Converts a jsii JSON tree to a local Java type. - * @param tree The JSON tree. - * @param type The expected return type. - * @param The return type. - * @return The local Java value. - * @throws JsonProcessingException If there was a problem reading the JSON tree. + * @param standardDeserializer a standard Jackson deserialize that can be delegated to in case the object is not a + * JSII "magic object". */ - @SuppressWarnings("unchecked") - public T treeToValue(final JsonNode tree, final Class type) throws JsonProcessingException { - if (tree == null) { - return null; - } + public JsiiDeserializer(final JsonDeserializer standardDeserializer) { + super(Object.class); + this.standardDeserializer = standardDeserializer; + } - if (tree.isArray()) { - ArrayNode array = (ArrayNode) tree; - ArrayList out = new ArrayList<>(); - for (JsonNode x : array) { - out.add(treeToValue(x, Object.class)); - } - return (T) out; - } + @Override + public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + final JsonNode node = p.readValueAsTree(); - if (tree.isObject() && tree.has(TOKEN_DATE)) { - return (T) Instant.parse(tree.get(TOKEN_DATE).textValue()); + if (node.isObject()) { + if (node.has(TOKEN_DATE)) { + return Instant.parse(node.get(TOKEN_DATE).textValue()); } - - if (tree.isObject() && tree.has(TOKEN_REF)) { - return (T) JsiiEngine.getInstance().nativeFromObjRef(JsiiObjectRef.parse(tree)); + if (node.has(TOKEN_ENUM)) { + return jsiiEngine.findEnumValue(node.get(TOKEN_ENUM).textValue()); } - - if (tree.isObject() && tree.has(TOKEN_ENUM)) { - return (T) JsiiEngine.getInstance().findEnumValue(tree.get(TOKEN_ENUM).textValue()); + if (node.has(TOKEN_REF)) { + return jsiiEngine.nativeFromObjRef(JsiiObjectRef.parse(node)); } + } - // json type - if (ObjectNode.class.isAssignableFrom(type)) { - return (T) tree; - } + final JsonParser nodeParser = node.traverse(p.getCodec()); + nodeParser.nextToken(); + return standardDeserializer.deserialize(nodeParser, ctxt); + } - if (tree.isObject()) { - ObjectNode objectNode = (ObjectNode) tree; - Map map = new HashMap<>(); - Iterable fields = objectNode::fieldNames; - for (String field : fields) { - Object value = treeToValue(objectNode.get(field), Object.class); - map.put(field, value); - } - return (T) map; - } + @Override + public JsonDeserializer createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException { + if (this.standardDeserializer instanceof ContextualDeserializer) { + return new JsiiDeserializer(((ContextualDeserializer)this.standardDeserializer).createContextual(ctxt, property)); + } + return this; + } - return standardMapper.treeToValue(tree, type); + @Override + public void resolve(DeserializationContext ctxt) throws JsonMappingException { + if (this.standardDeserializer instanceof ResolvableDeserializer) { + ((ResolvableDeserializer)this.standardDeserializer).resolve(ctxt); + } + } + } + + public final class JsiiDeserializerModifier extends BeanDeserializerModifier { + @Override + public JsonDeserializer modifyDeserializer(DeserializationConfig config, + BeanDescription beanDesc, + JsonDeserializer deserializer) { + return new JsiiDeserializer(deserializer); } - /** - * Serializer for enum values. - */ - @SuppressWarnings("rawtypes") - private static class EnumSerializer extends JsonSerializer { - @Override - public void serialize(final Enum value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException { - Jsii jsii = tryGetJsiiAnnotation(value.getClass(), false); - if (jsii == null) { - throw new JsiiException("Cannot serialize non-jsii enums"); - } else { - gen.writeStartObject(); - gen.writeStringField(TOKEN_ENUM, jsii.fqn() + "/" + value.toString()); - gen.writeEndObject(); - } - } + @Override + public JsonDeserializer modifyEnumDeserializer(DeserializationConfig config, + JavaType type, + BeanDescription beanDesc, + JsonDeserializer deserializer) { + return new JsiiDeserializer(deserializer); } - /** - * Serializer for dates. - */ - private static class DateSerializer extends JsonSerializer { - @Override - public void serialize(final Instant value, final JsonGenerator gen, final SerializerProvider serializers) - throws IOException { - gen.writeStartObject(); - gen.writeStringField(TOKEN_DATE, value.toString()); - gen.writeEndObject(); - } + @Override + public JsonDeserializer modifyMapDeserializer(DeserializationConfig config, + MapType type, + BeanDescription beanDesc, + JsonDeserializer deserializer) { + return new JsiiDeserializer(deserializer); } - /** - * Serializer for classes that extend JsiiObject and any other class that implements a jsii interface. - * We use the JsiiSerializable interface as a way to identify "anything jsii-able". - */ - private static class JsiiSerializer extends JsonSerializer { - @Override - public void serialize(final JsiiSerializable o, - final JsonGenerator jsonGenerator, - final SerializerProvider serializerProvider) throws IOException { + @Override + public JsonDeserializer modifyMapLikeDeserializer(DeserializationConfig config, + MapLikeType type, + BeanDescription beanDesc, + JsonDeserializer deserializer) { + return new JsiiDeserializer(deserializer); + } + } + + /** + * Serializer for classes that extend JsiiObject and any other class that implements a jsii interface. + * We use the JsiiSerializable interface as a way to identify "anything jsii-able". + */ + private static final class JsiiSerializer extends JsonSerializer { + @Override + public void serialize(final JsiiSerializable o, + final JsonGenerator jsonGenerator, + final SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeTree(o.$jsii$toJson()); + } + } + + /** + * Serializer for enum values. + */ + @SuppressWarnings("rawtypes") + private static final class EnumSerializer extends JsonSerializer { + @Override + public void serialize(final Enum value, final JsonGenerator gen, final SerializerProvider serializers) throws IOException { + Jsii jsii = this.tryGetJsiiAnnotation(value.getClass(), false); + if (jsii == null) { + throw new JsiiException("Cannot serialize non-jsii enums"); + } else { + gen.writeStartObject(); + gen.writeStringField(TOKEN_ENUM, jsii.fqn() + "/" + value.toString()); + gen.writeEndObject(); + } + } - jsonGenerator.writeTree(o.$jsii$toJson()); - } + private Jsii tryGetJsiiAnnotation(final Class type, final boolean inherited) { + Jsii[] ann; + + if (inherited) { + ann = (Jsii[]) type.getAnnotationsByType(Jsii.class); + } else { + ann = (Jsii[]) type.getDeclaredAnnotationsByType(Jsii.class); + } + + if (ann.length == 0) { + return null; + } + + return ann[0]; + } + } + + /** + * Serializer for Instants. + */ + private static final class Instanterializer extends JsonSerializer { + @Override + public void serialize(final Instant value, final JsonGenerator gen, final SerializerProvider serializers) throws IOException { + gen.writeStartObject(); + gen.writeStringField(TOKEN_DATE, value.toString()); + gen.writeEndObject(); } + } } diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectRef.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectRef.java index 76d372211b..3fe7826e3c 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectRef.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiObjectRef.java @@ -91,4 +91,21 @@ public String getObjId() { public String toString() { return objId; } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || !(obj instanceof JsiiObjectRef)) { + return false; + } + final JsiiObjectRef other = (JsiiObjectRef) obj; + return this.objId.equals(other.objId); + } + + @Override + public int hashCode() { + return this.objId.hashCode(); + } } diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiRuntime.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiRuntime.java index f27d2d6121..9cd0755092 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiRuntime.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiRuntime.java @@ -3,7 +3,6 @@ import software.amazon.jsii.api.Callback; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -28,11 +27,6 @@ public final class JsiiRuntime { */ private static final String VERSION_BUILD_PART_REGEX = "\\+[a-z0-9]+$"; - /** - * JSON object mapper. - */ - private static final ObjectMapper OM = new ObjectMapper(); - /** * True to print server traces to STDERR. */ @@ -129,12 +123,7 @@ private JsonNode processCallbackResponse(final JsonNode resp) { throw new JsiiException("Cannot process callback since callbackHandler was not set"); } - Callback callback; - try { - callback = OM.treeToValue(resp.get("callback"), Callback.class); - } catch (JsonProcessingException e) { - throw new JsiiException(e); - } + Callback callback = JsiiObjectMapper.treeToValue(resp.get("callback"), Callback.class); JsonNode result = null; String error = null; @@ -222,7 +211,7 @@ private void startRuntimeIfNeeded() { if (traceEnabled) { pb.environment().put("JSII_DEBUG", "1"); } - + pb.environment().put("JSII_AGENT", "Java/" + System.getProperty("java.version")); try { @@ -282,7 +271,7 @@ JsonNode readNextResponse() { String error = this.stderr.lines().collect(Collectors.joining("\n\t")); throw new JsiiException("Child process exited unexpectedly: " + error); } - return OM.readTree(responseLine); + return JsiiObjectMapper.INSTANCE.readTree(responseLine); } catch (IOException e) { throw new JsiiException("Unable to read reply from jsii-runtime: " + e.toString(), e); } diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/InvokeRequest.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/InvokeRequest.java index 6381844459..3fd51a9c59 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/InvokeRequest.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/InvokeRequest.java @@ -1,5 +1,6 @@ package software.amazon.jsii.api; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import java.util.List; @@ -21,7 +22,7 @@ public class InvokeRequest { /** * Method arguments. */ - private List args; + private List args; /** * @return The object reference. @@ -54,14 +55,14 @@ public void setMethod(final String method) { /** * @return Method arguments. */ - public List getArgs() { + public List getArgs() { return args; } /** * @param args Method arguments. */ - public void setArgs(final List args) { + public void setArgs(final List args) { this.args = args; } } diff --git a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/SetRequest.java b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/SetRequest.java index 8849a2caa3..13dd37eafd 100644 --- a/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/SetRequest.java +++ b/packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/api/SetRequest.java @@ -19,7 +19,7 @@ public class SetRequest { /** * The new value. */ - private Object value; + private JsonNode value; /** * @return The jsii object reference. @@ -52,14 +52,14 @@ public void setProperty(final String property) { /** * @return The new value. */ - public Object getValue() { + public JsonNode getValue() { return value; } /** * @param value The new value. */ - public void setValue(final Object value) { + public void setValue(final JsonNode value) { this.value = value; } } diff --git a/packages/jsii-java-runtime/project/src/test/java/software/amazon/jsii/JsiiObjectMapperTest.java b/packages/jsii-java-runtime/project/src/test/java/software/amazon/jsii/JsiiObjectMapperTest.java new file mode 100644 index 0000000000..c12f129e6d --- /dev/null +++ b/packages/jsii-java-runtime/project/src/test/java/software/amazon/jsii/JsiiObjectMapperTest.java @@ -0,0 +1,131 @@ +package software.amazon.jsii; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.time.Instant; +import java.util.List; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Charsets; +import com.google.common.io.Resources; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public final class JsiiObjectMapperTest { + private JsiiEngine jsiiEngine; + private ObjectMapper subject; + + @BeforeEach + public void setUp() { + this.jsiiEngine = mock(JsiiEngine.class); + this.subject = new JsiiObjectMapper(jsiiEngine).getObjectMapper(); + } + + @AfterEach + public void cleanUp() { + this.jsiiEngine = null; + this.subject = null; + } + + @Test + public void testDeserialization() throws Exception { + final Object mockObject1 = new Object(); + when(jsiiEngine.nativeFromObjRef(JsiiObjectRef.fromObjId("module.Type@1"))).thenReturn(mockObject1); + + when((TestEnum) jsiiEngine.findEnumValue("module.Enum#value")).thenReturn(TestEnum.DUMMY); + + final String json = + Resources.toString(Resources.getResource(this.getClass(), "complex-callback.json"), Charsets.UTF_8); + final TestCallback callback = subject.treeToValue(subject.readTree(json), TestCallback.class); + + assertEquals("CallbackID", callback.getCbid()); + assertNotNull(callback.getInvoke()); + if (callback.getCbid() != null) { + assertEquals("methodName", callback.getInvoke().getMethod()); + assertEquals(1337, callback.getInvoke().getArgs().get(0)); + assertEquals(mockObject1, callback.getInvoke().getArgs().get(1)); + assertEquals(Instant.ofEpochMilli(1553624863569L), callback.getInvoke().getArgs().get(2)); + assertEquals(TestEnum.DUMMY, callback.getInvoke().getArgs().get(3)); + } + } + + @Test + public void testSerializationOfJsiiSerializables() throws Exception { + final String dummyValue = "{\"foo\":\"Bar\"}"; + final JsiiSerializable object = mock(JsiiSerializable.class); + when(object.$jsii$toJson()).thenReturn(new ObjectMapper().readTree(dummyValue)); + + final String json = subject.writeValueAsString(object); + + assertEquals(dummyValue, json); + } + + @Test + public void testSerializationOfInstant() throws Exception { + final Instant object = Instant.ofEpochMilli(1553691207095L); + + final String json = subject.writeValueAsString(object); + + assertEquals("{\"$jsii.date\":\"2019-03-27T12:53:27.095Z\"}", json); + } + + private static enum TestEnum { + DUMMY + } + + /** + * Kinda like the Callback object expcet it does not model stuff as JsonNodes, + * so we can verify the deserialization behaviour. + */ + public static final class TestCallback { + private String cbid; + + private TestInvokeRequest invoke; + + public String getCbid() { + return cbid; + } + + public void setCbid(String cbid) { + this.cbid = cbid; + } + + public TestInvokeRequest getInvoke() { + return invoke; + } + + public void setInvoke(TestInvokeRequest invoke) { + this.invoke = invoke; + } + } + + /** + * Kinda like the InvokeRequest, except it does not model anything as JsonNode, + * so we can test the deserialization behavior properly. + */ + public static final class TestInvokeRequest { + private String method; + + private List args; + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public List getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + } +} diff --git a/packages/jsii-java-runtime/project/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/packages/jsii-java-runtime/project/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..1f0955d450 --- /dev/null +++ b/packages/jsii-java-runtime/project/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/packages/jsii-java-runtime/project/src/test/resources/software/amazon/jsii/complex-callback.json b/packages/jsii-java-runtime/project/src/test/resources/software/amazon/jsii/complex-callback.json new file mode 100644 index 0000000000..8216ba356c --- /dev/null +++ b/packages/jsii-java-runtime/project/src/test/resources/software/amazon/jsii/complex-callback.json @@ -0,0 +1,12 @@ +{ + "cbid": "CallbackID", + "invoke": { + "method": "methodName", + "args": [ + 1337, + { "$jsii.byref": "module.Type@1" }, + { "$jsii.date": "2019-03-26T18:27:43.569Z" }, + { "$jsii.enum": "module.Enum#value" } + ] + } +} diff --git a/packages/jsii-kernel/lib/kernel.ts b/packages/jsii-kernel/lib/kernel.ts index d76fafe0ce..c262a00532 100644 --- a/packages/jsii-kernel/lib/kernel.ts +++ b/packages/jsii-kernel/lib/kernel.ts @@ -768,7 +768,7 @@ export class Kernel { throw new Error(`Module '${moduleName}' not found`); } - const types = assembly.metadata.types || {}; + const types = assembly.metadata.types || {}; const fqnInfo = types[fqn]; if (!fqnInfo) { throw new Error(`Type '${fqn}' not found`); @@ -1074,4 +1074,4 @@ function mapSource(err: Error, sourceMaps: { [assm: string]: SourceMapConsumer } } } -const ANY_TYPE: spec.PrimitiveTypeReference = { primitive: spec.PrimitiveType.Any }; \ No newline at end of file +const ANY_TYPE: spec.PrimitiveTypeReference = { primitive: spec.PrimitiveType.Any }; diff --git a/packages/jsii-kernel/lib/objects.ts b/packages/jsii-kernel/lib/objects.ts index 0801b1d1e6..4d0a6a17be 100644 --- a/packages/jsii-kernel/lib/objects.ts +++ b/packages/jsii-kernel/lib/objects.ts @@ -89,6 +89,11 @@ export class ObjectTable { throw new Error('FQN cannot be undefined'); } + const existingRef = objectReference(obj); + if (existingRef) { + return existingRef; + } + const objid = this.makeId(fqn); this.objects[objid] = { instance: obj, fqn }; tagObject(obj, objid); @@ -132,4 +137,4 @@ export class ObjectTable { export interface RegisteredObject { instance: any; fqn: string; -} \ No newline at end of file +} diff --git a/packages/jsii-kernel/test/test.kernel.ts b/packages/jsii-kernel/test/test.kernel.ts index 9b34419021..1bae70b6b5 100644 --- a/packages/jsii-kernel/test/test.kernel.ts +++ b/packages/jsii-kernel/test/test.kernel.ts @@ -1090,6 +1090,28 @@ defineTest('can set and retrieve union properties', async (test, sandbox) => { test.equal(get(sandbox, unionArray[1])('value'), 33); }); +defineTest('Object ID does not get re-allocated when the constructor passes "this" out', async (test, sandbox) => { + sandbox.callbackHandler = makeSyncCallbackHandler((callback) => { + test.equal(callback.invoke && callback.invoke.method, 'consumePartiallyInitializedThis'); + test.deepEqual(callback.invoke && callback.invoke.args && callback.invoke.args, [{ + [api.TOKEN_REF]: 'jsii-calc.ConstructorPassesThisOut@10001' + }, { + [api.TOKEN_DATE]: '1970-01-01T00:00:00.000Z' + }, { + [api.TOKEN_ENUM]: 'jsii-calc.AllTypesEnum/ThisIsGreat' + }]); + return 'OK'; + }); + const reflector = sandbox.create({ + fqn: 'jsii-calc.PartiallyInitializedThisConsumer', + overrides: [{ method: 'consumePartiallyInitializedThis' }] + }); + test.equal(reflector[api.TOKEN_REF], 'jsii-calc.PartiallyInitializedThisConsumer@10000'); + + const classRef = sandbox.create({ fqn: 'jsii-calc.ConstructorPassesThisOut', args: [reflector] }); + test.equal(classRef[api.TOKEN_REF], 'jsii-calc.ConstructorPassesThisOut@10001'); +}); + // ================================================================================================= const testNames: { [name: string]: boolean } = { }; diff --git a/packages/jsii-pacmak/lib/generator.ts b/packages/jsii-pacmak/lib/generator.ts index f038dd432e..c5a8ef8df9 100644 --- a/packages/jsii-pacmak/lib/generator.ts +++ b/packages/jsii-pacmak/lib/generator.ts @@ -252,7 +252,7 @@ export abstract class Generator implements IGenerator { this.addAbstractPostfixToClassName(classSpec); } this.onBeginClass(classSpec, abstract); - this.visitClass(classSpec, abstract); + this.visitClass(classSpec); visitChildren(); this.onEndClass(classSpec); break; @@ -360,9 +360,9 @@ export abstract class Generator implements IGenerator { } } - private visitClass(cls: spec.ClassType, abstract: boolean | undefined) { + private visitClass(cls: spec.ClassType) { let initializer = cls.initializer; - if (!abstract && initializer) { + if (initializer) { this.onInitializer(cls, initializer); diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index 6c2fdc17db..8422cfdd53 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -804,7 +804,7 @@ class JavaGenerator extends Generator { // emit $jsii$toJson which will be called to serialize this object when sent to JS this.code.line(); this.code.openBlock(`public com.fasterxml.jackson.databind.JsonNode $jsii$toJson()`); - this.code.line(`software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance;`); + this.code.line(`com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE;`); // tslint:disable-next-line:max-line-length this.code.line(`com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode();`); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/Base.java b/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/Base.java index 7a64b8e3d7..aa712c99bf 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/Base.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/Base.java @@ -9,6 +9,10 @@ public abstract class Base extends software.amazon.jsii.JsiiObject { protected Base(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + public Base() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } /** * @return the name of the class (to verify native type names are created for derived classes). diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/BaseProps.java b/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/BaseProps.java index 3a7e75c7c1..ada23728e0 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/BaseProps.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/java/src/main/java/software/amazon/jsii/tests/calculator/base/BaseProps.java @@ -58,7 +58,7 @@ public software.amazon.jsii.tests.calculator.baseofbase.Very getFoo() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("bar", om.valueToTree(this.getBar())); obj.set("foo", om.valueToTree(this.getFoo())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/MyFirstStruct.java b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/MyFirstStruct.java index a78ea35ce8..0fd8d95830 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/MyFirstStruct.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/MyFirstStruct.java @@ -87,7 +87,7 @@ public java.util.List getFirstOptional() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("anumber", om.valueToTree(this.getAnumber())); obj.set("astring", om.valueToTree(this.getAstring())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Operation.java b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Operation.java index 2ae2a27035..b689b90d26 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Operation.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Operation.java @@ -9,6 +9,10 @@ public abstract class Operation extends software.amazon.jsii.tests.calculator.li protected Operation(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + public Operation() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } /** * String representation of the value. diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/StructWithOnlyOptionals.java b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/StructWithOnlyOptionals.java index 7eecb3e01a..87ac4d7100 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/StructWithOnlyOptionals.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/StructWithOnlyOptionals.java @@ -88,7 +88,7 @@ public java.lang.Boolean getOptional3() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("optional1", om.valueToTree(this.getOptional1())); obj.set("optional2", om.valueToTree(this.getOptional2())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Value.java b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Value.java index 16b9db138a..21ce8bdd18 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Value.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/src/main/java/software/amazon/jsii/tests/calculator/lib/Value.java @@ -9,6 +9,10 @@ public abstract class Value extends software.amazon.jsii.tests.calculator.base.B protected Value(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + public Value() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } /** * String representation of the value. 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 20fac29cd7..dc9f5f0401 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 @@ -84,6 +84,30 @@ }, "version": "0.8.0" }, + "@scope/jsii-calc-base-of-base": { + "peer": true, + "targets": { + "dotnet": { + "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", + "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" + }, + "java": { + "maven": { + "artifactId": "calculator-base-of-base", + "groupId": "software.amazon.jsii.tests" + }, + "package": "software.amazon.jsii.tests.calculator.baseofbase" + }, + "js": { + "npm": "@scope/jsii-calc-base-of-base" + }, + "python": { + "distName": "scope.jsii-calc-base-of-base", + "module": "scope.jsii_calc_base_of_base" + } + }, + "version": "0.8.0" + }, "@scope/jsii-calc-lib": { "dependencies": { "@scope/jsii-calc-base": { @@ -1250,6 +1274,23 @@ } ] }, + "jsii-calc.ConstructorPassesThisOut": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.ConstructorPassesThisOut", + "initializer": { + "initializer": true, + "parameters": [ + { + "name": "consumer", + "type": { + "fqn": "jsii-calc.PartiallyInitializedThisConsumer" + } + } + ] + }, + "kind": "class", + "name": "ConstructorPassesThisOut" + }, "jsii-calc.Constructors": { "assembly": "jsii-calc", "fqn": "jsii-calc.Constructors", @@ -3327,6 +3368,45 @@ ], "name": "OverrideReturnsObject" }, + "jsii-calc.PartiallyInitializedThisConsumer": { + "abstract": true, + "assembly": "jsii-calc", + "fqn": "jsii-calc.PartiallyInitializedThisConsumer", + "initializer": { + "initializer": true + }, + "kind": "class", + "methods": [ + { + "abstract": true, + "name": "consumePartiallyInitializedThis", + "parameters": [ + { + "name": "obj", + "type": { + "fqn": "jsii-calc.ConstructorPassesThisOut" + } + }, + { + "name": "dt", + "type": { + "primitive": "date" + } + }, + { + "name": "ev", + "type": { + "fqn": "jsii-calc.AllTypesEnum" + } + } + ], + "returns": { + "primitive": "string" + } + } + ], + "name": "PartiallyInitializedThisConsumer" + }, "jsii-calc.Polymorphism": { "assembly": "jsii-calc", "fqn": "jsii-calc.Polymorphism", @@ -4500,5 +4580,5 @@ } }, "version": "0.8.0", - "fingerprint": "WIFIhqgEwUDjCsDr7gliujhqcKZQSkDP+NstBfmdvZU=" + "fingerprint": "J0bhm0cu1dlTAyMfBlAMWCVXZf6e8k2pHkmxye6P7Wk=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj index bca205b843..88e65f9c6c 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj @@ -19,6 +19,7 @@ + diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ConstructorPassesThisOut.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ConstructorPassesThisOut.cs new file mode 100644 index 0000000000..e31c3513f0 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ConstructorPassesThisOut.cs @@ -0,0 +1,20 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiClass(typeof(ConstructorPassesThisOut), "jsii-calc.ConstructorPassesThisOut", "[{\"name\":\"consumer\",\"type\":{\"fqn\":\"jsii-calc.PartiallyInitializedThisConsumer\"}}]")] + public class ConstructorPassesThisOut : DeputyBase + { + public ConstructorPassesThisOut(PartiallyInitializedThisConsumer consumer): base(new DeputyProps(new object[]{consumer})) + { + } + + protected ConstructorPassesThisOut(ByRefValue reference): base(reference) + { + } + + protected ConstructorPassesThisOut(DeputyProps props): base(props) + { + } + } +} \ 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/Internal/DependencyResolution/Anchor.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/Internal/DependencyResolution/Anchor.cs index af4f74d979..d7d966706c 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/Internal/DependencyResolution/Anchor.cs +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/Internal/DependencyResolution/Anchor.cs @@ -5,6 +5,7 @@ public class Anchor public Anchor() { new Amazon.JSII.Tests.CalculatorNamespace.BaseNamespace.Internal.DependencyResolution.Anchor(); + new Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace.Internal.DependencyResolution.Anchor(); new Amazon.JSII.Tests.CalculatorNamespace.LibNamespace.Internal.DependencyResolution.Anchor(); } } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/PartiallyInitializedThisConsumer.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/PartiallyInitializedThisConsumer.cs new file mode 100644 index 0000000000..f578f5321f --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/PartiallyInitializedThisConsumer.cs @@ -0,0 +1,24 @@ +using Amazon.JSII.Runtime.Deputy; +using System; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiClass(typeof(PartiallyInitializedThisConsumer), "jsii-calc.PartiallyInitializedThisConsumer", "[]")] + public abstract class PartiallyInitializedThisConsumer : DeputyBase + { + protected PartiallyInitializedThisConsumer(): base(new DeputyProps(new object[]{})) + { + } + + protected PartiallyInitializedThisConsumer(ByRefValue reference): base(reference) + { + } + + protected PartiallyInitializedThisConsumer(DeputyProps props): base(props) + { + } + + [JsiiMethod("consumePartiallyInitializedThis", "{\"primitive\":\"string\"}", "[{\"name\":\"obj\",\"type\":{\"fqn\":\"jsii-calc.ConstructorPassesThisOut\"}},{\"name\":\"dt\",\"type\":{\"primitive\":\"date\"}},{\"name\":\"ev\",\"type\":{\"fqn\":\"jsii-calc.AllTypesEnum\"}}]")] + public abstract string ConsumePartiallyInitializedThis(ConstructorPassesThisOut obj, DateTime dt, AllTypesEnum ev); + } +} \ 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/PartiallyInitializedThisConsumerProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/PartiallyInitializedThisConsumerProxy.cs new file mode 100644 index 0000000000..2ebb268de0 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/PartiallyInitializedThisConsumerProxy.cs @@ -0,0 +1,19 @@ +using Amazon.JSII.Runtime.Deputy; +using System; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiTypeProxy(typeof(PartiallyInitializedThisConsumer), "jsii-calc.PartiallyInitializedThisConsumer")] + internal sealed class PartiallyInitializedThisConsumerProxy : PartiallyInitializedThisConsumer + { + private PartiallyInitializedThisConsumerProxy(ByRefValue reference): base(reference) + { + } + + [JsiiMethod("consumePartiallyInitializedThis", "{\"primitive\":\"string\"}", "[{\"name\":\"obj\",\"type\":{\"fqn\":\"jsii-calc.ConstructorPassesThisOut\"}},{\"name\":\"dt\",\"type\":{\"primitive\":\"date\"}},{\"name\":\"ev\",\"type\":{\"fqn\":\"jsii-calc.AllTypesEnum\"}}]")] + public override string ConsumePartiallyInitializedThis(ConstructorPassesThisOut obj, DateTime dt, AllTypesEnum ev) + { + return InvokeInstanceMethod(new object[]{obj, dt, ev}); + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml b/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml index 37ffffcdd2..6d9f336cfd 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml @@ -60,12 +60,12 @@ 0.8.0 - calculator-lib + calculator-base-of-base software.amazon.jsii.tests 0.8.0 - calculator-base-of-base + calculator-lib software.amazon.jsii.tests 0.8.0 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 770fbe051a..f780997301 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 @@ -12,7 +12,7 @@ public final class $Module extends JsiiModule { @Override public List> getDependencies() { - return asList(software.amazon.jsii.tests.calculator.base.$Module.class, software.amazon.jsii.tests.calculator.lib.$Module.class); + return asList(software.amazon.jsii.tests.calculator.base.$Module.class, software.amazon.jsii.tests.calculator.baseofbase.$Module.class, software.amazon.jsii.tests.calculator.lib.$Module.class); } @Override @@ -34,6 +34,7 @@ protected Class resolveClass(final String fqn) throws ClassNotFoundException case "jsii-calc.ClassThatImplementsThePrivateInterface": return software.amazon.jsii.tests.calculator.ClassThatImplementsThePrivateInterface.class; case "jsii-calc.ClassWithMutableObjectLiteralProperty": return software.amazon.jsii.tests.calculator.ClassWithMutableObjectLiteralProperty.class; case "jsii-calc.ClassWithPrivateConstructorAndAutomaticProperties": return software.amazon.jsii.tests.calculator.ClassWithPrivateConstructorAndAutomaticProperties.class; + case "jsii-calc.ConstructorPassesThisOut": return software.amazon.jsii.tests.calculator.ConstructorPassesThisOut.class; case "jsii-calc.Constructors": return software.amazon.jsii.tests.calculator.Constructors.class; case "jsii-calc.ConsumersOfThisCrazyTypeSystem": return software.amazon.jsii.tests.calculator.ConsumersOfThisCrazyTypeSystem.class; case "jsii-calc.DefaultedConstructorArgument": return software.amazon.jsii.tests.calculator.DefaultedConstructorArgument.class; @@ -92,6 +93,7 @@ protected Class resolveClass(final String fqn) throws ClassNotFoundException case "jsii-calc.ObjectRefsInCollections": return software.amazon.jsii.tests.calculator.ObjectRefsInCollections.class; case "jsii-calc.OptionalConstructorArgument": return software.amazon.jsii.tests.calculator.OptionalConstructorArgument.class; case "jsii-calc.OverrideReturnsObject": return software.amazon.jsii.tests.calculator.OverrideReturnsObject.class; + case "jsii-calc.PartiallyInitializedThisConsumer": return software.amazon.jsii.tests.calculator.PartiallyInitializedThisConsumer.class; 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.PublicClass": return software.amazon.jsii.tests.calculator.PublicClass.class; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClass.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClass.java index 97e11233a7..78061b7876 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClass.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClass.java @@ -6,6 +6,10 @@ public abstract class AbstractClass extends software.amazon.jsii.tests.calculato protected AbstractClass(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + public AbstractClass() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } public abstract java.lang.String abstractMethod(final java.lang.String name); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClassBase.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClassBase.java index 15756d5fb6..381fb205c6 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClassBase.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/AbstractClassBase.java @@ -6,6 +6,10 @@ public abstract class AbstractClassBase extends software.amazon.jsii.JsiiObject protected AbstractClassBase(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + public AbstractClassBase() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } public java.lang.String getAbstractProperty() { return this.jsiiGet("abstractProperty", java.lang.String.class); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/BinaryOperation.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/BinaryOperation.java index c75105c770..a2f38995bc 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/BinaryOperation.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/BinaryOperation.java @@ -9,6 +9,15 @@ public abstract class BinaryOperation extends software.amazon.jsii.tests.calcula protected BinaryOperation(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + /** + * Creates a BinaryOperation + * @param lhs Left-hand side operand + * @param rhs Right-hand side operand + */ + public BinaryOperation(final software.amazon.jsii.tests.calculator.lib.Value lhs, final software.amazon.jsii.tests.calculator.lib.Value rhs) { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this, java.util.stream.Stream.concat(java.util.stream.Stream.of(java.util.Objects.requireNonNull(lhs, "lhs is required")), java.util.stream.Stream.of(java.util.Objects.requireNonNull(rhs, "rhs is required"))).toArray()); + } /** * Say hello! diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/CalculatorProps.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/CalculatorProps.java index b338d7a347..b965bc1b48 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/CalculatorProps.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/CalculatorProps.java @@ -66,7 +66,7 @@ public java.lang.Number getMaximumValue() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("initialValue", om.valueToTree(this.getInitialValue())); obj.set("maximumValue", om.valueToTree(this.getMaximumValue())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ConstructorPassesThisOut.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ConstructorPassesThisOut.java new file mode 100644 index 0000000000..0090358fca --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ConstructorPassesThisOut.java @@ -0,0 +1,13 @@ +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.ConstructorPassesThisOut") +public class ConstructorPassesThisOut extends software.amazon.jsii.JsiiObject { + protected ConstructorPassesThisOut(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + public ConstructorPassesThisOut(final software.amazon.jsii.tests.calculator.PartiallyInitializedThisConsumer consumer) { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this, java.util.stream.Stream.of(java.util.Objects.requireNonNull(consumer, "consumer is required")).toArray()); + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/DerivedStruct.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/DerivedStruct.java index 3521a946d2..9e0a7ef4a8 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/DerivedStruct.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/DerivedStruct.java @@ -192,7 +192,7 @@ public java.util.List getFirstOptional() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("anotherRequired", om.valueToTree(this.getAnotherRequired())); obj.set("bool", om.valueToTree(this.getBool())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/EraseUndefinedHashValuesOptions.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/EraseUndefinedHashValuesOptions.java index 5679345465..6c3d314d83 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/EraseUndefinedHashValuesOptions.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/EraseUndefinedHashValuesOptions.java @@ -63,7 +63,7 @@ public java.lang.String getOption2() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("option1", om.valueToTree(this.getOption1())); obj.set("option2", om.valueToTree(this.getOption2())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsInternalInterface.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsInternalInterface.java index 2dd56d0f9e..2147ac9850 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsInternalInterface.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsInternalInterface.java @@ -42,7 +42,7 @@ public java.lang.Boolean getBoom() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("boom", om.valueToTree(this.getBoom())); return obj; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsPrivateInterface.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsPrivateInterface.java index ddddccb47e..a54e9c9b96 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsPrivateInterface.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ExtendsPrivateInterface.java @@ -42,7 +42,7 @@ public java.util.List getMoreThings() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("moreThings", om.valueToTree(this.getMoreThings())); return obj; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ImplictBaseOfBase.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ImplictBaseOfBase.java index 81e1bd0256..7467b51816 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ImplictBaseOfBase.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ImplictBaseOfBase.java @@ -74,7 +74,7 @@ public software.amazon.jsii.tests.calculator.baseofbase.Very getFoo() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("goo", om.valueToTree(this.getGoo())); obj.set("bar", om.valueToTree(this.getBar())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceImplementedByAbstractClass.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceImplementedByAbstractClass.java index 7a86e32bdf..2d82ab4fda 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceImplementedByAbstractClass.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceImplementedByAbstractClass.java @@ -46,7 +46,7 @@ public java.lang.String getPropFromInterface() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("propFromInterface", om.valueToTree(this.getPropFromInterface())); return obj; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceIncludesClasses/Hello.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceIncludesClasses/Hello.java index 5be456c296..df4d2c11a9 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceIncludesClasses/Hello.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceIncludesClasses/Hello.java @@ -42,7 +42,7 @@ public java.lang.Number getFoo() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("foo", om.valueToTree(this.getFoo())); return obj; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceOnlyInterface/Hello.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceOnlyInterface/Hello.java index 16c645adbf..cd5d24e776 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceOnlyInterface/Hello.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/InterfaceInNamespaceOnlyInterface/Hello.java @@ -42,7 +42,7 @@ public java.lang.Number getFoo() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("foo", om.valueToTree(this.getFoo())); return obj; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/LoadBalancedFargateServiceProps.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/LoadBalancedFargateServiceProps.java index dd8791035c..39ce1d3ac4 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/LoadBalancedFargateServiceProps.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/LoadBalancedFargateServiceProps.java @@ -189,7 +189,7 @@ public java.lang.Boolean getPublicTasks() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("containerPort", om.valueToTree(this.getContainerPort())); obj.set("cpu", om.valueToTree(this.getCpu())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/NullShouldBeTreatedAsUndefinedData.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/NullShouldBeTreatedAsUndefinedData.java index bdef5fc26a..ec17387884 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/NullShouldBeTreatedAsUndefinedData.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/NullShouldBeTreatedAsUndefinedData.java @@ -61,7 +61,7 @@ public java.lang.Object getThisShouldBeUndefined() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("arrayWithThreeElementsAndUndefinedAsSecondArgument", om.valueToTree(this.getArrayWithThreeElementsAndUndefinedAsSecondArgument())); obj.set("thisShouldBeUndefined", om.valueToTree(this.getThisShouldBeUndefined())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/PartiallyInitializedThisConsumer.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/PartiallyInitializedThisConsumer.java new file mode 100644 index 0000000000..744968b276 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/PartiallyInitializedThisConsumer.java @@ -0,0 +1,29 @@ +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.PartiallyInitializedThisConsumer") +public abstract class PartiallyInitializedThisConsumer extends software.amazon.jsii.JsiiObject { + protected PartiallyInitializedThisConsumer(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + public PartiallyInitializedThisConsumer() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } + + public abstract java.lang.String consumePartiallyInitializedThis(final software.amazon.jsii.tests.calculator.ConstructorPassesThisOut obj, final java.time.Instant dt, final software.amazon.jsii.tests.calculator.AllTypesEnum ev); + + /** + * A proxy class which represents a concrete javascript instance of this type. + */ + final static class Jsii$Proxy extends software.amazon.jsii.tests.calculator.PartiallyInitializedThisConsumer { + protected Jsii$Proxy(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + + @Override + public java.lang.String consumePartiallyInitializedThis(final software.amazon.jsii.tests.calculator.ConstructorPassesThisOut obj, final java.time.Instant dt, final software.amazon.jsii.tests.calculator.AllTypesEnum ev) { + return this.jsiiCall("consumePartiallyInitializedThis", java.lang.String.class, java.util.stream.Stream.concat(java.util.stream.Stream.concat(java.util.stream.Stream.of(java.util.Objects.requireNonNull(obj, "obj is required")), java.util.stream.Stream.of(java.util.Objects.requireNonNull(dt, "dt is required"))), java.util.stream.Stream.of(java.util.Objects.requireNonNull(ev, "ev is required"))).toArray()); + } + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnaryOperation.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnaryOperation.java index 546cec81e7..2ffb511e1e 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnaryOperation.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnaryOperation.java @@ -9,6 +9,10 @@ public abstract class UnaryOperation extends software.amazon.jsii.tests.calculat protected UnaryOperation(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + public UnaryOperation(final software.amazon.jsii.tests.calculator.lib.Value operand) { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this, java.util.stream.Stream.of(java.util.Objects.requireNonNull(operand, "operand is required")).toArray()); + } public software.amazon.jsii.tests.calculator.lib.Value getOperand() { return this.jsiiGet("operand", software.amazon.jsii.tests.calculator.lib.Value.class); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnionProperties.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnionProperties.java index ff141b54da..03d9389fc2 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnionProperties.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/UnionProperties.java @@ -88,7 +88,7 @@ public java.lang.Object getFoo() { } public com.fasterxml.jackson.databind.JsonNode $jsii$toJson() { - software.amazon.jsii.JsiiObjectMapper om = software.amazon.jsii.JsiiObjectMapper.instance; + com.fasterxml.jackson.databind.ObjectMapper om = software.amazon.jsii.JsiiObjectMapper.INSTANCE; com.fasterxml.jackson.databind.node.ObjectNode obj = com.fasterxml.jackson.databind.node.JsonNodeFactory.instance.objectNode(); obj.set("bar", om.valueToTree(this.getBar())); obj.set("foo", om.valueToTree(this.getFoo())); diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/composition/CompositeOperation.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/composition/CompositeOperation.java index 95d5a79bc7..c85dbb5b21 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/composition/CompositeOperation.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/composition/CompositeOperation.java @@ -9,6 +9,10 @@ public abstract class CompositeOperation extends software.amazon.jsii.tests.calc protected CompositeOperation(final software.amazon.jsii.JsiiObject.InitializationMode mode) { super(mode); } + public CompositeOperation() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } /** * String representation of the value. diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py b/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py index 0372a8337b..cc6eee5749 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py @@ -32,6 +32,7 @@ "jsii", "publication>=0.0.3", "scope.jsii-calc-base~=0.8.0", + "scope.jsii-calc-base-of-base~=0.8.0", "scope.jsii-calc-lib~=0.8.0" ] } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py index 3db9cadad7..8b9b0c3b50 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/__init__.py @@ -10,6 +10,7 @@ from jsii.python import classproperty import scope.jsii_calc_base +import scope.jsii_calc_base_of_base import scope.jsii_calc_lib __jsii_assembly__ = jsii.JSIIAssembly.load("jsii-calc", "0.8.0", __name__, "jsii-calc@0.8.0.jsii.tgz") class AbstractClassBase(metaclass=jsii.JSIIAbstractClass, jsii_type="jsii-calc.AbstractClassBase"): @@ -365,6 +366,11 @@ def mutable_object(self, value: "IMutableObjectLiteral"): return jsii.set(self, "mutableObject", value) +class ConstructorPassesThisOut(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.ConstructorPassesThisOut"): + def __init__(self, consumer: "PartiallyInitializedThisConsumer") -> None: + jsii.create(ConstructorPassesThisOut, self, [consumer]) + + class Constructors(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.Constructors"): def __init__(self) -> None: jsii.create(Constructors, self, []) @@ -1643,6 +1649,26 @@ def test(self, obj: "IReturnsNumber") -> jsii.Number: return jsii.invoke(self, "test", [obj]) +class PartiallyInitializedThisConsumer(metaclass=jsii.JSIIAbstractClass, jsii_type="jsii-calc.PartiallyInitializedThisConsumer"): + @staticmethod + def __jsii_proxy_class__(): + return _PartiallyInitializedThisConsumerProxy + + def __init__(self) -> None: + jsii.create(PartiallyInitializedThisConsumer, self, []) + + @jsii.member(jsii_name="consumePartiallyInitializedThis") + @abc.abstractmethod + def consume_partially_initialized_this(self, obj: "ConstructorPassesThisOut", dt: datetime.datetime, ev: "AllTypesEnum") -> str: + ... + + +class _PartiallyInitializedThisConsumerProxy(PartiallyInitializedThisConsumer): + @jsii.member(jsii_name="consumePartiallyInitializedThis") + def consume_partially_initialized_this(self, obj: "ConstructorPassesThisOut", dt: datetime.datetime, ev: "AllTypesEnum") -> str: + return jsii.invoke(self, "consumePartiallyInitializedThis", [obj, dt, ev]) + + class Polymorphism(metaclass=jsii.JSIIMeta, jsii_type="jsii-calc.Polymorphism"): def __init__(self) -> None: jsii.create(Polymorphism, self, []) @@ -2351,6 +2377,6 @@ def parts(self, value: typing.List[scope.jsii_calc_lib.Value]): return jsii.set(self, "parts", value) -__all__ = ["AbstractClass", "AbstractClassBase", "AbstractClassReturner", "Add", "AllTypes", "AllTypesEnum", "AllowedMethodNames", "AsyncVirtualMethods", "AugmentableClass", "BinaryOperation", "Calculator", "CalculatorProps", "ClassThatImplementsTheInternalInterface", "ClassThatImplementsThePrivateInterface", "ClassWithMutableObjectLiteralProperty", "ClassWithPrivateConstructorAndAutomaticProperties", "Constructors", "ConsumersOfThisCrazyTypeSystem", "DefaultedConstructorArgument", "DerivedClassHasNoProperties", "DerivedStruct", "DoNotOverridePrivates", "DoNotRecognizeAnyAsOptional", "DontComplainAboutVariadicAfterOptional", "DoubleTrouble", "EraseUndefinedHashValues", "EraseUndefinedHashValuesOptions", "ExportedBaseClass", "ExtendsInternalInterface", "ExtendsPrivateInterface", "GiveMeStructs", "GreetingAugmenter", "IAnotherPublicInterface", "IFriendlier", "IFriendlyRandomGenerator", "IInterfaceThatShouldNotBeADataType", "IInterfaceWithInternal", "IInterfaceWithMethods", "IInterfaceWithOptionalMethodArguments", "IInterfaceWithProperties", "IInterfaceWithPropertiesExtension", "IMutableObjectLiteral", "INonInternalInterface", "IPrivatelyImplemented", "IPublicInterface", "IPublicInterface2", "IRandomNumberGenerator", "IReturnsNumber", "ImplementInternalInterface", "ImplementsInterfaceWithInternal", "ImplementsInterfaceWithInternalSubclass", "ImplementsPrivateInterface", "ImplictBaseOfBase", "InbetweenClass", "InterfaceImplementedByAbstractClass", "InterfaceInNamespaceIncludesClasses", "InterfaceInNamespaceOnlyInterface", "JSObjectLiteralForInterface", "JSObjectLiteralToNative", "JSObjectLiteralToNativeClass", "JavaReservedWords", "JsiiAgent", "LoadBalancedFargateServiceProps", "Multiply", "Negate", "NodeStandardLibrary", "NullShouldBeTreatedAsUndefined", "NullShouldBeTreatedAsUndefinedData", "NumberGenerator", "ObjectRefsInCollections", "OptionalConstructorArgument", "OverrideReturnsObject", "Polymorphism", "Power", "PublicClass", "PythonReservedWords", "ReferenceEnumFromScopedPackage", "ReturnsPrivateImplementationOfInterface", "RuntimeTypeChecking", "SingleInstanceTwoTypes", "Statics", "StringEnum", "StripInternal", "Sum", "SyncVirtualMethods", "Thrower", "UnaryOperation", "UnionProperties", "UseBundledDependency", "UseCalcBase", "UsesInterfaceWithProperties", "VariadicMethod", "VirtualMethodPlayground", "__jsii_assembly__", "composition"] +__all__ = ["AbstractClass", "AbstractClassBase", "AbstractClassReturner", "Add", "AllTypes", "AllTypesEnum", "AllowedMethodNames", "AsyncVirtualMethods", "AugmentableClass", "BinaryOperation", "Calculator", "CalculatorProps", "ClassThatImplementsTheInternalInterface", "ClassThatImplementsThePrivateInterface", "ClassWithMutableObjectLiteralProperty", "ClassWithPrivateConstructorAndAutomaticProperties", "ConstructorPassesThisOut", "Constructors", "ConsumersOfThisCrazyTypeSystem", "DefaultedConstructorArgument", "DerivedClassHasNoProperties", "DerivedStruct", "DoNotOverridePrivates", "DoNotRecognizeAnyAsOptional", "DontComplainAboutVariadicAfterOptional", "DoubleTrouble", "EraseUndefinedHashValues", "EraseUndefinedHashValuesOptions", "ExportedBaseClass", "ExtendsInternalInterface", "ExtendsPrivateInterface", "GiveMeStructs", "GreetingAugmenter", "IAnotherPublicInterface", "IFriendlier", "IFriendlyRandomGenerator", "IInterfaceThatShouldNotBeADataType", "IInterfaceWithInternal", "IInterfaceWithMethods", "IInterfaceWithOptionalMethodArguments", "IInterfaceWithProperties", "IInterfaceWithPropertiesExtension", "IMutableObjectLiteral", "INonInternalInterface", "IPrivatelyImplemented", "IPublicInterface", "IPublicInterface2", "IRandomNumberGenerator", "IReturnsNumber", "ImplementInternalInterface", "ImplementsInterfaceWithInternal", "ImplementsInterfaceWithInternalSubclass", "ImplementsPrivateInterface", "ImplictBaseOfBase", "InbetweenClass", "InterfaceImplementedByAbstractClass", "InterfaceInNamespaceIncludesClasses", "InterfaceInNamespaceOnlyInterface", "JSObjectLiteralForInterface", "JSObjectLiteralToNative", "JSObjectLiteralToNativeClass", "JavaReservedWords", "JsiiAgent", "LoadBalancedFargateServiceProps", "Multiply", "Negate", "NodeStandardLibrary", "NullShouldBeTreatedAsUndefined", "NullShouldBeTreatedAsUndefinedData", "NumberGenerator", "ObjectRefsInCollections", "OptionalConstructorArgument", "OverrideReturnsObject", "PartiallyInitializedThisConsumer", "Polymorphism", "Power", "PublicClass", "PythonReservedWords", "ReferenceEnumFromScopedPackage", "ReturnsPrivateImplementationOfInterface", "RuntimeTypeChecking", "SingleInstanceTwoTypes", "Statics", "StringEnum", "StripInternal", "Sum", "SyncVirtualMethods", "Thrower", "UnaryOperation", "UnionProperties", "UseBundledDependency", "UseCalcBase", "UsesInterfaceWithProperties", "VariadicMethod", "VirtualMethodPlayground", "__jsii_assembly__", "composition"] publication.publish() diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/_jsii/__init__.py b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/_jsii/__init__.py index 90f4bfb6dc..565b8a9c38 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/_jsii/__init__.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/src/jsii_calc/_jsii/__init__.py @@ -10,6 +10,7 @@ from jsii.python import classproperty import scope.jsii_calc_base +import scope.jsii_calc_base_of_base import scope.jsii_calc_lib __all__ = [] 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 a88becce56..004982f54a 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 @@ -1258,6 +1258,36 @@ ClassWithPrivateConstructorAndAutomaticProperties :type: string +ConstructorPassesThisOut +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:class:: ConstructorPassesThisOut(consumer) + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.ConstructorPassesThisOut; + + .. code-tab:: javascript + + const { ConstructorPassesThisOut } = require('jsii-calc'); + + .. code-tab:: typescript + + import { ConstructorPassesThisOut } from 'jsii-calc'; + + + + :param consumer: + :type consumer: :py:class:`~jsii-calc.PartiallyInitializedThisConsumer`\ + Constructors ^^^^^^^^^^^^ @@ -4253,6 +4283,47 @@ OverrideReturnsObject :rtype: number +PartiallyInitializedThisConsumer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:class:: PartiallyInitializedThisConsumer() + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.PartiallyInitializedThisConsumer; + + .. code-tab:: javascript + + const { PartiallyInitializedThisConsumer } = require('jsii-calc'); + + .. code-tab:: typescript + + import { PartiallyInitializedThisConsumer } from 'jsii-calc'; + + + + :abstract: Yes + + .. py:method:: consumePartiallyInitializedThis(obj, dt, ev) -> string + + :param obj: + :type obj: :py:class:`~jsii-calc.ConstructorPassesThisOut`\ + :param dt: + :type dt: date + :param ev: + :type ev: :py:class:`~jsii-calc.AllTypesEnum`\ + :rtype: string + :abstract: Yes + + Polymorphism ^^^^^^^^^^^^ diff --git a/packages/jsii-python-runtime/.gitignore b/packages/jsii-python-runtime/.gitignore index f340dffb9a..3696b9726d 100644 --- a/packages/jsii-python-runtime/.gitignore +++ b/packages/jsii-python-runtime/.gitignore @@ -10,5 +10,6 @@ dist/ __pycache__ .mypy_cache +.pytest_cache README.md diff --git a/packages/jsii-python-runtime/tests/test_compliance.py b/packages/jsii-python-runtime/tests/test_compliance.py index e1ca7ab010..96bd1b2d71 100644 --- a/packages/jsii-python-runtime/tests/test_compliance.py +++ b/packages/jsii-python-runtime/tests/test_compliance.py @@ -13,6 +13,7 @@ AsyncVirtualMethods, Calculator, ClassWithPrivateConstructorAndAutomaticProperties, + ConstructorPassesThisOut, DoNotOverridePrivates, DoubleTrouble, GreetingAugmenter, @@ -28,6 +29,7 @@ NodeStandardLibrary, NullShouldBeTreatedAsUndefined, NumberGenerator, + PartiallyInitializedThisConsumer, Polymorphism, Power, PythonReservedWords, @@ -895,3 +897,14 @@ def test_eraseUnsetDataValues(): } assert EraseUndefinedHashValues.does_key_exist(opts, "option1") assert not EraseUndefinedHashValues.does_key_exist(opts, "option2") + + +@xfail_callbacks +def test_objectIdDoesNotGetReallocatedWhenTheConstructorPassesThisOut(): + class PartiallyInitializedThisConsumerImpl(PartiallyInitializedThisConsumer): + def consume_partially_initialized_this(self): + return "OK" + + reflector = PartiallyInitializedThisConsumerImpl() + obj = ConstructorPassesThisOut(reflector) + assert obj is not None diff --git a/packages/jsii-reflect/test/classes.expected.txt b/packages/jsii-reflect/test/classes.expected.txt index e29d7390be..192c5f05ac 100644 --- a/packages/jsii-reflect/test/classes.expected.txt +++ b/packages/jsii-reflect/test/classes.expected.txt @@ -15,6 +15,7 @@ ClassThatImplementsThePrivateInterface ClassWithMutableObjectLiteralProperty ClassWithPrivateConstructorAndAutomaticProperties CompositeOperation +ConstructorPassesThisOut Constructors ConsumersOfThisCrazyTypeSystem DefaultedConstructorArgument @@ -48,6 +49,7 @@ ObjectRefsInCollections Operation OptionalConstructorArgument OverrideReturnsObject +PartiallyInitializedThisConsumer Polymorphism Power PublicClass diff --git a/packages/jsii-reflect/test/jsii-tree.test.all.expected.txt b/packages/jsii-reflect/test/jsii-tree.test.all.expected.txt index fc41e4bedc..bcc7c81eec 100644 --- a/packages/jsii-reflect/test/jsii-tree.test.all.expected.txt +++ b/packages/jsii-reflect/test/jsii-tree.test.all.expected.txt @@ -2,6 +2,7 @@ assemblies ├─┬ jsii-calc │ ├─┬ dependencies │ │ ├── @scope/jsii-calc-base + │ │ ├── @scope/jsii-calc-base-of-base │ │ └── @scope/jsii-calc-lib │ └─┬ types │ ├─┬ class AbstractClass @@ -278,6 +279,13 @@ assemblies │ │ │ └── type: primitive:string │ │ └─┬ readWriteString property │ │ └── type: primitive:string + │ ├─┬ class ConstructorPassesThisOut + │ │ └─┬ members + │ │ └─┬ (consumer) method + │ │ ├─┬ parameters + │ │ │ └─┬ consumer + │ │ │ └── type: class:jsii-calc.PartiallyInitializedThisConsumer + │ │ └── returns: void │ ├─┬ class Constructors │ │ └─┬ members │ │ ├─┬ () method @@ -770,6 +778,20 @@ assemblies │ │ │ └─┬ obj │ │ │ └── type: interface:jsii-calc.IReturnsNumber │ │ └── returns: primitive:number + │ ├─┬ class PartiallyInitializedThisConsumer + │ │ └─┬ members + │ │ ├─┬ () method + │ │ │ └── returns: void + │ │ └─┬ consumePartiallyInitializedThis(obj,dt,ev) method + │ │ ├── abstract + │ │ ├─┬ parameters + │ │ │ ├─┬ obj + │ │ │ │ └── type: class:jsii-calc.ConstructorPassesThisOut + │ │ │ ├─┬ dt + │ │ │ │ └── type: primitive:date + │ │ │ └─┬ ev + │ │ │ └── type: enum:jsii-calc.AllTypesEnum + │ │ └── returns: primitive:string │ ├─┬ class Polymorphism │ │ └─┬ members │ │ ├─┬ () method diff --git a/packages/jsii-reflect/test/jsii-tree.test.inheritance.expected.txt b/packages/jsii-reflect/test/jsii-tree.test.inheritance.expected.txt index f0bda4dddb..40abaf6846 100644 --- a/packages/jsii-reflect/test/jsii-tree.test.inheritance.expected.txt +++ b/packages/jsii-reflect/test/jsii-tree.test.inheritance.expected.txt @@ -24,6 +24,7 @@ assemblies │ ├── class ClassWithMutableObjectLiteralProperty │ ├─┬ class ClassWithPrivateConstructorAndAutomaticProperties │ │ └── interfaces: IInterfaceWithProperties + │ ├── class ConstructorPassesThisOut │ ├── class Constructors │ ├── class ConsumersOfThisCrazyTypeSystem │ ├── class DefaultedConstructorArgument @@ -66,6 +67,7 @@ assemblies │ ├── class ObjectRefsInCollections │ ├── class OptionalConstructorArgument │ ├── class OverrideReturnsObject + │ ├── class PartiallyInitializedThisConsumer │ ├── class Polymorphism │ ├─┬ class Power │ │ └── base: CompositeOperation diff --git a/packages/jsii-reflect/test/jsii-tree.test.members.expected.txt b/packages/jsii-reflect/test/jsii-tree.test.members.expected.txt index 23a8d2c2de..393039e798 100644 --- a/packages/jsii-reflect/test/jsii-tree.test.members.expected.txt +++ b/packages/jsii-reflect/test/jsii-tree.test.members.expected.txt @@ -111,6 +111,9 @@ assemblies │ │ ├── create(readOnlyString,readWriteString) method │ │ ├── readOnlyString property │ │ └── readWriteString property + │ ├─┬ class ConstructorPassesThisOut + │ │ └─┬ members + │ │ └── (consumer) method │ ├─┬ class Constructors │ │ └─┬ members │ │ ├── () method @@ -327,6 +330,10 @@ assemblies │ │ └─┬ members │ │ ├── () method │ │ └── test(obj) method + │ ├─┬ class PartiallyInitializedThisConsumer + │ │ └─┬ members + │ │ ├── () method + │ │ └── consumePartiallyInitializedThis(obj,dt,ev) method │ ├─┬ class Polymorphism │ │ └─┬ members │ │ ├── () method diff --git a/packages/jsii-reflect/test/jsii-tree.test.types.expected.txt b/packages/jsii-reflect/test/jsii-tree.test.types.expected.txt index da05887ea3..d5e5609b4c 100644 --- a/packages/jsii-reflect/test/jsii-tree.test.types.expected.txt +++ b/packages/jsii-reflect/test/jsii-tree.test.types.expected.txt @@ -15,6 +15,7 @@ assemblies │ ├── class ClassThatImplementsThePrivateInterface │ ├── class ClassWithMutableObjectLiteralProperty │ ├── class ClassWithPrivateConstructorAndAutomaticProperties + │ ├── class ConstructorPassesThisOut │ ├── class Constructors │ ├── class ConsumersOfThisCrazyTypeSystem │ ├── class DefaultedConstructorArgument @@ -47,6 +48,7 @@ assemblies │ ├── class ObjectRefsInCollections │ ├── class OptionalConstructorArgument │ ├── class OverrideReturnsObject + │ ├── class PartiallyInitializedThisConsumer │ ├── class Polymorphism │ ├── class Power │ ├── class PublicClass