// Copyright (c) 2022, 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. // Tests that static fields are properly reset after hot restarts. // Requirements=nnbd import 'dart:_runtime' as dart show hotRestart, resetFields; import 'package:expect/expect.dart'; String? noInitializer; int withInitializer = 1; class Statics { static String? noInitializer; static int withInitializer = 2; } class StaticsGeneric { static String? noInitializer; static int withInitializer = 3; } class StaticsSetter { static int counter = 0; static const field = 5; static const field2 = null; static set field(int value) => StaticsSetter.counter += 1; static set field2(value) => 42; } void main() { testStaticFields(); testStaticSetterOfConstField(); } void testStaticFields() { var resetFieldCount = dart.resetFields.length; // Set static fields without explicit initializers. Avoid calling getters for // these statics to ensure they are reset even if they are never accessed. noInitializer = 'set via setter'; Statics.noInitializer = 'Statics set via setter'; StaticsGeneric.noInitializer = 'StaticsGeneric set via setter'; // Initialized statics should contain their values. Expect.equals(1, withInitializer); Expect.equals(2, Statics.withInitializer); Expect.equals(3, StaticsGeneric.withInitializer); // Six new field resets from 3 setter calls and 3 getter calls. var expectedResets = resetFieldCount + 6; Expect.equals(expectedResets, dart.resetFields.length); dart.hotRestart(); resetFieldCount = dart.resetFields.length; // Uninitialized statics have been reset to their implicit null initial state. Expect.equals(null, noInitializer); Expect.equals(null, Statics.noInitializer); Expect.equals(null, StaticsGeneric.noInitializer); noInitializer = 'set via setter'; Statics.noInitializer = 'Statics set via setter'; StaticsGeneric.noInitializer = 'StaticsGeneric set via setter'; // All statics should contain their set values. Expect.equals('set via setter', noInitializer); Expect.equals('Statics set via setter', Statics.noInitializer); Expect.equals('StaticsGeneric set via setter', StaticsGeneric.noInitializer); Expect.equals(1, withInitializer); Expect.equals(2, Statics.withInitializer); Expect.equals(3, StaticsGeneric.withInitializer); // Six total new field resets despite getter and setter calls on the same // static fields. expectedResets = resetFieldCount + 6; Expect.equals(expectedResets, dart.resetFields.length); dart.hotRestart(); dart.hotRestart(); resetFieldCount = dart.resetFields.length; // All statics should contain their initial values. Expect.equals(null, noInitializer); Expect.equals(null, Statics.noInitializer); Expect.equals(null, StaticsGeneric.noInitializer); Expect.equals(1, withInitializer); Expect.equals(2, Statics.withInitializer); Expect.equals(3, StaticsGeneric.withInitializer); // Six new field resets from 6 getter calls. expectedResets = resetFieldCount + 6; Expect.equals(expectedResets, dart.resetFields.length); } void testStaticSetterOfConstField() { var resetFieldCount = dart.resetFields.length; // Static setters of const fields should behave according to spec. Expect.equals(StaticsSetter.counter, 0); Expect.equals(StaticsSetter.field, 5); StaticsSetter.field = 100; StaticsSetter.field = 100; StaticsSetter.field = 100; Expect.equals(StaticsSetter.field, 5); Expect.equals(StaticsSetter.counter, 3); // 2 new field resets: [StaticsSetter.counter] and [StaticsSetter.field]. var expectedResets = resetFieldCount + 2; Expect.equals(expectedResets, dart.resetFields.length); dart.hotRestart(); resetFieldCount = dart.resetFields.length; // Static setters of const fields should be properly reset. Expect.equals(StaticsSetter.counter, 0); Expect.equals(StaticsSetter.field, 5); StaticsSetter.field = 100; StaticsSetter.field = 100; StaticsSetter.field = 100; Expect.equals(StaticsSetter.field, 5); Expect.equals(StaticsSetter.counter, 3); // 2 new field resets: [StaticsSetter.counter] and [StaticsSetter.field]. expectedResets = resetFieldCount + 2; Expect.equals(expectedResets, dart.resetFields.length); dart.hotRestart(); dart.hotRestart(); resetFieldCount = dart.resetFields.length; // Invoke the static setter but not the getter. StaticsSetter.field2 = 100; StaticsSetter.field2 = 100; StaticsSetter.field2 = 100; // 1 new field reset: [StaticsSetter.field2]. expectedResets = resetFieldCount + 1; Expect.equals(expectedResets, dart.resetFields.length); }