diff --git a/packages/jsii-calc/lib/compliance.ts b/packages/jsii-calc/lib/compliance.ts
index a0989493cc..24768a0b6b 100644
--- a/packages/jsii-calc/lib/compliance.ts
+++ b/packages/jsii-calc/lib/compliance.ts
@@ -948,3 +948,49 @@ export class DoNotRecognizeAnyAsOptional {
}
}
+
+/**
+ * jsii#282, aws-cdk#157: null should be treated as "undefined"
+ */
+export class NullShouldBeTreatedAsUndefined {
+ public changeMeToUndefined? = "hello";
+
+ constructor(_param1: string, optional?: any) {
+ if (optional !== undefined) {
+ throw new Error('Expecting second constructor argument to be "undefined"');
+ }
+ }
+
+ public giveMeUndefined(value?: any) {
+ if (value !== undefined) {
+ throw new Error('I am disappointed. I expected undefined and got: ' + JSON.stringify(value));
+ }
+ }
+
+ public giveMeUndefinedInsideAnObject(input: NullShouldBeTreatedAsUndefinedData) {
+ if (input.thisShouldBeUndefined !== undefined) {
+ throw new Error('I am disappointed. I expected undefined in "thisShouldBeUndefined" and got: ' + JSON.stringify(input));
+ }
+
+ const array = input.arrayWithThreeElementsAndUndefinedAsSecondArgument;
+ if (array.length !== 3) {
+ throw new Error('Expecting "arrayWithThreeElementsAndUndefinedAsSecondArgument" to have three elements: ' + JSON.stringify(input));
+ }
+
+ if (array[1] !== undefined) {
+ throw new Error('Expected arrayWithThreeElementsAndUndefinedAsSecondArgument[1] to be undefined: ' + JSON.stringify(input))
+ }
+ }
+
+ public verifyPropertyIsUndefined() {
+ if (this.changeMeToUndefined !== undefined) {
+ throw new Error('Expecting property "changeMeToUndefined" to be undefined, and it is: ' + this.changeMeToUndefined);
+ }
+ }
+}
+
+export interface NullShouldBeTreatedAsUndefinedData {
+ thisShouldBeUndefined?: any;
+ arrayWithThreeElementsAndUndefinedAsSecondArgument: any[];
+}
+
diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii
index d245fa15e5..533c28165d 100644
--- a/packages/jsii-calc/test/assembly.jsii
+++ b/packages/jsii-calc/test/assembly.jsii
@@ -2273,6 +2273,99 @@
}
]
},
+ "jsii-calc.NullShouldBeTreatedAsUndefined": {
+ "assembly": "jsii-calc",
+ "docs": {
+ "comment": "jsii#282, aws-cdk#157: null should be treated as \"undefined\""
+ },
+ "fqn": "jsii-calc.NullShouldBeTreatedAsUndefined",
+ "initializer": {
+ "initializer": true,
+ "parameters": [
+ {
+ "name": "_param1",
+ "type": {
+ "primitive": "string"
+ }
+ },
+ {
+ "name": "optional",
+ "type": {
+ "optional": true,
+ "primitive": "any"
+ }
+ }
+ ]
+ },
+ "kind": "class",
+ "methods": [
+ {
+ "name": "giveMeUndefined",
+ "parameters": [
+ {
+ "name": "value",
+ "type": {
+ "optional": true,
+ "primitive": "any"
+ }
+ }
+ ]
+ },
+ {
+ "name": "giveMeUndefinedInsideAnObject",
+ "parameters": [
+ {
+ "name": "input",
+ "type": {
+ "fqn": "jsii-calc.NullShouldBeTreatedAsUndefinedData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "verifyPropertyIsUndefined"
+ }
+ ],
+ "name": "NullShouldBeTreatedAsUndefined",
+ "properties": [
+ {
+ "name": "changeMeToUndefined",
+ "type": {
+ "optional": true,
+ "primitive": "string"
+ }
+ }
+ ]
+ },
+ "jsii-calc.NullShouldBeTreatedAsUndefinedData": {
+ "assembly": "jsii-calc",
+ "datatype": true,
+ "fqn": "jsii-calc.NullShouldBeTreatedAsUndefinedData",
+ "kind": "interface",
+ "name": "NullShouldBeTreatedAsUndefinedData",
+ "properties": [
+ {
+ "abstract": true,
+ "name": "arrayWithThreeElementsAndUndefinedAsSecondArgument",
+ "type": {
+ "collection": {
+ "elementtype": {
+ "primitive": "any"
+ },
+ "kind": "array"
+ }
+ }
+ },
+ {
+ "abstract": true,
+ "name": "thisShouldBeUndefined",
+ "type": {
+ "optional": true,
+ "primitive": "any"
+ }
+ }
+ ]
+ },
"jsii-calc.NumberGenerator": {
"assembly": "jsii-calc",
"docs": {
@@ -3444,5 +3537,5 @@
}
},
"version": "0.7.8",
- "fingerprint": "2BaszImarh4WChl9DFUcygfTpEfXU17fHQT2wgEptfM="
+ "fingerprint": "FZk0ePQ2XUte84CmnOjU3PPCl6QUA88ke6wHIJKhyzo="
}
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 ff6747a7be..7cd6934249 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
@@ -827,6 +827,27 @@ public void TestReturnInterfaceFromOverride()
Assert.Equal(4 * n, obj.Test(arg));
}
+ [Fact(DisplayName = Prefix + nameof(NullShouldBeTreatedAsUndefined))]
+ public void NullShouldBeTreatedAsUndefined()
+ {
+ // ctor
+ var obj = new NullShouldBeTreatedAsUndefined("param1", null);
+
+ // method argument
+ obj.GiveMeUndefined(null);
+
+ // inside object
+ obj.GiveMeUndefinedInsideAnObject(new NullShouldBeTreatedAsUndefinedData
+ {
+ ThisShouldBeUndefined = null,
+ ArrayWithThreeElementsAndUndefinedAsSecondArgument = new[] { "hello", null, "world" }
+ });
+
+ // property
+ obj.ChangeMeToUndefined = null;
+ obj.VerifyPropertyIsUndefined();
+ }
+
class NumberReturner : DeputyBase, IIReturnsNumber
{
public NumberReturner(double number)
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 f2c437819b..48dac8a445 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
@@ -25,6 +25,8 @@
import software.amazon.jsii.tests.calculator.Multiply;
import software.amazon.jsii.tests.calculator.Negate;
import software.amazon.jsii.tests.calculator.NodeStandardLibrary;
+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.Polymorphism;
import software.amazon.jsii.tests.calculator.Power;
@@ -927,6 +929,18 @@ public void classWithPrivateConstructorAndAutomaticProperties() {
assertEquals("Hello", obj.getReadOnlyString());
}
+ @Test
+ public void nullShouldBeTreatedAsUndefined() {
+ NullShouldBeTreatedAsUndefined obj = new NullShouldBeTreatedAsUndefined("hello", null);
+ obj.giveMeUndefined(null);
+ obj.giveMeUndefinedInsideAnObject(NullShouldBeTreatedAsUndefinedData.builder()
+ .withThisShouldBeUndefined(null)
+ .withArrayWithThreeElementsAndUndefinedAsSecondArgument(Arrays.asList("hello", null, "boom"))
+ .build());
+ obj.setChangeMeToUndefined(null);
+ obj.verifyPropertyIsUndefined();
+ }
+
static class MulTen extends Multiply {
public MulTen(final int value) {
super(new Number(value), new Number(10));
diff --git a/packages/jsii-kernel/lib/kernel.ts b/packages/jsii-kernel/lib/kernel.ts
index a7f5241ba9..c508e34599 100644
--- a/packages/jsii-kernel/lib/kernel.ts
+++ b/packages/jsii-kernel/lib/kernel.ts
@@ -877,9 +877,10 @@ export class Kernel {
return undefined;
}
- // null
+ // null is treated as "undefined" because most languages do not have this distinction
+ // see awslabs/aws-cdk#157 and awslabs/jsii#282
if (v === null) {
- return null;
+ return undefined;
}
// pointer
diff --git a/packages/jsii-kernel/test/test.kernel.ts b/packages/jsii-kernel/test/test.kernel.ts
index bd778be7d5..7d54fe430f 100644
--- a/packages/jsii-kernel/test/test.kernel.ts
+++ b/packages/jsii-kernel/test/test.kernel.ts
@@ -936,6 +936,29 @@ defineTest('overrides: skip overrides of private properties', async (test, sandb
test.deepEqual(result.result, 'privateProperty');
});
+defineTest('nulls are converted to undefined - ctor', async (_test, sandbox) => {
+ sandbox.create({ fqn: 'jsii-calc.NullShouldBeTreatedAsUndefined', args: [ "foo", null ] });
+});
+
+defineTest('nulls are converted to undefined - method arguments', async (_test, sandbox) => {
+ const objref = sandbox.create({ fqn: 'jsii-calc.NullShouldBeTreatedAsUndefined', args: [ "foo" ] });
+ sandbox.invoke({ objref, method: 'giveMeUndefined', args: [ null ] });
+});
+
+defineTest('nulls are converted to undefined - inside objects', async (_test, sandbox) => {
+ const objref = sandbox.create({ fqn: 'jsii-calc.NullShouldBeTreatedAsUndefined', args: [ "foo" ] });
+ sandbox.invoke({ objref, method: 'giveMeUndefinedInsideAnObject', args: [ {
+ thisShouldBeUndefined: null,
+ arrayWithThreeElementsAndUndefinedAsSecondArgument: [ 'one', null, 'two' ]
+ } ]});
+});
+
+defineTest('nulls are converted to undefined - properties', async (_test, sandbox) => {
+ const objref = sandbox.create({ fqn: 'jsii-calc.NullShouldBeTreatedAsUndefined', args: [ "foo" ] });
+ sandbox.set({ objref, property: 'changeMeToUndefined', value: null });
+ sandbox.invoke({ objref, method: 'verifyPropertyIsUndefined' });
+});
+
// =================================================================================================
const testNames: { [name: string]: boolean } = { };
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 d245fa15e5..533c28165d 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
@@ -2273,6 +2273,99 @@
}
]
},
+ "jsii-calc.NullShouldBeTreatedAsUndefined": {
+ "assembly": "jsii-calc",
+ "docs": {
+ "comment": "jsii#282, aws-cdk#157: null should be treated as \"undefined\""
+ },
+ "fqn": "jsii-calc.NullShouldBeTreatedAsUndefined",
+ "initializer": {
+ "initializer": true,
+ "parameters": [
+ {
+ "name": "_param1",
+ "type": {
+ "primitive": "string"
+ }
+ },
+ {
+ "name": "optional",
+ "type": {
+ "optional": true,
+ "primitive": "any"
+ }
+ }
+ ]
+ },
+ "kind": "class",
+ "methods": [
+ {
+ "name": "giveMeUndefined",
+ "parameters": [
+ {
+ "name": "value",
+ "type": {
+ "optional": true,
+ "primitive": "any"
+ }
+ }
+ ]
+ },
+ {
+ "name": "giveMeUndefinedInsideAnObject",
+ "parameters": [
+ {
+ "name": "input",
+ "type": {
+ "fqn": "jsii-calc.NullShouldBeTreatedAsUndefinedData"
+ }
+ }
+ ]
+ },
+ {
+ "name": "verifyPropertyIsUndefined"
+ }
+ ],
+ "name": "NullShouldBeTreatedAsUndefined",
+ "properties": [
+ {
+ "name": "changeMeToUndefined",
+ "type": {
+ "optional": true,
+ "primitive": "string"
+ }
+ }
+ ]
+ },
+ "jsii-calc.NullShouldBeTreatedAsUndefinedData": {
+ "assembly": "jsii-calc",
+ "datatype": true,
+ "fqn": "jsii-calc.NullShouldBeTreatedAsUndefinedData",
+ "kind": "interface",
+ "name": "NullShouldBeTreatedAsUndefinedData",
+ "properties": [
+ {
+ "abstract": true,
+ "name": "arrayWithThreeElementsAndUndefinedAsSecondArgument",
+ "type": {
+ "collection": {
+ "elementtype": {
+ "primitive": "any"
+ },
+ "kind": "array"
+ }
+ }
+ },
+ {
+ "abstract": true,
+ "name": "thisShouldBeUndefined",
+ "type": {
+ "optional": true,
+ "primitive": "any"
+ }
+ }
+ ]
+ },
"jsii-calc.NumberGenerator": {
"assembly": "jsii-calc",
"docs": {
@@ -3444,5 +3537,5 @@
}
},
"version": "0.7.8",
- "fingerprint": "2BaszImarh4WChl9DFUcygfTpEfXU17fHQT2wgEptfM="
+ "fingerprint": "FZk0ePQ2XUte84CmnOjU3PPCl6QUA88ke6wHIJKhyzo="
}
diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/INullShouldBeTreatedAsUndefinedData.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/INullShouldBeTreatedAsUndefinedData.cs
new file mode 100644
index 0000000000..c5eed0cac8
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/INullShouldBeTreatedAsUndefinedData.cs
@@ -0,0 +1,22 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ [JsiiInterface(typeof(INullShouldBeTreatedAsUndefinedData), "jsii-calc.NullShouldBeTreatedAsUndefinedData")]
+ public interface INullShouldBeTreatedAsUndefinedData
+ {
+ [JsiiProperty("arrayWithThreeElementsAndUndefinedAsSecondArgument", "{\"collection\":{\"kind\":\"array\",\"elementtype\":{\"primitive\":\"any\"}}}")]
+ object[] ArrayWithThreeElementsAndUndefinedAsSecondArgument
+ {
+ get;
+ set;
+ }
+
+ [JsiiProperty("thisShouldBeUndefined", "{\"primitive\":\"any\",\"optional\":true}")]
+ object ThisShouldBeUndefined
+ {
+ get;
+ set;
+ }
+ }
+}
\ 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/NullShouldBeTreatedAsUndefined.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NullShouldBeTreatedAsUndefined.cs
new file mode 100644
index 0000000000..59078293ae
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NullShouldBeTreatedAsUndefined.cs
@@ -0,0 +1,46 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ /// jsii#282, aws-cdk#157: null should be treated as "undefined"
+ [JsiiClass(typeof(NullShouldBeTreatedAsUndefined), "jsii-calc.NullShouldBeTreatedAsUndefined", "[{\"name\":\"_param1\",\"type\":{\"primitive\":\"string\"}},{\"name\":\"optional\",\"type\":{\"primitive\":\"any\",\"optional\":true}}]")]
+ public class NullShouldBeTreatedAsUndefined : DeputyBase
+ {
+ public NullShouldBeTreatedAsUndefined(string _param1, object optional): base(new DeputyProps(new object[]{_param1, optional}))
+ {
+ }
+
+ protected NullShouldBeTreatedAsUndefined(ByRefValue reference): base(reference)
+ {
+ }
+
+ protected NullShouldBeTreatedAsUndefined(DeputyProps props): base(props)
+ {
+ }
+
+ [JsiiProperty("changeMeToUndefined", "{\"primitive\":\"string\",\"optional\":true}")]
+ public virtual string ChangeMeToUndefined
+ {
+ get => GetInstanceProperty();
+ set => SetInstanceProperty(value);
+ }
+
+ [JsiiMethod("giveMeUndefined", null, "[{\"name\":\"value\",\"type\":{\"primitive\":\"any\",\"optional\":true}}]")]
+ public virtual void GiveMeUndefined(object value)
+ {
+ InvokeInstanceVoidMethod(new object[]{value});
+ }
+
+ [JsiiMethod("giveMeUndefinedInsideAnObject", null, "[{\"name\":\"input\",\"type\":{\"fqn\":\"jsii-calc.NullShouldBeTreatedAsUndefinedData\"}}]")]
+ public virtual void GiveMeUndefinedInsideAnObject(INullShouldBeTreatedAsUndefinedData input)
+ {
+ InvokeInstanceVoidMethod(new object[]{input});
+ }
+
+ [JsiiMethod("verifyPropertyIsUndefined", null, "[]")]
+ public virtual void VerifyPropertyIsUndefined()
+ {
+ InvokeInstanceVoidMethod(new object[]{});
+ }
+ }
+}
\ 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/NullShouldBeTreatedAsUndefinedData.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NullShouldBeTreatedAsUndefinedData.cs
new file mode 100644
index 0000000000..9be4f5bbd0
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NullShouldBeTreatedAsUndefinedData.cs
@@ -0,0 +1,21 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ public class NullShouldBeTreatedAsUndefinedData : DeputyBase, INullShouldBeTreatedAsUndefinedData
+ {
+ [JsiiProperty("arrayWithThreeElementsAndUndefinedAsSecondArgument", "{\"collection\":{\"kind\":\"array\",\"elementtype\":{\"primitive\":\"any\"}}}", true)]
+ public object[] ArrayWithThreeElementsAndUndefinedAsSecondArgument
+ {
+ get;
+ set;
+ }
+
+ [JsiiProperty("thisShouldBeUndefined", "{\"primitive\":\"any\",\"optional\":true}", true)]
+ public object ThisShouldBeUndefined
+ {
+ get;
+ set;
+ }
+ }
+}
\ 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/NullShouldBeTreatedAsUndefinedDataProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NullShouldBeTreatedAsUndefinedDataProxy.cs
new file mode 100644
index 0000000000..0456317c14
--- /dev/null
+++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/NullShouldBeTreatedAsUndefinedDataProxy.cs
@@ -0,0 +1,26 @@
+using Amazon.JSII.Runtime.Deputy;
+
+namespace Amazon.JSII.Tests.CalculatorNamespace
+{
+ [JsiiTypeProxy(typeof(INullShouldBeTreatedAsUndefinedData), "jsii-calc.NullShouldBeTreatedAsUndefinedData")]
+ internal sealed class NullShouldBeTreatedAsUndefinedDataProxy : DeputyBase, INullShouldBeTreatedAsUndefinedData
+ {
+ private NullShouldBeTreatedAsUndefinedDataProxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ [JsiiProperty("arrayWithThreeElementsAndUndefinedAsSecondArgument", "{\"collection\":{\"kind\":\"array\",\"elementtype\":{\"primitive\":\"any\"}}}")]
+ public object[] ArrayWithThreeElementsAndUndefinedAsSecondArgument
+ {
+ get => GetInstanceProperty