Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: sdk/lib/isolate/mangler.dart

Issue 11308154: Stream isolates. (Closed) Base URL: https://dart.googlecode.com/svn/experimental/lib_v2/dart
Patch Set: Fixes and test. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 class _IsolateEncoder {
6 final manglingToken;
7 // TODO(floitsch): switch to identity set.
8 final Map _encoded = new Map();
Anton Muhin 2012/11/25 10:23:16 why not = {}?
floitsch 2012/11/28 14:13:18 If I'm not wrong that would be a Map<String, dynam
9 final Map _visiting = new Map();
10 final Function _mangle;
11 static const int _REFERENCE = 0;
12 static const int _DECLARATION = 1;
13 static const int _ESCAPED = 2;
14 static const int _MANGLED = 3;
15
16 _IsolateEncoder(this.manglingToken, mangle(data))
Anton Muhin 2012/11/25 10:23:16 why not this._mangle here?
floitsch 2012/11/28 14:13:18 This way I get a little bit of typing. The field i
17 : this._mangle = mangle;
18
19 encode(var data) {
20 if (data is num || data is String || data is bool || data == null) {
21 return data;
22 }
23
24 if (_encoded.containsKey(data)) return _encoded[data];
25 if (_visiting.containsKey(data)) {
26 // Self reference.
27 var selfReference = _visiting[data];
28 if (selfReference == data) {
29 // Nobody used the self-reference yet.
30 selfReference = _createReference();
31 _visiting[data] = selfReference;
32 }
33 return selfReference;
34 }
35 _visiting[data] = data;
36
37 var result;
38
39 if (data is List) {
40 bool hasBeenDuplicated = false;
41 result = data;
42 for (int i = 0; i < data.length; i++) {
43 var mangled = encode(data[i]);
44 if (mangled != data[i] && !hasBeenDuplicated) {
45 result = new List(data.length);
46 for (int j = 0; j < i; j++) {
47 result[j] = data[j];
48 }
49 hasBeenDuplicated = true;
50 }
51 if (hasBeenDuplicated) {
52 result[i] = mangled;
53 }
54 }
55 result = _escapeIfNecessary(result);
56 } else if (data is Set) {
57 // TODO(floitsch): should we accept sets?
58 bool needsCopy = false;
59 for (var entry in data) {
60 var encoded = encode(entry);
61 if (encoded != entry) {
62 needsCopy = true;
63 break;
64 }
65 }
66 result = data;
67 if (needsCopy) {
68 result = new Set();
69 data.forEach((entry) {
70 result.add(encode(entry));
71 });
72 }
73 } else if (data is Map) {
74 bool needsCopy = false;
75 data.forEach((key, value) {
76 var encodedKey = encode(key);
77 var encodedValue = encode(value);
78 if (encodedKey != key) needsCopy = true;
79 if (encodedValue != value) needsCopy = true;
80 });
81 result = data;
82 if (needsCopy) {
83 result = new Map();
84 data.forEach((key, value) {
85 result[encode(key)] = encode(value);
86 });
87 }
88 } else {
89 // We don't handle self-references for user data.
90 // TODO(floitsch): we could keep the reference and throw when we see it
91 // again. However now the user has at least the possibility to do
92 // cyclic data-structures.
93 _visiting.remove(data);
94 result = _mangle(data);
95 if (result != data) {
96 result = _wrapMangled(encode(result));
97 }
98 }
99
100 var selfReference = _visiting[data];
101 if (selfReference != null && selfReference != data) {
102 // A self-reference has been used.
103 result = _declareReference(selfReference, result);
104 }
105 _encoded[data] = result;
106
107 _visiting.remove(data);
108 return result;
109 }
110
111 _createReference() => [manglingToken, _REFERENCE];
112 _declareReference(reference, data) {
113 return [manglingToken, _DECLARATION, reference, data];
114 }
115
116 _wrapMangled(data) => [manglingToken, _MANGLED, data];
117 _escapeIfNecessary(List list) {
118 if (!list.isEmpty && list[0] == manglingToken) {
119 return [manglingToken, _ESCAPED, list];
120 } else {
121 return list;
122 }
123 }
124 }
125
126 class _IsolateDecoder {
127 final manglingToken;
128 final Map _decoded = new Map();
129 final Function _unmangle;
130 static const int _REFERENCE = _IsolateEncoder._REFERENCE;
131 static const int _DECLARATION = _IsolateEncoder._DECLARATION;
132 static const int _ESCAPED = _IsolateEncoder._ESCAPED;
133 static const int _MANGLED = _IsolateEncoder._MANGLED;
134
135 _IsolateDecoder(this.manglingToken, unmangle(data))
136 : this._unmangle = unmangle;
137
138 decode(var data) {
139 if (data is num || data is String || data is bool || data == null) {
140 return data;
141 }
142
143 if (_decoded.containsKey(data)) return _decoded[data];
144
145 if (_isDeclaration(data)) {
146 var reference = _extractReference(data);
147 var declared = _extractDeclared(data);
148 return _decodeObject(declared, reference);
149 } else {
150 return _decodeObject(data, null);
151 }
152 }
153
154 _decodeObject(data, reference) {
155 if (_decoded.containsKey(data)) {
156 assert(reference == null);
157 return _decoded[data];
158 }
159
160 // If the data was a reference then we would have found it in the _decoded
161 // map.
162 assert(!_isReference(data));
163
164 var result;
165 if (_isMangled(data)) {
166 assert(reference == null);
167 List mangled = _extractMangled(data);
168 var decoded = decode(mangled);
169 result = _unmangle(decoded);
170 } else if (data is List) {
171 if (_isEscaped(data)) data = _extractEscaped(data);
172 assert(!_isMarked(data));
173 result = data;
174 bool hasBeenDuplicated = false;
175 List duplicate() {
176 assert(!hasBeenDuplicated);
177 result = new List();
178 result.length = data.length;
179 if (reference != null) _decoded[reference] = result;
180 hasBeenDuplicated = true;
181 }
182
183 if (reference != null) duplicate();
184 for (int i = 0; i < data.length; i++) {
185 var decoded = decode(data[i]);
186 if (decoded != data[i] && !hasBeenDuplicated) {
187 duplicate();
188 for (int j = 0; j < i; j++) {
189 result[j] = data[j];
190 }
191 }
192 if (hasBeenDuplicated) {
193 result[i] = decoded;
194 }
195 }
196 } else if (data is Set) {
197 bool needsCopy = reference != null;
198 if (!needsCopy) {
199 for (var entry in data) {
200 var decoded = decode(entry);
201 if (decoded != entry) {
202 needsCopy = true;
203 break;
204 }
205 }
206 }
207 result = data;
208 if (needsCopy) {
209 result = new Set();
210 if (reference != null) _decoded[reference] = result;
211 for (var entry in data) {
212 result.add(decode(entry));
213 }
214 }
215 } else if (data is Map) {
216 bool needsCopy = reference != null;
217 if (!needsCopy) {
218 data.forEach((key, value) {
219 var decodedKey = decode(key);
220 var decodedValue = decode(value);
221 if (decodedKey != key) needsCopy = true;
222 if (decodedValue != value) needsCopy = true;
223 });
224 }
225 result = data;
226 if (needsCopy) {
227 result = new Map();
228 if (reference != null) _decoded[reference] = result;
229 data.forEach((key, value) {
230 result[decode(key)] = decode(value);
231 });
232 }
233 } else {
234 result = data;
235 }
236 _decoded[data] = result;
237 return result;
238 }
239
240 _isMarked(data) {
241 if (data is List && !data.isEmpty && data[0] == manglingToken) {
242 assert(data.length > 1);
243 return true;
244 }
245 return false;
246 }
247 _isReference(data) => _isMarked(data) && data[1] == _REFERENCE;
248 _isDeclaration(data) => _isMarked(data) && data[1] == _DECLARATION;
249 _isMangled(data) => _isMarked(data) && data[1] == _MANGLED;
250 _isEscaped(data) => _isMarked(data) && data[1] == _ESCAPED;
251
252 _extractReference(declaration) {
253 assert(_isDeclaration(declaration));
254 return declaration[2];
255 }
256 _extractDeclared(declaration) {
257 assert(_isDeclaration(declaration));
258 return declaration[3];
259 }
260 _extractMangled(wrappedMangled) {
261 assert(_isMangled(wrappedMangled));
262 return wrappedMangled[2];
263 }
264 _extractEscaped(data) {
265 assert(_isEscaped(data));
266 return data[2];
267 }
268 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698