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

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: Removed hack and improved doc. 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 final Map _encoded = new Map();
8 final Map _visiting = new Map();
9 final Function _mangle;
10 static const int _REFERENCE = 0;
11 static const int _DECLARATION = 1;
12 static const int _ESCAPED = 2;
13 static const int _MANGLED = 3;
14
15 _IsolateEncoder(this.manglingToken, mangle(data))
16 : this._mangle = mangle;
17
18 encode(var data) {
19 if (data is num || data is String || data is bool || data == null) {
20 return data;
21 }
22
23 if (_encoded.containsKey(data)) return _encoded[data];
Lasse Reichstein Nielsen 2012/11/22 10:23:15 This uses equality, not identiity. We should use a
floitsch 2012/11/22 20:06:12 Added TODO.
24 if (_visiting.containsKey(data)) {
25 // Self reference.
26 var selfReference = _visiting[data];
27 if (selfReference == data) {
28 // Nobody used the self-reference yet.
29 selfReference = _createReference();
30 _visiting[data] = selfReference;
31 }
32 return selfReference;
33 }
34
35 var result;
36
37 if (data is List) {
38 bool hasBeenDuplicated = false;
39 result = data;
40 for (int i = 0; i < data.length; i++) {
41 var mangled = encode(data[i]);
42 if (mangled != data[i] && !hasBeenDuplicated) {
43 result = new List(data.length);
44 for (int j = 0; j < i; j++) {
45 result[j] = data[j];
46 }
Lasse Reichstein Nielsen 2012/11/22 10:23:15 hasBeenDuplicated = true; ?
floitsch 2012/11/22 20:06:12 Done.
47 }
48 if (hasBeenDuplicated) {
49 result[i] = mangled;
50 }
51 }
52 result = _escapeIfNecessary(result);
53 } else if (data is Set) {
54 bool needsCopy = false;
55 data.forEach((entry) {
56 var encoded = encode(entry);
57 if (encoded != entry) needsCopy = true;
Lasse Reichstein Nielsen 2012/11/22 10:23:15 and break. No need to test more after the first mo
floitsch 2012/11/22 20:06:12 Duplicate encoding is not a problem since they are
58 });
59 result = data;
60 if (needsCopy) {
61 result = new Set();
62 data.forEach((entry) {
63 result.add(encode(entry));
64 });
65 }
66 } else if (data is Map) {
67 bool needsCopy = false;
68 data.forEach((key, value) {
69 var encodedKey = encode(key);
70 var encodedValue = encode(value);
71 if (encodedKey != key) needsCopy = true;
72 if (encodedValue != value) needsCopy = true;
Lasse Reichstein Nielsen 2012/11/22 10:23:15 And break after the first encoding is found.
floitsch 2012/11/22 20:06:12 cannot. This is a map.forEach.
Lasse Reichstein Nielsen 2012/11/23 12:12:38 True. You would need to iterate the keys instead.
73 });
74 result = data;
75 if (needsCopy) {
76 result = new Map();
77 data.forEach((key, value) {
78 result[encode(key)] = encode(value);
79 });
80 }
81 } else {
82 // We don't handle self-references for user data.
83 _visiting.remove(data);
Lasse Reichstein Nielsen 2012/11/22 10:23:15 Consider keeping it and throwing if you see the sa
floitsch 2012/11/22 20:06:12 Added TODO.
84 result = _mangle(data);
85 if (result != data) {
86 result = _wrapMangled(encode(result));
87 }
88 }
89
90 var selfReference = _visiting[data];
91 if (selfReference != null && selfReference != data) {
92 // A self-reference has been used.
93 result = encode(_declareReference(selfReference, data));
94 }
95 _encoded[data] = result;
96
97 _visiting.remove(data);
98 return result;
99 }
100
101 _createReference() => [manglingToken, _REFERENCE];
Lasse Reichstein Nielsen 2012/11/22 10:23:15 What is it a reference to? I.e., how can you tell
floitsch 2012/11/22 20:06:12 Done.
102 _declareReference(reference, data) {
103 return [manglingToken, _DECLARATION, reference, data];
104 }
105
106 _wrapMangled(data) => [manglingToken, _MANGLED, data];
107 _escapeIfNecessary(List list) {
108 if (!list.isEmpty && list[0] == manglingToken) {
109 return [manglingToken, _ESCAPED, list];
Lasse Reichstein Nielsen 2012/11/22 10:23:15 Then the list contents are not encoded. You should
floitsch 2012/11/22 20:06:12 _escapeIfNecessary is only called on a encoded lis
Lasse Reichstein Nielsen 2012/11/23 12:12:38 Ah, true.
110 } else {
111 return list;
112 }
113 }
114 }
115
116 class _IsolateDecoder {
117 final manglingToken;
118 final Map _decoded = new Map();
119 final Function _unmangle;
120 static const int _REFERENCE = IsolateEncoder._REFERENCE;
121 static const int _DECLARATION = IsolateEncoder._DECLARATION;
122 static const int _ESCAPED = IsolateEncoder._ESCAPED;
123 static const int _MANGLED = IsolateEncoder._MANGLED;
124
125 _IsolateDecoder(this.manglingToken, unmangle(data))
126 : this._unmangle = unmangle;
127
128 decode(var data) {
129 if (data is num || data is String || data is bool || data == null) {
130 return data;
131 }
132
133 if (_decoded.containsKey(data)) return _decoded[data];
Lasse Reichstein Nielsen 2012/11/22 10:23:15 if 'data' comes from a JSON.parse, it's not equal
floitsch 2012/11/22 20:06:12 data comes from the isolate-communication. These g
134
135 if (_isDeclaration(data)) {
136 var reference = _extractReference(data);
137 var declared = _extractDeclared(data);
138 return _decodeObject(declared, reference);
Lasse Reichstein Nielsen 2012/11/22 10:23:15 So the reference is just a list: [magic#, REFERENC
floitsch 2012/11/22 20:06:12 This works because of the guarantees of the send/r
139 } else {
140 return _decodeObject(data, null);
141 }
142 }
143
144 _decodeObject(data, reference) {
145 if (_decoded.containsKey(data)) {
Lasse Reichstein Nielsen 2012/11/22 10:23:15 I don't think this lookup will ever succeed if the
floitsch 2012/11/22 20:06:12 which it hasn't.
146 assert(reference == null);
147 return _decoded[data];
148 }
149
150 // If the data was a reference then we would have found it in the _decoded
151 // map.
Lasse Reichstein Nielsen 2012/11/22 10:23:15 I find that unlikely.
floitsch 2012/11/22 20:06:12 see above.
152 assert(!_isReference(data));
153
154 var result;
155 if (_isMangled(data)) {
156 assert(reference == null);
157 List mangled = _extractMangled(data);
158 var decoded = decode(mangled);
159 result = _unmangle(decoded);
160 } else if (data is List) {
161 if (_isEscaped(data)) data = _extractEscaped(data);
Lasse Reichstein Nielsen 2012/11/22 10:23:15 Here you decode the escaped data, even if it wasn'
floitsch 2012/11/22 20:06:12 data cannot be mangled and escaped at the same tim
Lasse Reichstein Nielsen 2012/11/23 12:12:38 Ack, isMangled is not the same as isMarked.
162 assert(!_isMarked(data));
163 result = data;
164 bool hasBeenDuplicated = false;
165 List duplicate() {
166 assert(!hasBeenDuplicated);
167 result = new List();
168 result.length = data.length;
169 if (reference != null) _decoded[reference] = result;
170 hasBeenDuplicated = true;
171 }
172
173 if (reference != null) duplicate();
174 for (int i = 0; i < data.length; i++) {
175 var decoded = decode(data[i]);
176 if (decoded != data[i] && !hasBeenDuplicated) {
177 duplicate();
178 for (int j = 0; j < i; j++) {
179 result[j] = data[j];
180 }
181 }
182 if (hasBeenDuplicated) {
183 result[i] = decoded;
184 }
185 }
186 } else if (data is Set) {
187 bool needsCopy = reference != null;
188 if (!needsCopy) {
189 data.forEach((entry) {
190 var decoded = decode(entry);
191 if (decoded != entry) needsCopy = true;
Lasse Reichstein Nielsen 2012/11/22 10:23:15 and break.
floitsch 2012/11/22 20:06:12 Done.
192 });
193 }
194 result = data;
195 if (needsCopy) {
196 result = new Set();
197 if (reference != null) _decoded[reference] = result;
198 data.forEach((entry) {
199 result.add(decode(entry));
200 });
201 }
202 } else if (data is Map) {
203 bool needsCopy = reference != null;
204 if (!needsCopy) {
205 data.forEach((key, value) {
206 var decodedKey = decode(key);
207 var decodedValue = decode(value);
208 if (decodedKey != key) needsCopy = true;
209 if (decodedValue != value) needsCopy = true;
210 });
211 }
212 result = data;
213 if (needsCopy) {
214 result = new Map();
215 if (reference != null) _decoded[reference] = result;
216 data.forEach((key, value) {
217 result[decode(key)] = decode(value);
218 });
219 }
220 } else {
221 result = data;
222 }
223 _decoded[data] = result;
224 return result;
225 }
226
227 _isMarked(data)
228 => data is List && !data.isEmpty && data[0] == manglingToken;
Lasse Reichstein Nielsen 2012/11/22 10:23:15 '!data.isEmpty' -> 'data.length >= 2' or you can't
floitsch 2012/11/22 20:06:12 added assert.
229 _isReference(data) => _isMarked(data) && data[1] == _REFERENCE;
230 _isDeclaration(data) => _isMarked(data) && data[1] == _DECLARATION;
231 _isMangled(data) => _isMarked(data) && data[1] == _MANGLED;
232 _isEscaped(data) => _isMarked(data) && data[1] == _ESCAPED;
233
234 _extractReference(declaration) {
235 assert(_isDeclaration(declaration));
236 return declaration[2];
237 }
238 _extractDeclared(declaration) {
239 assert(_isDeclaration(declaration));
240 return declaration[3];
241 }
242 _extractMangled(wrappedMangled) {
243 assert(_isMangled(wrappedMangled));
244 return wrappedMangled[2];
245 }
246 _extractEscaped(data) {
247 assert(_isEscaped(data));
248 return data[2];
249 }
250 }
OLDNEW
« sdk/lib/isolate/isolate_stream.dart ('K') | « sdk/lib/isolate/isolate_stream.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698