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 // Track proxied functions. | 49 function RefTable(name) { |
50 // TODO: Fix leaks, particularly in dart2js case. | 50 // TODO: Fix leaks, particularly in dart2js case. |
Emily Fortuna
2012/08/21 23:39:56
TODO(vsm):
vsm
2012/08/22 00:04:28
Done.
| |
51 var functionRefMap = {}; | 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++; } | |
52 | 58 |
53 var nextFunctionRefId = 0; | 59 RefTable.prototype.makeRef = function (obj) { |
54 | 60 this.initializeOnce(); |
55 function functionRefDispatch(message) { | 61 // TODO: Cache refs for each obj. |
Emily Fortuna
2012/08/21 23:39:56
add username to TODO :-)
vsm
2012/08/22 00:04:28
Done.
| |
56 var id = message[0]; | 62 var ref = this.name + '-' + this.nextId(); |
57 var args = message[1]; | 63 this.map[ref] = obj; |
Emily Fortuna
2012/08/21 23:39:56
Is this for improved debugging experience (could b
vsm
2012/08/22 00:04:28
Primarily debugging ease. Makes it easier to tell
| |
58 var f = functionRefMap[id]; | |
59 // TODO: Should we capture this automatically? | |
60 return f.apply(null, args); | |
61 } | |
62 | |
63 var functionRefPort = null; | |
64 | |
65 function makeFunctionRef(f) { | |
66 if (functionRefPort == null) { | |
67 var port = new ReceivePortSync(); | |
68 port.receive(functionRefDispatch); | |
69 functionRefPort = port.toSendPort(); | |
70 } | |
71 var ref = 'func-ref-' + (nextFunctionRefId++); | |
72 functionRefMap[ref] = f; | |
73 return ref; | 64 return ref; |
74 } | 65 } |
75 | 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 } | |
Emily Fortuna
2012/08/21 23:39:56
move this up to the previous line? http://www.corp
vsm
2012/08/22 00:04:28
Done.
| |
77 | |
78 RefTable.prototype.get = function (ref) { | |
79 return this.map[ref]; | |
80 } | |
81 | |
82 function FunctionRefTable() { | |
83 } | |
Emily Fortuna
2012/08/21 23:39:56
probably can move this } up onto the previous line
vsm
2012/08/22 00:04:28
Done.
| |
84 FunctionRefTable.prototype = new RefTable('func-ref'); | |
85 | |
86 FunctionRefTable.prototype.initialize = function () { | |
87 var receivePort = new ReceivePortSync(); | |
88 map = this.map; | |
89 receivePort.receive(function (message) { | |
90 var id = message[0]; | |
91 var args = message[1]; | |
92 var f = map[id]; | |
93 // TODO: Should we capture this automatically? | |
Emily Fortuna
2012/08/21 23:39:56
TODO(vsm):
vsm
2012/08/22 00:04:28
Done.
| |
94 return f.apply(null, args); | |
95 }); | |
96 this.port = receivePort.toSendPort(); | |
97 } | |
98 | |
99 var functionRefTable = new FunctionRefTable(); | |
100 | |
101 function JSRefTable() { | |
102 } | |
103 JSRefTable.prototype = new RefTable('js-ref'); | |
Emily Fortuna
2012/08/21 23:39:56
add an extra whitespace line above
vsm
2012/08/22 00:04:28
Done.
| |
104 var jsRefTable = new JSRefTable(); | |
105 | |
106 function DartProxy(id) { | |
107 // TODO(vsm): Set isolate id. | |
108 this.id = id; | |
109 } | |
110 | |
76 function serialize(message) { | 111 function serialize(message) { |
77 var visited = []; | 112 var visited = []; |
78 function checkedSerialization(obj, serializer) { | 113 function checkedSerialization(obj, serializer) { |
79 // Implementation detail: for now use linear search. | 114 // Implementation detail: for now use linear search. |
80 // Another option is expando, but it may prohibit | 115 // Another option is expando, but it may prohibit |
81 // VM optimizations (like putting object into slow mode | 116 // VM optimizations (like putting object into slow mode |
82 // on property deletion.) | 117 // on property deletion.) |
83 var id = visited.indexOf(obj); | 118 var id = visited.indexOf(obj); |
84 if (id != -1) return [ 'ref', id ]; | 119 if (id != -1) return [ 'ref', id ]; |
85 var id = visited.length; | 120 var id = visited.length; |
(...skipping 14 matching lines...) Expand all Loading... | |
100 for (var i = 0; i < message.length; i++) { | 135 for (var i = 0; i < message.length; i++) { |
101 values[i] = doSerialize(message[i]); | 136 values[i] = doSerialize(message[i]); |
102 } | 137 } |
103 return [ 'list', id, values ]; | 138 return [ 'list', id, values ]; |
104 }); | 139 }); |
105 } else if (message instanceof LocalSendPortSync) { | 140 } else if (message instanceof LocalSendPortSync) { |
106 return [ 'sendport', 'nativejs', message.receivePort.id ]; | 141 return [ 'sendport', 'nativejs', message.receivePort.id ]; |
107 } else if (message instanceof DartSendPortSync) { | 142 } else if (message instanceof DartSendPortSync) { |
108 return [ 'sendport', 'dart', message.isolateId, message.portId ]; | 143 return [ 'sendport', 'dart', message.isolateId, message.portId ]; |
109 } else if (message instanceof Function) { | 144 } else if (message instanceof Function) { |
110 return [ 'funcref', makeFunctionRef(message), | 145 return [ 'funcref', functionRefTable.makeRef(message), |
111 doSerialize(functionRefPort) ]; | 146 doSerialize(functionRefTable.port) ]; |
147 } else if (message instanceof DartProxy) { | |
148 return [ 'objref', 'dart', message.id ]; | |
149 } else if (message.__proto__ != {}.__proto) { | |
150 » // TODO(vsm): Is the above portable and what we want? | |
Emily Fortuna
2012/08/21 23:39:56
remove tabs here
vsm
2012/08/22 00:04:28
Done.
| |
151 » // Proxy non-map Objects. | |
152 return [ 'objref', 'nativejs', jsRefTable.makeRef(message) ]; | |
Emily Fortuna
2012/08/21 23:39:56
I thought all objects in JS could be examined as m
vsm
2012/08/22 00:04:28
Right. The proto check in the preceding if is try
| |
112 } else { | 153 } else { |
113 return checkedSerialization(message, function(id) { | 154 return checkedSerialization(message, function(id) { |
114 var keys = Object.getOwnPropertyNames(message); | 155 var keys = Object.getOwnPropertyNames(message); |
115 var values = new Array(keys.length); | 156 var values = new Array(keys.length); |
116 for (var i = 0; i < keys.length; i++) { | 157 for (var i = 0; i < keys.length; i++) { |
117 values[i] = doSerialize(message[keys[i]]); | 158 values[i] = doSerialize(message[keys[i]]); |
118 } | 159 } |
119 return [ 'map', id, keys, values ]; | 160 return [ 'map', id, keys, values ]; |
120 }); | 161 }); |
121 } | 162 } |
122 } | 163 } |
123 return doSerialize(message); | 164 return doSerialize(message); |
124 } | 165 } |
125 | 166 |
126 function deserialize(message) { | 167 function deserialize(message) { |
127 return deserializeHelper(message); | 168 return deserializeHelper(message); |
128 } | 169 } |
129 | 170 |
130 function deserializeHelper(x) { | 171 function deserializeHelper(x) { |
dgrove
2012/08/21 23:43:27
better name than "x"?
vsm
2012/08/22 00:04:28
Done.
| |
131 if (x == null || | 172 if (x == null || |
132 typeof(x) == 'string' || | 173 typeof(x) == 'string' || |
133 typeof(x) == 'number' || | 174 typeof(x) == 'number' || |
134 typeof(x) == 'boolean') { | 175 typeof(x) == 'boolean') { |
135 return x; | 176 return x; |
136 } | 177 } |
137 switch (x[0]) { | 178 switch (x[0]) { |
138 case 'map': return deserializeMap(x); | 179 case 'map': return deserializeMap(x); |
139 case 'sendport': return deserializeSendPort(x); | 180 case 'sendport': return deserializeSendPort(x); |
140 case 'list': return deserializeList(x); | 181 case 'list': return deserializeList(x); |
141 case 'funcref': return deserializeFunction(x); | 182 case 'funcref': return deserializeFunction(x); |
183 case 'objref': return deserializeProxy(x); | |
142 default: throw 'unimplemented'; | 184 default: throw 'unimplemented'; |
143 } | 185 } |
144 } | 186 } |
145 | 187 |
146 function deserializeMap(x) { | 188 function deserializeMap(x) { |
dgrove
2012/08/21 23:43:27
ditto
vsm
2012/08/22 00:04:28
Done.
| |
147 var result = { }; | 189 var result = { }; |
148 var id = x[1]; | 190 var id = x[1]; |
149 var keys = x[2]; | 191 var keys = x[2]; |
150 var values = x[3]; | 192 var values = x[3]; |
151 for (var i = 0, length = keys.length; i < length; i++) { | 193 for (var i = 0, length = keys.length; i < length; i++) { |
152 var key = deserializeHelper(keys[i]); | 194 var key = deserializeHelper(keys[i]); |
153 var value = deserializeHelper(values[i]); | 195 var value = deserializeHelper(values[i]); |
154 result[key] = value; | 196 result[key] = value; |
155 } | 197 } |
156 return result; | 198 return result; |
(...skipping 17 matching lines...) Expand all Loading... | |
174 function deserializeList(x) { | 216 function deserializeList(x) { |
175 var values = x[2]; | 217 var values = x[2]; |
176 var length = values.length; | 218 var length = values.length; |
177 var result = new Array(length); | 219 var result = new Array(length); |
178 for (var i = 0; i < length; i++) { | 220 for (var i = 0; i < length; i++) { |
179 result[i] = deserializeHelper(values[i]); | 221 result[i] = deserializeHelper(values[i]); |
180 } | 222 } |
181 return result; | 223 return result; |
182 } | 224 } |
183 | 225 |
184 function deserializeFunction(x) { | 226 function deserializeFunction(x) { |
dgrove
2012/08/21 23:43:27
ditto
vsm
2012/08/22 00:04:28
Done.
| |
185 var ref = x[1]; | 227 var ref = x[1]; |
186 var sendPort = deserializeSendPort(x[2]); | 228 var sendPort = deserializeSendPort(x[2]); |
187 // Number of arguments is not used as of now | 229 // Number of arguments is not used as of now |
188 // we cannot find it out for Dart function in pure Dart. | 230 // we cannot find it out for Dart function in pure Dart. |
189 return _makeFunctionFromRef(ref, sendPort); | 231 return _makeFunctionFromRef(ref, sendPort); |
190 } | 232 } |
191 | 233 |
234 function deserializeProxy(x) { | |
235 var tag = x[1]; | |
236 if (tag == 'nativejs') { | |
237 var id = x[2]; | |
238 return jsRefTable.map[id]; | |
239 } else if (tag == 'dart') { | |
240 var id = x[2]; | |
241 return new DartProxy(id); | |
242 } | |
243 throw 'Illegal proxy object: ' + x; | |
244 } | |
245 | |
192 window.registerPort = function(name, port) { | 246 window.registerPort = function(name, port) { |
193 var stringified = JSON.stringify(serialize(port)); | 247 var stringified = JSON.stringify(serialize(port)); |
194 window.localStorage['dart-port:' + name] = stringified; | 248 window.localStorage['dart-port:' + name] = stringified; |
195 }; | 249 }; |
196 | 250 |
197 window.lookupPort = function(name) { | 251 window.lookupPort = function(name) { |
198 var stringified = window.localStorage['dart-port:' + name]; | 252 var stringified = window.localStorage['dart-port:' + name]; |
199 return deserialize(JSON.parse(stringified)); | 253 return deserialize(JSON.parse(stringified)); |
200 }; | 254 }; |
201 | 255 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
274 } | 328 } |
275 | 329 |
276 // Leaking implementation. | 330 // Leaking implementation. |
277 // TODO: provide proper, backend-specific implementation. | 331 // TODO: provide proper, backend-specific implementation. |
278 function _makeFunctionFromRef(ref, sendPort) { | 332 function _makeFunctionFromRef(ref, sendPort) { |
279 return function() { | 333 return function() { |
280 return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]); | 334 return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]); |
281 } | 335 } |
282 } | 336 } |
283 })(); | 337 })(); |
OLD | NEW |