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) { | 49 // Serialize: |
50 // TODO(vsm): Fix leaks, particularly in dart2js case. | 50 // - primitives / null: unchanged |
51 this.name = name; | 51 // - lists: [ 'list', id, list of recursively serialized elements ] |
52 this.map = {}; | 52 // - maps: [ 'map', id, map of keys and recursively serialized values ] |
53 this.id = 0; | 53 // - functions: [ 'funcref', function-proxy-id, function-proxy-send-port ] |
54 this.initialized = false; | 54 // - objects: [ 'objref', object-proxy-id, object-proxy-send-port ] |
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) { | 55 function serialize(message) { |
112 var visited = []; | 56 var visited = []; |
113 function checkedSerialization(obj, serializer) { | 57 function checkedSerialization(obj, serializer) { |
114 // Implementation detail: for now use linear search. | 58 // Implementation detail: for now use linear search. |
115 // Another option is expando, but it may prohibit | 59 // Another option is expando, but it may prohibit |
116 // VM optimizations (like putting object into slow mode | 60 // VM optimizations (like putting object into slow mode |
117 // on property deletion.) | 61 // on property deletion.) |
118 var id = visited.indexOf(obj); | 62 var id = visited.indexOf(obj); |
119 if (id != -1) return [ 'ref', id ]; | 63 if (id != -1) return [ 'ref', id ]; |
120 var id = visited.length; | 64 var id = visited.length; |
(...skipping 15 matching lines...) Expand all Loading... |
136 values[i] = doSerialize(message[i]); | 80 values[i] = doSerialize(message[i]); |
137 } | 81 } |
138 return [ 'list', id, values ]; | 82 return [ 'list', id, values ]; |
139 }); | 83 }); |
140 } else if (message instanceof LocalSendPortSync) { | 84 } else if (message instanceof LocalSendPortSync) { |
141 return [ 'sendport', 'nativejs', message.receivePort.id ]; | 85 return [ 'sendport', 'nativejs', message.receivePort.id ]; |
142 } else if (message instanceof DartSendPortSync) { | 86 } else if (message instanceof DartSendPortSync) { |
143 return [ 'sendport', 'dart', message.isolateId, message.portId ]; | 87 return [ 'sendport', 'dart', message.isolateId, message.portId ]; |
144 } else if (message instanceof Function) { | 88 } else if (message instanceof Function) { |
145 return [ 'funcref', functionRefTable.makeRef(message), | 89 return [ 'funcref', functionRefTable.makeRef(message), |
146 doSerialize(functionRefTable.port) ]; | 90 doSerialize(functionRefTable.sendPort) ]; |
147 } else if (message instanceof DartProxy) { | 91 } else if (message instanceof DartProxy) { |
148 return [ 'objref', 'dart', message.id ]; | 92 return [ 'objref', message._id, doSerialize(message._port) ]; |
149 } else if (message.__proto__ != {}.__proto__) { | 93 } else if (message.__proto__ != {}.__proto__) { |
150 // TODO(vsm): Is the above portable and what we want? | 94 // TODO(vsm): Is the above portable and what we want? |
151 // Proxy non-map Objects. | 95 // Proxy non-map Objects. |
152 return [ 'objref', 'nativejs', jsRefTable.makeRef(message) ]; | 96 return [ 'objref', jsRefTable.makeRef(message), |
| 97 doSerialize(jsRefTable.sendPort) ]; |
153 } else { | 98 } else { |
154 return checkedSerialization(message, function(id) { | 99 return checkedSerialization(message, function(id) { |
155 var keys = Object.getOwnPropertyNames(message); | 100 var keys = Object.getOwnPropertyNames(message); |
156 var values = new Array(keys.length); | 101 var values = new Array(keys.length); |
157 for (var i = 0; i < keys.length; i++) { | 102 for (var i = 0; i < keys.length; i++) { |
158 values[i] = doSerialize(message[keys[i]]); | 103 values[i] = doSerialize(message[keys[i]]); |
159 } | 104 } |
160 return [ 'map', id, keys, values ]; | 105 return [ 'map', id, keys, values ]; |
161 }); | 106 }); |
162 } | 107 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 | 170 |
226 function deserializeFunction(message) { | 171 function deserializeFunction(message) { |
227 var ref = message[1]; | 172 var ref = message[1]; |
228 var sendPort = deserializeSendPort(message[2]); | 173 var sendPort = deserializeSendPort(message[2]); |
229 // Number of arguments is not used as of now | 174 // Number of arguments is not used as of now |
230 // we cannot find it out for Dart function in pure Dart. | 175 // we cannot find it out for Dart function in pure Dart. |
231 return _makeFunctionFromRef(ref, sendPort); | 176 return _makeFunctionFromRef(ref, sendPort); |
232 } | 177 } |
233 | 178 |
234 function deserializeProxy(message) { | 179 function deserializeProxy(message) { |
235 var tag = message[1]; | 180 var id = message[1]; |
236 if (tag == 'nativejs') { | 181 var port = deserializeSendPort(message[2]); |
237 var id = message[2]; | 182 if (port instanceof LocalSendPortSync) { |
238 return jsRefTable.map[id]; | 183 return jsRefTable.map[id]; |
239 } else if (tag == 'dart') { | 184 } else if (port instanceof DartSendPortSync) { |
240 var id = message[2]; | 185 return new DartProxy(port, id); |
241 return new DartProxy(id); | |
242 } | 186 } |
243 throw 'Illegal proxy object: ' + message; | 187 throw 'Illegal proxy object: ' + message; |
244 } | 188 } |
245 | 189 |
246 window.registerPort = function(name, port) { | 190 window.registerPort = function(name, port) { |
247 var stringified = JSON.stringify(serialize(port)); | 191 var stringified = JSON.stringify(serialize(port)); |
248 window.localStorage['dart-port:' + name] = stringified; | 192 window.localStorage['dart-port:' + name] = stringified; |
249 }; | 193 }; |
250 | 194 |
251 window.lookupPort = function(name) { | 195 window.lookupPort = function(name) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 var result = null; | 264 var result = null; |
321 var listener = function (e) { | 265 var listener = function (e) { |
322 result = JSON.parse(e.data); | 266 result = JSON.parse(e.data); |
323 }; | 267 }; |
324 window.addEventListener(source, listener, false); | 268 window.addEventListener(source, listener, false); |
325 dispatchEvent(target, [source, serialized]); | 269 dispatchEvent(target, [source, serialized]); |
326 window.removeEventListener(source, listener, false); | 270 window.removeEventListener(source, listener, false); |
327 return deserialize(result); | 271 return deserialize(result); |
328 } | 272 } |
329 | 273 |
| 274 // Proxy support |
| 275 |
| 276 function RefTable(name) { |
| 277 // TODO(vsm): Fix leaks, particularly in dart2js case. |
| 278 this.name = name; |
| 279 this.map = {}; |
| 280 this.id = 0; |
| 281 this.initialized = false; |
| 282 this.port = new ReceivePortSync(); |
| 283 this.sendPort = this.port.toSendPort(); |
| 284 } |
| 285 |
| 286 RefTable.prototype.nextId = function () { return this.id++; } |
| 287 |
| 288 RefTable.prototype.makeRef = function (obj) { |
| 289 this.initializeOnce(); |
| 290 // TODO(vsm): Cache refs for each obj. |
| 291 var ref = this.name + '-' + this.nextId(); |
| 292 this.map[ref] = obj; |
| 293 return ref; |
| 294 } |
| 295 |
| 296 RefTable.prototype.initializeOnce = function () { |
| 297 if (!this.initialized) { |
| 298 this.initialize(); |
| 299 } |
| 300 this.initialized = true; |
| 301 } |
| 302 |
| 303 // Overridable initialization on first use hook. |
| 304 RefTable.prototype.initialize = function () {} |
| 305 |
| 306 RefTable.prototype.get = function (ref) { |
| 307 return this.map[ref]; |
| 308 } |
| 309 |
| 310 function FunctionRefTable() {} |
| 311 |
| 312 FunctionRefTable.prototype = new RefTable('func-ref'); |
| 313 |
| 314 FunctionRefTable.prototype.initialize = function () { |
| 315 map = this.map; |
| 316 this.port.receive(function (message) { |
| 317 var id = message[0]; |
| 318 var args = message[1]; |
| 319 var f = map[id]; |
| 320 // TODO(vsm): Should we capture this automatically? |
| 321 return f.apply(null, args); |
| 322 }); |
| 323 } |
| 324 |
| 325 var functionRefTable = new FunctionRefTable(); |
| 326 |
| 327 function JSRefTable() {} |
| 328 |
| 329 JSRefTable.prototype = new RefTable('js-ref'); |
| 330 |
| 331 JSRefTable.prototype.initialize = function () { |
| 332 map = this.map; |
| 333 this.port.receive(function (message) { |
| 334 // TODO(vsm): Support a mechanism to register a handler here. |
| 335 var receiver = map[message[0]]; |
| 336 var method = message[1]; |
| 337 var args = message[2]; |
| 338 if (method.indexOf("get:") == 0) { |
| 339 // Getter. |
| 340 var field = method.substring(4); |
| 341 if (field in receiver && args.length == 0) { |
| 342 return [ 'return', receiver[field] ]; |
| 343 } |
| 344 } else if (method.indexOf("set:") == 0) { |
| 345 // Setter. |
| 346 var field = method.substring(4); |
| 347 if (field in receiver && args.length == 1) { |
| 348 return [ 'return', receiver[field] = args[0] ]; |
| 349 } |
| 350 } else { |
| 351 var f = receiver[method]; |
| 352 if (f) { |
| 353 try { |
| 354 var result = f.apply(receiver, args); |
| 355 return [ 'return', result ]; |
| 356 } catch (e) { |
| 357 return [ 'exception', e ]; |
| 358 } |
| 359 } |
| 360 } |
| 361 return [ 'none' ]; |
| 362 }); |
| 363 } |
| 364 |
| 365 var jsRefTable = new JSRefTable(); |
| 366 |
| 367 function DartProxy(port, id) { |
| 368 this._port = port; |
| 369 this._id = id; |
| 370 } |
| 371 |
330 // Leaking implementation. | 372 // Leaking implementation. |
331 // TODO(vsm): provide proper, backend-specific implementation. | 373 // TODO(vsm): provide proper, backend-specific implementation. |
332 function _makeFunctionFromRef(ref, sendPort) { | 374 function _makeFunctionFromRef(ref, sendPort) { |
333 return function() { | 375 return function() { |
334 return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]); | 376 return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]); |
335 } | 377 } |
336 } | 378 } |
337 })(); | 379 })(); |
OLD | NEW |