Skip to content

Commit c7dfad3

Browse files
authored
fix(runtime): type not found (#3763)
When a jsii module returned a private class implementation of an interface, consuming jsii.rtti data may return an FQN for the internal class, which does not exist in foreign languages, leading to an error. Revert to tagging FQNs directly instead. Fixes #3742
1 parent ad085eb commit c7dfad3

File tree

25 files changed

+589
-36
lines changed

25 files changed

+589
-36
lines changed

.all-contributorsrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,15 @@
14571457
"contributions": [
14581458
"review"
14591459
]
1460+
},
1461+
{
1462+
"login": "cn-cit",
1463+
"name": "cn-cit",
1464+
"avatar_url": "https://avatars.githubusercontent.com/u/27255477?v=4",
1465+
"profile": "https://github.com/cn-cit",
1466+
"contributions": [
1467+
"bug"
1468+
]
14601469
}
14611470
],
14621471
"repoType": "github",

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,23 +228,24 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
228228
</tr>
229229
<tr>
230230
<td align="center"><a href="https://github.com/arnogeurts-sqills"><img src="https://avatars.githubusercontent.com/u/79304871?v=4?s=100" width="100px;" alt=""/><br /><sub><b>arnogeurts-sqills</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Aarnogeurts-sqills+label%3Abug" title="Bug reports">🐛</a> <a href="https://github.com/aws/jsii/commits?author=arnogeurts-sqills" title="Code">💻</a></td>
231+
<td align="center"><a href="https://github.com/cn-cit"><img src="https://avatars.githubusercontent.com/u/27255477?v=4?s=100" width="100px;" alt=""/><br /><sub><b>cn-cit</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Acn-cit+label%3Abug" title="Bug reports">🐛</a></td>
231232
<td align="center"><a href="https://github.com/deccy-mcc"><img src="https://avatars0.githubusercontent.com/u/45844893?v=4?s=100" width="100px;" alt=""/><br /><sub><b>deccy-mcc</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Adeccy-mcc+label%3Abug" title="Bug reports">🐛</a></td>
232233
<td align="center"><a href="https://github.com/apps/dependabot-preview"><img src="https://avatars3.githubusercontent.com/in/2141?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dependabot-preview[bot]</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Adependabot-preview[bot]+label%3Abug" title="Bug reports">🐛</a> <a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Adependabot-preview[bot]" title="Maintenance">🚧</a></td>
233234
<td align="center"><a href="https://github.com/apps/dependabot"><img src="https://avatars0.githubusercontent.com/in/29110?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dependabot[bot]</b></sub></a><br /><a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Adependabot[bot]" title="Maintenance">🚧</a></td>
234235
<td align="center"><a href="https://github.com/dheffx"><img src="https://avatars0.githubusercontent.com/u/22029918?v=4?s=100" width="100px;" alt=""/><br /><sub><b>dheffx</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Adheffx+label%3Abug" title="Bug reports">🐛</a></td>
235236
<td align="center"><a href="https://github.com/gregswdl"><img src="https://avatars0.githubusercontent.com/u/47365273?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gregswdl</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Agregswdl+label%3Abug" title="Bug reports">🐛</a></td>
236-
<td align="center"><a href="https://github.com/guyroberts21"><img src="https://avatars.githubusercontent.com/u/47118902?v=4?s=100" width="100px;" alt=""/><br /><sub><b>guyroberts21</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=guyroberts21" title="Documentation">📖</a></td>
237237
</tr>
238238
<tr>
239+
<td align="center"><a href="https://github.com/guyroberts21"><img src="https://avatars.githubusercontent.com/u/47118902?v=4?s=100" width="100px;" alt=""/><br /><sub><b>guyroberts21</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=guyroberts21" title="Documentation">📖</a></td>
239240
<td align="center"><a href="https://github.com/mattBrzezinski"><img src="https://avatars.githubusercontent.com/u/4356074?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mattBrzezinski</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=mattBrzezinski" title="Documentation">📖</a></td>
240241
<td align="center"><a href="https://github.com/mergify"><img src="https://avatars.githubusercontent.com/u/18240476?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mergify</b></sub></a><br /><a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Amergify" title="Maintenance">🚧</a></td>
241242
<td align="center"><a href="https://github.com/apps/mergify"><img src="https://avatars1.githubusercontent.com/in/10562?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mergify[bot]</b></sub></a><br /><a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Amergify[bot]" title="Maintenance">🚧</a></td>
242243
<td align="center"><a href="https://github.com/nathannaveen"><img src="https://avatars.githubusercontent.com/u/42319948?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nathannaveen</b></sub></a><br /><a href="https://github.com/aws/jsii/pulls?q=is%3Apr+author%3Anathannaveen" title="Maintenance">🚧</a></td>
243244
<td align="center"><a href="https://github.com/seiyashima"><img src="https://avatars2.githubusercontent.com/u/4947101?v=4?s=100" width="100px;" alt=""/><br /><sub><b>seiyashima42</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Aseiyashima+label%3Abug" title="Bug reports">🐛</a> <a href="https://github.com/aws/jsii/commits?author=seiyashima" title="Code">💻</a> <a href="https://github.com/aws/jsii/commits?author=seiyashima" title="Documentation">📖</a></td>
244245
<td align="center"><a href="https://github.com/sullis"><img src="https://avatars3.githubusercontent.com/u/30938?v=4?s=100" width="100px;" alt=""/><br /><sub><b>sullis</b></sub></a><br /><a href="https://github.com/aws/jsii/commits?author=sullis" title="Code">💻</a></td>
245-
<td align="center"><a href="https://github.com/vaneek"><img src="https://avatars1.githubusercontent.com/u/8113305?v=4?s=100" width="100px;" alt=""/><br /><sub><b>vaneek</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Avaneek+label%3Abug" title="Bug reports">🐛</a></td>
246246
</tr>
247247
<tr>
248+
<td align="center"><a href="https://github.com/vaneek"><img src="https://avatars1.githubusercontent.com/u/8113305?v=4?s=100" width="100px;" alt=""/><br /><sub><b>vaneek</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Avaneek+label%3Abug" title="Bug reports">🐛</a></td>
248249
<td align="center"><a href="https://github.com/wendysophie"><img src="https://avatars.githubusercontent.com/u/54415551?v=4?s=100" width="100px;" alt=""/><br /><sub><b>wendysophie</b></sub></a><br /><a href="https://github.com/aws/jsii/issues?q=author%3Awendysophie+label%3Abug" title="Bug reports">🐛</a></td>
249250
</tr>
250251
</tbody>

gh-pages/content/specification/6-compliance-report.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
This section details the current state of each language binding with respect to our standard compliance suite.
66

77

8-
| number | test | java (98.33%) | golang (79.17%) | Dotnet | Python |
8+
| number | test | java (98.35%) | golang (79.34%) | Dotnet | Python |
99
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------------------------------------------- | ------ | ------ |
1010
| 1 | asyncOverrides_overrideCallsSuper | 🟢 | [🔴](https://github.com/aws/jsii/issues/2670) |||
1111
| 2 | [arrayReturnedByMethodCanBeRead]("Array created in the kernel can be queried for its elements") | 🟢 | 🟢 |||
@@ -127,3 +127,4 @@ This section details the current state of each language binding with respect to
127127
| 118 | [callbackParameterIsInterface]("Validates pure interfaces can be passed to callbacks") || 🟢 |||
128128
| 119 | [classCanBeUsedWhenNotExpressedlyLoaded]("Validates that types not explicitly loaded by the user can safely be returned by JS code") | 🟢 | 🟢 |||
129129
| 120 | [downcasting]("Ensures unsafe-cast features work as expected") || 🟢 |||
130+
| 121 | [strippedDeprecatedMemberCanBeReceived]("Ensures --strip-deprecated does not cause odd runtime errors") | 🟢 | 🟢 |||

packages/@jsii/dotnet-runtime-test/test/Amazon.JSII.Runtime.IntegrationTests/ComplianceTests.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using CompositeOperation = Amazon.JSII.Tests.CalculatorNamespace.Composition.CompositeOperation;
88
using Amazon.JSII.Tests.CalculatorNamespace.LibNamespace;
99
using Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace;
10+
using Amazon.JSII.Tests.CalculatorNamespace.LibNamespace.DeprecationRemoval;
1011
using Newtonsoft.Json.Linq;
1112
using Xunit;
1213
using Xunit.Abstractions;
@@ -1534,9 +1535,15 @@ public void ClassCanBeUsedWhenNotExpressedlyLoaded()
15341535
}
15351536

15361537
private sealed class Cdk16625Impl: Cdk16625 {
1537-
protected override double Unwrap(IRandomNumberGenerator rng) {
1538-
return rng.Next();
1539-
}
1538+
protected override double Unwrap(IRandomNumberGenerator rng) {
1539+
return rng.Next();
15401540
}
1541+
}
1542+
1543+
[Fact(DisplayName = Prefix + nameof(StrippedDeprecatedMemberCanBeReceived))]
1544+
public void StrippedDeprecatedMemberCanBeReceived()
1545+
{
1546+
Assert.NotNull(InterfaceFactory.Create());
1547+
}
15411548
}
15421549
}

packages/@jsii/go-runtime-test/project/compliance_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/aws/jsii/jsii-calc/go/jsiicalc/v3/submodule/child"
2525
calclib "github.com/aws/jsii/jsii-calc/go/scopejsiicalclib"
2626
"github.com/aws/jsii/jsii-calc/go/scopejsiicalclib/customsubmodulename"
27+
"github.com/aws/jsii/jsii-calc/go/scopejsiicalclib/deprecationremoval"
2728
"github.com/stretchr/testify/require"
2829
"github.com/stretchr/testify/suite"
2930
)
@@ -1655,6 +1656,12 @@ func (suite *ComplianceSuite) TestDownCasting() {
16551656
require.Equal(realValue.Foo(), jsii.Number(1337))
16561657
}
16571658

1659+
func (suite *ComplianceSuite) TestStrippedDeprecatedMemberCanBeReceived() {
1660+
require := suite.Require()
1661+
1662+
require.NotNil(deprecationremoval.InterfaceFactory_Create())
1663+
}
1664+
16581665
// required to make `go test` recognize the suite.
16591666
func TestComplianceSuite(t *testing.T) {
16601667
suite.Run(t, new(ComplianceSuite))

packages/@jsii/java-runtime-test/project/src/test/java/software/amazon/jsii/testing/ComplianceTest.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.databind.JsonNode;
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import com.fasterxml.jackson.databind.node.ObjectNode;
6+
import org.jetbrains.annotations.NotNull;
67
import org.junit.jupiter.api.Test;
78
import org.junit.jupiter.api.extension.ExtendWith;
89
import software.amazon.jsii.ComplianceSuiteHarness;
@@ -14,6 +15,7 @@
1415
import software.amazon.jsii.tests.calculator.cdk16625.Cdk16625;
1516
import software.amazon.jsii.tests.calculator.composition.CompositeOperation;
1617
import software.amazon.jsii.tests.calculator.custom_submodule_name.NestingClass.NestedStruct;
18+
import software.amazon.jsii.tests.calculator.lib.deprecation_removal.InterfaceFactory;
1719
import software.amazon.jsii.tests.calculator.lib.EnumFromScopedModule;
1820
import software.amazon.jsii.tests.calculator.lib.IFriendly;
1921
import software.amazon.jsii.tests.calculator.lib.MyFirstStruct;
@@ -24,10 +26,6 @@
2426

2527
import java.io.IOException;
2628
import java.lang.reflect.Constructor;
27-
import java.lang.reflect.InvocationTargetException;
28-
import java.security.AccessController;
29-
import java.security.PrivilegedActionException;
30-
import java.security.PrivilegedExceptionAction;
3129
import java.text.DateFormat;
3230
import java.text.SimpleDateFormat;
3331
import java.time.Instant;
@@ -1790,13 +1788,17 @@ public void iso8601DoesNotDeserializeToDate() {
17901788
final String nowAsISO = df.format(new Date());
17911789

17921790
final IWallClock wallClock = new IWallClock() {
1791+
@NotNull
1792+
@Override
17931793
public String iso8601Now() {
17941794
return nowAsISO;
17951795
}
17961796
};
17971797

17981798
final Entropy entropy = new Entropy(wallClock) {
1799-
public String repeat(final String word) {
1799+
@NotNull
1800+
@Override
1801+
public String repeat(@NotNull final String word) {
18001802
return word;
18011803
}
18021804
};
@@ -1807,11 +1809,17 @@ public String repeat(final String word) {
18071809
@Test
18081810
public void classCanBeUsedWhenNotExpressedlyLoaded() {
18091811
final Cdk16625 subject = new Cdk16625() {
1812+
@NotNull
18101813
@Override
18111814
protected java.lang.Number unwrap(final IRandomNumberGenerator rng) {
18121815
return rng.next();
18131816
}
18141817
};
18151818
subject.test();
18161819
}
1820+
1821+
@Test
1822+
public void strippedDeprecatedMemberCanBeReceived() {
1823+
assertNotNull(InterfaceFactory.create());
1824+
}
18171825
}

packages/@jsii/kernel/src/kernel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ export class Kernel {
583583
case spec.TypeKind.Class:
584584
case spec.TypeKind.Enum:
585585
const constructor = this._findSymbol(fqn);
586-
tagJsiiConstructor(constructor, fqn, assm.metadata.version);
586+
tagJsiiConstructor(constructor, fqn);
587587
}
588588
}
589589
}

packages/@jsii/kernel/src/objects.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as spec from '@jsii/spec';
2+
import * as assert from 'assert';
23

34
import * as api from './api';
45
import { JsiiFault } from './kernel';
@@ -15,15 +16,12 @@ const OBJID_SYMBOL = Symbol.for('$__jsii__objid__$');
1516
const IFACES_SYMBOL = Symbol.for('$__jsii__interfaces__$');
1617

1718
/**
18-
* Symbol we use to tag the constructor of a JSII class
19+
* Symbol we use to tag constructors that are exported from a JSII module.
1920
*/
20-
const JSII_RTTI_SYMBOL = Symbol.for('jsii.rtti');
21+
const JSII_TYPE_FQN_SYMBOL = Symbol('$__jsii__fqn__$');
2122

2223
interface ManagedConstructor {
23-
readonly [JSII_RTTI_SYMBOL]: {
24-
readonly fqn: string;
25-
readonly version: string;
26-
};
24+
readonly [JSII_TYPE_FQN_SYMBOL]: string;
2725
}
2826

2927
type MaybeManagedConstructor = Partial<ManagedConstructor>;
@@ -36,7 +34,7 @@ type MaybeManagedConstructor = Partial<ManagedConstructor>;
3634
* information.
3735
*/
3836
export function jsiiTypeFqn(obj: any): string | undefined {
39-
return (obj.constructor as MaybeManagedConstructor)[JSII_RTTI_SYMBOL]?.fqn;
37+
return (obj.constructor as MaybeManagedConstructor)[JSII_TYPE_FQN_SYMBOL];
4038
}
4139

4240
/**
@@ -96,19 +94,21 @@ function tagObject(obj: unknown, objid: string, interfaces?: string[]) {
9694
/**
9795
* Set the JSII FQN for classes produced by a given constructor
9896
*/
99-
export function tagJsiiConstructor(
100-
constructor: any,
101-
fqn: string,
102-
version: string,
103-
) {
104-
if (Object.prototype.hasOwnProperty.call(constructor, JSII_RTTI_SYMBOL)) {
105-
return;
97+
export function tagJsiiConstructor(constructor: any, fqn: string) {
98+
if (Object.prototype.hasOwnProperty.call(constructor, JSII_TYPE_FQN_SYMBOL)) {
99+
return assert(
100+
constructor[JSII_TYPE_FQN_SYMBOL] === fqn,
101+
`Unable to register ${constructor.name} as ${fqn}: it is already registerd with FQN ${constructor[JSII_TYPE_FQN_SYMBOL]}`,
102+
);
106103
}
107-
Object.defineProperty(constructor, JSII_RTTI_SYMBOL, {
104+
105+
// Mark this constructor as exported from a jsii module, so we know we
106+
// should be considering it's FQN as a valid exported type.
107+
Object.defineProperty(constructor, JSII_TYPE_FQN_SYMBOL, {
108108
configurable: false,
109109
enumerable: false,
110110
writable: false,
111-
value: { fqn, version },
111+
value: fqn,
112112
});
113113
}
114114

packages/@jsii/python-runtime/tests/test_compliance.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
from jsii_calc.submodule.child import SomeEnum
8787
from scope.jsii_calc_lib import IFriendly, EnumFromScopedModule, Number
8888
from scope.jsii_calc_lib.custom_submodule_name import IReflectable, ReflectableEntry
89+
from scope.jsii_calc_lib.deprecation_removal import InterfaceFactory
8990

9091
# Note: The names of these test functions have been chosen to map as closely to the
9192
# Java Compliance tests as possible.
@@ -1343,3 +1344,7 @@ def _unwrap(self, rng: IRandomNumberGenerator):
13431344

13441345
# This should NOT throw
13451346
Subject().test()
1347+
1348+
1349+
def test_stripped_deprecated_member_can_be_received():
1350+
assert InterfaceFactory.create() is not None
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@scope/jsii-calc-lib.deprecationRemoval.DeprecatedImplementation

0 commit comments

Comments
 (0)