| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of dart.core; | |
| 6 | |
| 7 /** | |
| 8 * An [Expando] allows adding new properties to objects. | |
| 9 * | |
| 10 * Does not work on numbers, strings, booleans or null. | |
| 11 * | |
| 12 * An `Expando` does not hold on to the added property value after an object | |
| 13 * becomes inacessible. | |
| 14 * | |
| 15 * Since you can always create a new number that is identical to an existing | |
| 16 * number, it means that an expando property on a number could never be | |
| 17 * released. To avoid this, expando properties cannot be added to numbers. | |
| 18 * The same argument applies to strings, booleans and null, which also have | |
| 19 * literals that evaluate to identical values when they occur more than once. | |
| 20 * | |
| 21 * There is no restriction on other classes, even for compile time constant | |
| 22 * objects. Be careful if adding expando properties to compile time constants, | |
| 23 * since they will stay alive forever. | |
| 24 */ | |
| 25 class Expando<T> { | |
| 26 | |
| 27 /** | |
| 28 * The name of the this [Expando] as passed to the constructor. If | |
| 29 * no name was passed to the constructor, the name is [:null:]. | |
| 30 */ | |
| 31 final String name; | |
| 32 | |
| 33 /** | |
| 34 * Creates a new [Expando]. The optional name is only used for | |
| 35 * debugging purposes and creating two different [Expando]s with the | |
| 36 * same name yields two [Expando]s that work on different properties | |
| 37 * of the objects they are used on. | |
| 38 */ | |
| 39 Expando([String name]) : this.name = name; | |
| 40 | |
| 41 /** | |
| 42 * Expando toString method override. | |
| 43 */ | |
| 44 String toString() => "Expando:$name"; | |
| 45 | |
| 46 /** | |
| 47 * Gets the value of this [Expando]'s property on the given | |
| 48 * object. If the object hasn't been expanded, the method returns | |
| 49 * [:null:]. | |
| 50 * | |
| 51 * The object must not be a number, a string, a boolean or null. | |
| 52 */ | |
| 53 T operator[](Object object) { | |
| 54 var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME); | |
| 55 return (values == null) ? null : Primitives.getProperty(values, _getKey()); | |
| 56 } | |
| 57 | |
| 58 /** | |
| 59 * Sets the value of this [Expando]'s property on the given | |
| 60 * object. Properties can effectively be removed again by setting | |
| 61 * their value to null. | |
| 62 * | |
| 63 * The object must not be a number, a string, a boolean or null. | |
| 64 */ | |
| 65 void operator[]=(Object object, T value) { | |
| 66 var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME); | |
| 67 if (values == null) { | |
| 68 values = new Object(); | |
| 69 Primitives.setProperty(object, _EXPANDO_PROPERTY_NAME, values); | |
| 70 } | |
| 71 Primitives.setProperty(values, _getKey(), value); | |
| 72 } | |
| 73 | |
| 74 String _getKey() { | |
| 75 String key = Primitives.getProperty(this, _KEY_PROPERTY_NAME); | |
| 76 if (key == null) { | |
| 77 key = "expando\$key\$${_keyCount++}"; | |
| 78 Primitives.setProperty(this, _KEY_PROPERTY_NAME, key); | |
| 79 } | |
| 80 return key; | |
| 81 } | |
| 82 | |
| 83 static const String _KEY_PROPERTY_NAME = 'expando\$key'; | |
| 84 | |
| 85 static const String _EXPANDO_PROPERTY_NAME = 'expando\$values'; | |
| 86 | |
| 87 static int _keyCount = 0; | |
| 88 | |
| 89 } | |
| OLD | NEW |