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

Side by Side Diff: client/dart.js

Issue 10873037: Support methods, getters, and setters on JS proxies. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix status Created 8 years, 3 months 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
« no previous file with comments | « no previous file | lib/html/dart2js/html_dart2js.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 })();
OLDNEW
« no previous file with comments | « no previous file | lib/html/dart2js/html_dart2js.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698