Skip to content

Commit f337050

Browse files
authored
[pigeon]fix a crash when casting NSNull to an Array (#4289)
Fixes a crash introduced in #3658: ``` static func fromList(_ list: [Any?]) -> NativeAuthSession? { if let userPoolTokensList = list[2] as! [Any?]? {} } ``` where `list[2]` is `NSNull`, which is not an Optional, hence can't be casted to `[Any?]?`. Recall that `nilOrValue` helper is created for this purpose. So the fix is simply: ``` static func fromList(_ list: [Any?]) -> NativeAuthSession? { if let userPoolTokensList: [Any?] = nilOrValue(list[2]) {} // <- HERE } ``` ## Why didn't we catch this regression Missing unit tests - we did not test `NSNull` fields to ensure `nilOrValue` works for them. ## Why did it work in previous version? It's surprising that this worked fine before! The original code is: ``` static func fromList(_ list: [Any]) -> NativeAuthSession? { if let userPoolTokensList = list[2] as! [Any]? {} } ``` From [my previous PR](flutter/flutter#129283), we know that list[2] is an implicit optional (that contains a NSNull value). I think Swift made an exception here when casting implicit optional NSNull (either intentionally or unintentionally). *List which issues are fixed by this PR. You must list at least one issue.* Fixes flutter/flutter#129283 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
1 parent 61df84d commit f337050

File tree

47 files changed

+1134
-619
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1134
-619
lines changed

packages/pigeon/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 10.1.2
2+
3+
* [swift] Fixes a crash when passing `null` for nested nullable classes.
4+
15
## 10.1.1
26

37
* Updates README to better reflect modern usage.

packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
import android.util.Log;

packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77

packages/pigeon/example/app/ios/Runner/Messages.g.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
import Foundation

packages/pigeon/example/app/lib/src/messages.g.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
77

packages/pigeon/example/app/macos/Runner/messages.g.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
#import <Foundation/Foundation.h>

packages/pigeon/example/app/macos/Runner/messages.g.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
#import "messages.g.h"

packages/pigeon/example/app/windows/runner/messages.g.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
#undef _HAS_EXCEPTIONS

packages/pigeon/example/app/windows/runner/messages.g.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
4+
// Autogenerated from Pigeon (v10.1.2), do not edit directly.
55
// See also: https://pub.dev/packages/pigeon
66

77
#ifndef PIGEON_MESSAGES_G_H_

packages/pigeon/lib/generator_tools.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import 'ast.dart';
1111
/// The current version of pigeon.
1212
///
1313
/// This must match the version in pubspec.yaml.
14-
const String pigeonVersion = '10.1.1';
14+
const String pigeonVersion = '10.1.2';
1515

1616
/// Read all the content from [stdin] to a String.
1717
String readStdin() {

packages/pigeon/lib/swift_generator.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,8 @@ import FlutterMacOS
627627
if (listEncodedClassNames != null &&
628628
listEncodedClassNames.contains(type.baseName)) {
629629
indent.writeln('var $variableName: $fieldType? = nil');
630-
indent.write('if let ${variableName}List = $value as! [Any?]? ');
630+
indent
631+
.write('if let ${variableName}List: [Any?] = nilOrValue($value) ');
631632
indent.addScoped('{', '}', () {
632633
indent.writeln(
633634
'$variableName = $fieldType.fromList(${variableName}List)');

packages/pigeon/mock_handler_tester/test/message.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44
//
5-
// Autogenerated from Pigeon (v9.2.5), do not edit directly.
5+
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
66
// See also: https://pub.dev/packages/pigeon
77
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
88

packages/pigeon/mock_handler_tester/test/test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44
//
5-
// Autogenerated from Pigeon (v9.2.5), do not edit directly.
5+
// Autogenerated from Pigeon (v10.1.1), do not edit directly.
66
// See also: https://pub.dev/packages/pigeon
77
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import
88
// ignore_for_file: avoid_relative_lib_imports

packages/pigeon/pigeons/core_tests.dart

+18-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ enum AnEnum {
1010
three,
1111
}
1212

13-
// A class containing all supported types.
13+
/// A class containing all supported types.
1414
class AllTypes {
1515
AllTypes({
1616
this.aBool = false,
@@ -43,7 +43,7 @@ class AllTypes {
4343
String aString;
4444
}
4545

46-
// A class containing all supported nullable types.
46+
/// A class containing all supported nullable types.
4747
class AllNullableTypes {
4848
AllNullableTypes(
4949
this.aNullableBool,
@@ -82,10 +82,15 @@ class AllNullableTypes {
8282
String? aNullableString;
8383
}
8484

85-
// A class for testing nested object handling.
86-
class AllNullableTypesWrapper {
87-
AllNullableTypesWrapper(this.values);
88-
AllNullableTypes values;
85+
/// A class for testing nested class handling.
86+
///
87+
/// This is needed to test nested nullable and non-nullable classes,
88+
/// `AllNullableTypes` is non-nullable here as it is easier to instantiate
89+
/// than `AllTypes` when testing doesn't require both (ie. testing null classes).
90+
class AllClassesWrapper {
91+
AllClassesWrapper(this.allNullableTypes, this.allTypes);
92+
AllNullableTypes allNullableTypes;
93+
AllTypes? allTypes;
8994
}
9095

9196
/// The core interface that each host language plugin must implement in
@@ -152,6 +157,11 @@ abstract class HostIntegrationCoreApi {
152157
@SwiftFunction('echo(_:)')
153158
Map<String?, Object?> echoMap(Map<String?, Object?> aMap);
154159

160+
/// Returns the passed map to test nested class serialization and deserialization.
161+
@ObjCSelector('echoClassWrapper:')
162+
@SwiftFunction('echo(_:)')
163+
AllClassesWrapper echoClassWrapper(AllClassesWrapper wrapper);
164+
155165
// ========== Synchronous nullable method tests ==========
156166

157167
/// Returns the passed object, to test serialization and deserialization.
@@ -163,13 +173,13 @@ abstract class HostIntegrationCoreApi {
163173
/// sending of nested objects.
164174
@ObjCSelector('extractNestedNullableStringFrom:')
165175
@SwiftFunction('extractNestedNullableString(from:)')
166-
String? extractNestedNullableString(AllNullableTypesWrapper wrapper);
176+
String? extractNestedNullableString(AllClassesWrapper wrapper);
167177

168178
/// Returns the inner `aString` value from the wrapped object, to test
169179
/// sending of nested objects.
170180
@ObjCSelector('createNestedObjectWithNullableString:')
171181
@SwiftFunction('createNestedObject(with:)')
172-
AllNullableTypesWrapper createNestedNullableString(String? nullableString);
182+
AllClassesWrapper createNestedNullableString(String? nullableString);
173183

174184
/// Returns passed in arguments of multiple types.
175185
@ObjCSelector('sendMultipleNullableTypesABool:anInt:aString:')

packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java

+10-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
import androidx.annotation.NonNull;
88
import androidx.annotation.Nullable;
9+
import com.example.alternate_language_test_plugin.CoreTests.AllClassesWrapper;
910
import com.example.alternate_language_test_plugin.CoreTests.AllNullableTypes;
10-
import com.example.alternate_language_test_plugin.CoreTests.AllNullableTypesWrapper;
1111
import com.example.alternate_language_test_plugin.CoreTests.AllTypes;
1212
import com.example.alternate_language_test_plugin.CoreTests.FlutterIntegrationCoreApi;
1313
import com.example.alternate_language_test_plugin.CoreTests.HostIntegrationCoreApi;
@@ -99,17 +99,21 @@ public void throwErrorFromVoid() {
9999
return aMap;
100100
}
101101

102+
@NonNull
103+
public AllClassesWrapper echoClassWrapper(@NonNull AllClassesWrapper wrapper) {
104+
return wrapper;
105+
}
106+
102107
@Override
103-
public @Nullable String extractNestedNullableString(@NonNull AllNullableTypesWrapper wrapper) {
104-
return wrapper.getValues().getANullableString();
108+
public @Nullable String extractNestedNullableString(@NonNull AllClassesWrapper wrapper) {
109+
return wrapper.getAllNullableTypes().getANullableString();
105110
}
106111

107112
@Override
108-
public @NonNull AllNullableTypesWrapper createNestedNullableString(
109-
@Nullable String nullableString) {
113+
public @NonNull AllClassesWrapper createNestedNullableString(@Nullable String nullableString) {
110114
AllNullableTypes innerObject =
111115
new AllNullableTypes.Builder().setANullableString(nullableString).build();
112-
return new AllNullableTypesWrapper.Builder().setValues(innerObject).build();
116+
return new AllClassesWrapper.Builder().setAllNullableTypes(innerObject).build();
113117
}
114118

115119
@Override

0 commit comments

Comments
 (0)