| // Copyright (c) 2013, 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 'package:expect/async_helper.dart'; | |
| import 'package:expect/expect.dart'; | |
| import 'dart:async'; | |
| void main() { | |
| Expect.identical(Zone.root, Zone.current); // Sanity check. | |
| // Distinct objects only equal to each other. | |
| var wrap = Wrap(Object()); | |
| var wrap2 = Wrap(wrap.id); | |
| Expect.equals(wrap, wrap2); | |
| Expect.equals(wrap2, wrap); | |
| // Create a map with various key types. | |
| var barList = <Object?>[]; | |
| var zoneValues = <Object?, Object?>{ | |
| #foo: 499, | |
| "bar": barList, | |
| wrap: "wrap", | |
| 0: "zero!", | |
| null: "nullKey", | |
| }; | |
| Zone forked = Zone.current.fork(zoneValues: zoneValues); | |
| // Values are not present when not inside the zone. | |
| Expect.identical(Zone.root, Zone.current); | |
| Expect.isNull(Zone.current[#foo]); | |
| Expect.isNull(Zone.current["bar"]); | |
| Expect.isNull(Zone.current[wrap]); | |
| Expect.isNull(Zone.current[wrap2]); | |
| Expect.isNull(Zone.current[0]); | |
| Expect.isNull(Zone.current[null]); | |
| Expect.isNull(Zone.current["qux"]); // Not key in zoneValues at all. | |
| // Changing the original map has no effect after the zone is created. | |
| zoneValues[#foo] = -1; | |
| // Values are available directly on the zone. | |
| Expect.equals(499, forked[#foo]); | |
| Expect.identical(barList, forked["bar"]); | |
| Expect.equals("wrap", forked[wrap]); | |
| Expect.equals("wrap", forked[wrap2]); // Because wrap == wrap2. | |
| Expect.equals("zero!", forked[0]); | |
| Expect.equals("zero!", forked[0.0]); // Lookup uses equality. | |
| Expect.equals("zero!", forked[-0.0]); | |
| Expect.equals("nullKey", forked[null]); | |
| Expect.isNull(forked["qux"]); // Wasn't added as key. | |
| forked.run(() { | |
| // Changing zone doesn't change what the zone does. | |
| Expect.identical(forked, Zone.current); // Sanity check. | |
| // Values are present on current when inside zone. | |
| Expect.equals(499, Zone.current[#foo]); | |
| Expect.identical(barList, Zone.current["bar"]); | |
| Expect.equals("wrap", Zone.current[wrap]); | |
| Expect.equals("wrap", Zone.current[wrap2]); | |
| Expect.equals("zero!", Zone.current[0]); | |
| Expect.equals("zero!", Zone.current[0.0]); // Lookup uses equality. | |
| Expect.equals("zero!", Zone.current[-0.0]); | |
| Expect.equals("nullKey", Zone.current[null]); | |
| Expect.isNull(Zone.current["qux"]); | |
| // And doesn't change what the root zone does. | |
| Expect.isNull(Zone.root[#foo]); | |
| Expect.isNull(Zone.root["bar"]); | |
| Expect.isNull(Zone.root[wrap]); | |
| Expect.isNull(Zone.root[wrap2]); | |
| Expect.isNull(Zone.root[0]); | |
| Expect.isNull(Zone.root[null]); | |
| Expect.isNull(Zone.root["qux"]); | |
| }); | |
| // Values are still not present when not inside the zone. | |
| Expect.identical(Zone.root, Zone.current); | |
| Expect.isNull(Zone.current[#foo]); | |
| Expect.isNull(Zone.current["bar"]); | |
| Expect.isNull(Zone.current[wrap]); | |
| Expect.isNull(Zone.current[wrap2]); | |
| Expect.isNull(Zone.current[0]); | |
| Expect.isNull(Zone.current[null]); | |
| Expect.isNull(Zone.current["qux"]); | |
| // Modifying the stored values work as expected. | |
| barList.add(42); // Updates the list stored in the zone. | |
| Expect.listEquals([42], forked["bar"]); | |
| Expect.identical(barList, forked["bar"]); | |
| forked.run(() { | |
| Expect.listEquals([42], Zone.current["bar"]); | |
| Expect.identical(zoneValues["bar"], Zone.current["bar"]); | |
| }); | |
| // Creating a further nested zone with new values allows keeping, overriding, | |
| // and shadowing existing values from the outer zone. | |
| var newZoneValues = <Object?, Object?>{ | |
| #foo: -499, // Values can be overridden. | |
| "qux": 99, // Values can be added | |
| // Keys shadow everything they are equal to. | |
| wrap2: "wrap2", | |
| 0.0: null, // Values can be changed to null. | |
| // Not shadowing the `null` key. | |
| }; | |
| Zone forkedChild = forked.fork(zoneValues: newZoneValues); | |
| // New values available on zone. | |
| Expect.equals(-499, forkedChild[#foo]); // Overridden. | |
| Expect.isNull(forkedChild[0]); // Overridden to null. | |
| Expect.isNull(forkedChild[0.0]); // Overridden to null. | |
| Expect.isNull(forkedChild[-0.0]); // Overridden to null. | |
| Expect.equals("wrap2", forkedChild[wrap]); // Overridden by equal. | |
| Expect.equals("wrap2", forkedChild[wrap2]); // Overridden by equal. | |
| Expect.equals("nullKey", forkedChild[null]); // Inherited. | |
| Expect.identical(zoneValues["bar"], forkedChild["bar"]); // Inherited. | |
| Expect.equals(99, forkedChild["qux"]); // Added. | |
| forkedChild.run(() { | |
| Expect.identical(forkedChild, Zone.current); // Sanity check. | |
| Expect.identical(forked, forkedChild.parent); | |
| // New values available on current zone when the zone is current. | |
| Expect.equals(-499, Zone.current[#foo]); | |
| Expect.isNull(Zone.current[0]); | |
| Expect.isNull(Zone.current[0.0]); | |
| Expect.isNull(Zone.current[-0.0]); | |
| Expect.equals("wrap2", Zone.current[wrap]); | |
| Expect.equals("wrap2", Zone.current[wrap2]); | |
| Expect.equals("nullKey", Zone.current[null]); | |
| Expect.identical(zoneValues["bar"], Zone.current["bar"]); | |
| Expect.equals(99, Zone.current["qux"]); | |
| }); | |
| // Parent zone values are unchanged. | |
| Expect.equals(499, forked[#foo]); | |
| Expect.identical(barList, forked["bar"]); | |
| Expect.equals("wrap", forked[wrap]); | |
| Expect.equals("wrap", forked[wrap2]); | |
| Expect.equals("zero!", forked[0]); | |
| Expect.equals("zero!", forked[0.0]); // Lookup uses equality. | |
| Expect.equals("zero!", forked[-0.0]); | |
| Expect.equals("nullKey", forked[null]); | |
| Expect.isNull(forked["qux"]); | |
| } | |
| // Objects equal to other wraps with the same ID. | |
| class Wrap { | |
| final Object id; | |
| Wrap(this.id); | |
| int get hashCode => id.hashCode; | |
| bool operator ==(Object other) => (other is Wrap) && id == other.id; | |
| } |