@@ -106,37 +106,61 @@ class Function {
106
106
// Patch for Expando implementation.
107
107
@patch
108
108
class Expando <T > {
109
+ static const String _EXPANDO_PROPERTY_NAME = 'expando\$ values' ;
110
+
111
+ // Incremented to make unique keys.
112
+ static int _keyCount = 0 ;
113
+
114
+ // Stores either a JS WeakMap or a "unique" string key.
115
+ final Object _jsWeakMapOrKey;
116
+
109
117
@patch
110
- Expando ([String name]) : this .name = name;
118
+ Expando ([String name])
119
+ : this .name = name,
120
+ _jsWeakMapOrKey = JS ('bool' , 'typeof WeakMap == "function"' )
121
+ ? JS ('=Object|Null' , 'new WeakMap()' )
122
+ : _createKey ();
111
123
112
124
@patch
113
125
T operator [](Object object) {
114
- var values = Primitives .getProperty (object, _EXPANDO_PROPERTY_NAME );
115
- return (values == null ) ? null : Primitives .getProperty (values, _getKey ());
126
+ if (_jsWeakMapOrKey is ! String ) {
127
+ _checkType (object); // WeakMap doesn't check on reading, only writing.
128
+ return JS ('' , '#.get(#)' , _jsWeakMapOrKey, object);
129
+ }
130
+ return _getFromObject (_jsWeakMapOrKey, object);
116
131
}
117
132
118
133
@patch
119
134
void operator []= (Object object, T value) {
135
+ if (_jsWeakMapOrKey is ! String ) {
136
+ JS ('void' , '#.set(#, #)' , _jsWeakMapOrKey, object, value);
137
+ } else {
138
+ _setOnObject (_jsWeakMapOrKey, object, value);
139
+ }
140
+ }
141
+
142
+ static Object _getFromObject (String key, Object object) {
143
+ var values = Primitives .getProperty (object, _EXPANDO_PROPERTY_NAME );
144
+ return (values == null ) ? null : Primitives .getProperty (values, key);
145
+ }
146
+
147
+ static void _setOnObject (String key, Object object, Object value) {
120
148
var values = Primitives .getProperty (object, _EXPANDO_PROPERTY_NAME );
121
149
if (values == null ) {
122
150
values = new Object ();
123
151
Primitives .setProperty (object, _EXPANDO_PROPERTY_NAME , values);
124
152
}
125
- Primitives .setProperty (values, _getKey () , value);
153
+ Primitives .setProperty (values, key , value);
126
154
}
127
155
128
- String _getKey () {
129
- String key = Primitives .getProperty (this , _KEY_PROPERTY_NAME );
130
- if (key == null ) {
131
- key = "expando\$ key\$ ${_keyCount ++}" ;
132
- Primitives .setProperty (this , _KEY_PROPERTY_NAME , key);
156
+ static String _createKey () => "expando\$ key\$ ${_keyCount ++}" ;
157
+
158
+ static _checkType (object) {
159
+ if (object == null || object is bool || object is num || object is String ) {
160
+ throw new ArgumentError .value (object,
161
+ "Expandos are not allowed on strings, numbers, booleans or null" );
133
162
}
134
- return key;
135
163
}
136
-
137
- static const String _KEY_PROPERTY_NAME = 'expando\$ key' ;
138
- static const String _EXPANDO_PROPERTY_NAME = 'expando\$ values' ;
139
- static int _keyCount = 0 ;
140
164
}
141
165
142
166
@patch
0 commit comments