Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(jsii-runtime): treat "null" as "undefined" #297

Merged
merged 4 commits into from
Nov 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions packages/jsii-calc/lib/compliance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
}

95 changes: 94 additions & 1 deletion packages/jsii-calc/test/assembly.jsii
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down Expand Up @@ -3444,5 +3537,5 @@
}
},
"version": "0.7.8",
"fingerprint": "2BaszImarh4WChl9DFUcygfTpEfXU17fHQT2wgEptfM="
"fingerprint": "FZk0ePQ2XUte84CmnOjU3PPCl6QUA88ke6wHIJKhyzo="
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -927,6 +929,18 @@ public void classWithPrivateConstructorAndAutomaticProperties() {
assertEquals("Hello", obj.getReadOnlyString());
}

@Test
public void nullShouldBeTreatedAsUndefined() {
NullShouldBeTreatedAsUndefined obj = new NullShouldBeTreatedAsUndefined("hello", null);
eladb marked this conversation as resolved.
Show resolved Hide resolved
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));
Expand Down
5 changes: 3 additions & 2 deletions packages/jsii-kernel/lib/kernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions packages/jsii-kernel/test/test.kernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 } = { };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down Expand Up @@ -3444,5 +3537,5 @@
}
},
"version": "0.7.8",
"fingerprint": "2BaszImarh4WChl9DFUcygfTpEfXU17fHQT2wgEptfM="
"fingerprint": "FZk0ePQ2XUte84CmnOjU3PPCl6QUA88ke6wHIJKhyzo="
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Loading