OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // Bootstrap support for Dart scripts on the page as this script. | 5 // Bootstrap support for Dart scripts on the page as this script. |
6 if (navigator.webkitStartDart) { | 6 if (navigator.webkitStartDart) { |
7 if (!navigator.webkitStartDart()) { | 7 if (!navigator.webkitStartDart()) { |
8 document.body.innerHTML = 'This build has expired. Please download a new Da rtium at http://www.dartlang.org/dartium/index.html'; | 8 document.body.innerHTML = 'This build has expired. Please download a new Da rtium at http://www.dartlang.org/dartium/index.html'; |
9 } | 9 } |
10 } else { | 10 } else { |
(...skipping 28 matching lines...) Expand all Loading... | |
39 // --------------------------------------------------------------------------- | 39 // --------------------------------------------------------------------------- |
40 function SendPortSync() { | 40 function SendPortSync() { |
41 } | 41 } |
42 | 42 |
43 function ReceivePortSync() { | 43 function ReceivePortSync() { |
44 this.id = ReceivePortSync.id++; | 44 this.id = ReceivePortSync.id++; |
45 ReceivePortSync.map[this.id] = this; | 45 ReceivePortSync.map[this.id] = this; |
46 } | 46 } |
47 | 47 |
48 (function() { | 48 (function() { |
49 function RefTable(name) { | |
50 // TODO(vsm): Fix leaks, particularly in dart2js case. | |
51 this.name = name; | |
52 this.map = {}; | |
53 this.id = 0; | |
54 this.initialized = false; | |
55 } | |
56 | |
57 RefTable.prototype.nextId = function () { return this.id++; } | |
58 | |
59 RefTable.prototype.makeRef = function (obj) { | |
60 this.initializeOnce(); | |
61 // TODO(vsm): Cache refs for each obj. | |
62 var ref = this.name + '-' + this.nextId(); | |
63 this.map[ref] = obj; | |
64 return ref; | |
65 } | |
66 | |
67 RefTable.prototype.initializeOnce = function () { | |
68 if (!this.initialized) { | |
69 this.initialize(); | |
70 } | |
71 this.initialized = true; | |
72 } | |
73 | |
74 // Overridable initialization on first use hook. | |
75 RefTable.prototype.initialize = function () {} | |
76 | |
77 RefTable.prototype.get = function (ref) { | |
78 return this.map[ref]; | |
79 } | |
80 | |
81 function FunctionRefTable() {} | |
82 | |
83 FunctionRefTable.prototype = new RefTable('func-ref'); | |
84 | |
85 FunctionRefTable.prototype.initialize = function () { | |
86 var receivePort = new ReceivePortSync(); | |
87 map = this.map; | |
88 receivePort.receive(function (message) { | |
89 var id = message[0]; | |
90 var args = message[1]; | |
91 var f = map[id]; | |
92 // TODO(vsm): Should we capture this automatically? | |
93 return f.apply(null, args); | |
94 }); | |
95 this.port = receivePort.toSendPort(); | |
96 } | |
97 | |
98 var functionRefTable = new FunctionRefTable(); | |
99 | |
100 function JSRefTable() {} | |
101 | |
102 JSRefTable.prototype = new RefTable('js-ref'); | |
103 | |
104 var jsRefTable = new JSRefTable(); | |
105 | |
106 function DartProxy(id) { | |
107 // TODO(vsm): Set isolate id. | |
108 this.id = id; | |
109 } | |
110 | |
111 function serialize(message) { | 49 function serialize(message) { |
112 var visited = []; | 50 var visited = []; |
113 function checkedSerialization(obj, serializer) { | 51 function checkedSerialization(obj, serializer) { |
114 // Implementation detail: for now use linear search. | 52 // Implementation detail: for now use linear search. |
115 // Another option is expando, but it may prohibit | 53 // Another option is expando, but it may prohibit |
116 // VM optimizations (like putting object into slow mode | 54 // VM optimizations (like putting object into slow mode |
117 // on property deletion.) | 55 // on property deletion.) |
118 var id = visited.indexOf(obj); | 56 var id = visited.indexOf(obj); |
119 if (id != -1) return [ 'ref', id ]; | 57 if (id != -1) return [ 'ref', id ]; |
120 var id = visited.length; | 58 var id = visited.length; |
(...skipping 15 matching lines...) Expand all Loading... | |
136 values[i] = doSerialize(message[i]); | 74 values[i] = doSerialize(message[i]); |
137 } | 75 } |
138 return [ 'list', id, values ]; | 76 return [ 'list', id, values ]; |
139 }); | 77 }); |
140 } else if (message instanceof LocalSendPortSync) { | 78 } else if (message instanceof LocalSendPortSync) { |
141 return [ 'sendport', 'nativejs', message.receivePort.id ]; | 79 return [ 'sendport', 'nativejs', message.receivePort.id ]; |
142 } else if (message instanceof DartSendPortSync) { | 80 } else if (message instanceof DartSendPortSync) { |
143 return [ 'sendport', 'dart', message.isolateId, message.portId ]; | 81 return [ 'sendport', 'dart', message.isolateId, message.portId ]; |
144 } else if (message instanceof Function) { | 82 } else if (message instanceof Function) { |
145 return [ 'funcref', functionRefTable.makeRef(message), | 83 return [ 'funcref', functionRefTable.makeRef(message), |
146 doSerialize(functionRefTable.port) ]; | 84 doSerialize(functionRefTable.sendPort) ]; |
147 } else if (message instanceof DartProxy) { | 85 } else if (message instanceof DartProxy) { |
148 return [ 'objref', 'dart', message.id ]; | 86 return [ 'objref', message._id, doSerialize(message._port) ]; |
Emily Fortuna
2012/08/23 21:04:35
An overall comment for doSerialize about the forma
| |
149 } else if (message.__proto__ != {}.__proto__) { | 87 } else if (message.__proto__ != {}.__proto__) { |
150 // TODO(vsm): Is the above portable and what we want? | 88 // TODO(vsm): Is the above portable and what we want? |
151 // Proxy non-map Objects. | 89 // Proxy non-map Objects. |
152 return [ 'objref', 'nativejs', jsRefTable.makeRef(message) ]; | 90 return [ 'objref', jsRefTable.makeRef(message), |
91 doSerialize(jsRefTable.sendPort) ]; | |
153 } else { | 92 } else { |
154 return checkedSerialization(message, function(id) { | 93 return checkedSerialization(message, function(id) { |
155 var keys = Object.getOwnPropertyNames(message); | 94 var keys = Object.getOwnPropertyNames(message); |
156 var values = new Array(keys.length); | 95 var values = new Array(keys.length); |
157 for (var i = 0; i < keys.length; i++) { | 96 for (var i = 0; i < keys.length; i++) { |
158 values[i] = doSerialize(message[keys[i]]); | 97 values[i] = doSerialize(message[keys[i]]); |
159 } | 98 } |
160 return [ 'map', id, keys, values ]; | 99 return [ 'map', id, keys, values ]; |
161 }); | 100 }); |
162 } | 101 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 | 164 |
226 function deserializeFunction(message) { | 165 function deserializeFunction(message) { |
227 var ref = message[1]; | 166 var ref = message[1]; |
228 var sendPort = deserializeSendPort(message[2]); | 167 var sendPort = deserializeSendPort(message[2]); |
229 // Number of arguments is not used as of now | 168 // Number of arguments is not used as of now |
230 // we cannot find it out for Dart function in pure Dart. | 169 // we cannot find it out for Dart function in pure Dart. |
231 return _makeFunctionFromRef(ref, sendPort); | 170 return _makeFunctionFromRef(ref, sendPort); |
232 } | 171 } |
233 | 172 |
234 function deserializeProxy(message) { | 173 function deserializeProxy(message) { |
235 var tag = message[1]; | 174 var id = message[1]; |
236 if (tag == 'nativejs') { | 175 var port = deserializeSendPort(message[2]); |
237 var id = message[2]; | 176 if (port instanceof LocalSendPortSync) { |
238 return jsRefTable.map[id]; | 177 return jsRefTable.map[id]; |
239 } else if (tag == 'dart') { | 178 } else if (port instanceof DartSendPortSync) { |
240 var id = message[2]; | 179 return new DartProxy(port, id); |
241 return new DartProxy(id); | |
242 } | 180 } |
243 throw 'Illegal proxy object: ' + message; | 181 throw 'Illegal proxy object: ' + message; |
244 } | 182 } |
245 | 183 |
246 window.registerPort = function(name, port) { | 184 window.registerPort = function(name, port) { |
247 var stringified = JSON.stringify(serialize(port)); | 185 var stringified = JSON.stringify(serialize(port)); |
248 window.localStorage['dart-port:' + name] = stringified; | 186 window.localStorage['dart-port:' + name] = stringified; |
249 }; | 187 }; |
250 | 188 |
251 window.lookupPort = function(name) { | 189 window.lookupPort = function(name) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 var result = null; | 258 var result = null; |
321 var listener = function (e) { | 259 var listener = function (e) { |
322 result = JSON.parse(e.data); | 260 result = JSON.parse(e.data); |
323 }; | 261 }; |
324 window.addEventListener(source, listener, false); | 262 window.addEventListener(source, listener, false); |
325 dispatchEvent(target, [source, serialized]); | 263 dispatchEvent(target, [source, serialized]); |
326 window.removeEventListener(source, listener, false); | 264 window.removeEventListener(source, listener, false); |
327 return deserialize(result); | 265 return deserialize(result); |
328 } | 266 } |
329 | 267 |
268 // Proxy support | |
269 | |
270 function RefTable(name) { | |
271 // TODO(vsm): Fix leaks, particularly in dart2js case. | |
272 this.name = name; | |
273 this.map = {}; | |
274 this.id = 0; | |
275 this.initialized = false; | |
276 this.port = new ReceivePortSync(); | |
277 this.sendPort = this.port.toSendPort(); | |
278 } | |
279 | |
280 RefTable.prototype.nextId = function () { return this.id++; } | |
281 | |
282 RefTable.prototype.makeRef = function (obj) { | |
283 this.initializeOnce(); | |
284 // TODO(vsm): Cache refs for each obj. | |
285 var ref = this.name + '-' + this.nextId(); | |
286 this.map[ref] = obj; | |
287 return ref; | |
288 } | |
289 | |
290 RefTable.prototype.initializeOnce = function () { | |
291 if (!this.initialized) { | |
292 this.initialize(); | |
293 } | |
294 this.initialized = true; | |
295 } | |
296 | |
297 // Overridable initialization on first use hook. | |
298 RefTable.prototype.initialize = function () {} | |
299 | |
300 RefTable.prototype.get = function (ref) { | |
301 return this.map[ref]; | |
302 } | |
303 | |
304 function FunctionRefTable() {} | |
305 | |
306 FunctionRefTable.prototype = new RefTable('func-ref'); | |
307 | |
308 FunctionRefTable.prototype.initialize = function () { | |
309 map = this.map; | |
310 this.port.receive(function (message) { | |
311 var id = message[0]; | |
312 var args = message[1]; | |
313 var f = map[id]; | |
314 // TODO(vsm): Should we capture this automatically? | |
315 return f.apply(null, args); | |
316 }); | |
317 } | |
318 | |
319 var functionRefTable = new FunctionRefTable(); | |
320 | |
321 function JSRefTable() {} | |
322 | |
323 JSRefTable.prototype = new RefTable('js-ref'); | |
324 | |
325 JSRefTable.prototype.initialize = function () { | |
326 map = this.map; | |
327 this.port.receive(function (message) { | |
328 // TODO(vsm): Support a mechanism to register a handler here. | |
329 var receiver = map[message[0]]; | |
330 var method = message[1]; | |
331 var args = message[2]; | |
332 if (method.indexOf("get:") == 0) { | |
333 // Getter. | |
334 var field = method.substring(4); | |
335 if (field in receiver && args.length == 0) { | |
336 return [ 'return', receiver[field] ]; | |
337 } | |
338 } else if (method.indexOf("set:") == 0) { | |
339 // Setter. | |
340 var field = method.substring(4); | |
341 if (field in receiver && args.length == 1) { | |
342 return [ 'return', receiver[field] = args[0] ]; | |
343 } | |
344 } else { | |
345 var f = receiver[method]; | |
346 if (f) { | |
347 try { | |
348 var result = f.apply(receiver, args); | |
349 return [ 'return', result ]; | |
350 } catch (e) { | |
351 return [ 'exception', e ]; | |
352 } | |
353 } | |
354 } | |
355 return [ 'none' ]; | |
356 }); | |
357 } | |
358 | |
359 var jsRefTable = new JSRefTable(); | |
360 | |
361 function DartProxy(port, id) { | |
362 this._port = port; | |
363 this._id = id; | |
364 } | |
365 | |
330 // Leaking implementation. | 366 // Leaking implementation. |
331 // TODO(vsm): provide proper, backend-specific implementation. | 367 // TODO(vsm): provide proper, backend-specific implementation. |
332 function _makeFunctionFromRef(ref, sendPort) { | 368 function _makeFunctionFromRef(ref, sendPort) { |
333 return function() { | 369 return function() { |
334 return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]); | 370 return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]); |
335 } | 371 } |
336 } | 372 } |
337 })(); | 373 })(); |
OLD | NEW |