// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import '../native_testing.dart'; import 'null_assertions_test_lib.dart'; // Implementations of `NativeInterface` and `JSInterface` in a folder that is // part of the allowlist for the `--native-null-assertions` flag. This file is // treated as a web library, and therefore native members and `JS()` invocations // should be checked. @Native("AAA") class AAA implements NativeInterface { int get size native; String get name native; String? get optName native; int method1() native; String method2() native; String? optMethod() native; } @Native('CCC') class CCC implements JSInterface { String get name => JS('String', '#.name', this); String? get optName => JS('String|Null', '#.optName', this); } /// Returns an 'AAA' object that satisfies the interface. AAA makeA() native; /// Returns an 'AAA' object where each method breaks the interface's contract. AAA makeAX() native; /// Returns a 'CCC' object that satisfies the interface using `JS()` /// invocations. CCC makeC() native; /// Returns a 'CCC' object where each method breaks the interface's contract. CCC makeCX() native; // The 'AAA' version of the code is passed only objects of a single native // class, so the native method can be inlined (which happens in the optimizer). // This tests that the null-check exists in the 'inlined' code. @pragma('dart2js:noInline') String describeAAA(AAA o) { return '${o.name} ${o.method2()} ${o.size} ${o.method1()}'; } @pragma('dart2js:noInline') String describeOptAAA(AAA o) { return '${o.optName} ${o.optMethod()}'; } void testNativeNullAssertions(bool flagEnabled) { nativeTesting(); setup(); AAA a = makeA(); BBB b = BBB(); Expect.equals(expectedA, describeNativeInterface(a)); Expect.equals(expectedB, describeNativeInterface(b)); Expect.equals(expectedA, describeAAA(a)); AAA x = makeAX(); // This object returns `null`! // Since native members are in a web library, this should throw if null checks // are enabled. var checkExpectation = flagEnabled ? Expect.throws : (f) => f(); checkExpectation(() => describeNativeInterface(x)); checkExpectation(() => describeAAA(x)); checkExpectation(() => x.name); checkExpectation(() => x.size); checkExpectation(() => x.method1()); checkExpectation(() => x.method2()); // Now test that a nullable return type does not have a check. Expect.equals(expectedOptA, describeOptNativeInterface(a)); Expect.equals(expectedOptB, describeOptNativeInterface(b)); Expect.equals(expectedOptX, describeOptNativeInterface(x)); Expect.equals(expectedOptA, describeOptAAA(a)); Expect.equals(expectedOptX, describeOptAAA(x)); } void testJSInvocationNullAssertions(bool flagEnabled) { nativeTesting(); setup(); CCC c = makeC(); CCC cx = makeCX(); Expect.equals(expectedC, describeJSInterface(c)); // Since invocations are in a web library, this should throw if null checks // are enabled. var checkExpectation = flagEnabled ? Expect.throws : (f) => f(); checkExpectation(() => describeJSInterface(cx)); // Test that invocations with a nullable static type do not have checks. Expect.equals(expectedOptC, describeOptJSInterface(c)); Expect.equals(expectedOptCX, describeOptJSInterface(cx)); }