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

Side by Side Diff: sdk/lib/js/dartium/js_dartium.dart

Issue 23291005: add JsArray and JsObject.asJsMap() Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: optimizations Created 7 years, 4 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 | « sdk/lib/js/dart2js/js_dart2js.dart ('k') | tests/html/js_test.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /** 5 /**
6 * The js.dart library provides simple JavaScript invocation from Dart that 6 * The js.dart library provides simple JavaScript invocation from Dart that
7 * works on both Dartium and on other modern browsers via Dart2JS. 7 * works on both Dartium and on other modern browsers via Dart2JS.
8 * 8 *
9 * It provides a model based on scoped [JsObject] objects. Proxies give Dart 9 * It provides a model based on scoped [JsObject] objects. Proxies give Dart
10 * code access to JavaScript objects, fields, and functions as well as the 10 * code access to JavaScript objects, fields, and functions as well as the
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 * var foo = new JsObject(context['Foo'], [42]); 59 * var foo = new JsObject(context['Foo'], [42]);
60 * var foo2 = foo.callMethod('add', [foo]); 60 * var foo2 = foo.callMethod('add', [foo]);
61 * print(foo2['x']); 61 * print(foo2['x']);
62 * 62 *
63 * will construct a JavaScript Foo object with the parameter 42, invoke its 63 * will construct a JavaScript Foo object with the parameter 42, invoke its
64 * add method, and return a [JsObject] to a new Foo object whose x field is 84. 64 * add method, and return a [JsObject] to a new Foo object whose x field is 84.
65 */ 65 */
66 66
67 library dart.js; 67 library dart.js;
68 68
69 import 'dart:collection' show ListMixin, Maps;
69 import 'dart:html'; 70 import 'dart:html';
70 import 'dart:isolate'; 71 import 'dart:isolate';
71 72
72 // Global ports to manage communication from Dart to JS. 73 // Global ports to manage communication from Dart to JS.
73 SendPortSync _jsPortSync = window.lookupPort('dart-js-context'); 74 SendPortSync _jsPortSync = window.lookupPort('dart-js-context');
74 SendPortSync _jsPortCreate = window.lookupPort('dart-js-create'); 75 SendPortSync _jsPortCreate = window.lookupPort('dart-js-create');
75 SendPortSync _jsPortInstanceof = window.lookupPort('dart-js-instanceof'); 76 SendPortSync _jsPortInstanceof = window.lookupPort('dart-js-instanceof');
76 SendPortSync _jsPortDeleteProperty = window.lookupPort('dart-js-delete-property' ); 77 SendPortSync _jsPortDeleteProperty = window.lookupPort('dart-js-delete-property' );
77 SendPortSync _jsPortConvert = window.lookupPort('dart-js-convert'); 78 SendPortSync _jsPortConvert = window.lookupPort('dart-js-convert');
78 79
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 return _forward(this, 'toString', 'method', []); 192 return _forward(this, 'toString', 'method', []);
192 } catch(e) { 193 } catch(e) {
193 return super.toString(); 194 return super.toString();
194 } 195 }
195 } 196 }
196 197
197 callMethod(String name, [List args]) { 198 callMethod(String name, [List args]) {
198 return _forward(this, name, 'method', args != null ? args : []); 199 return _forward(this, name, 'method', args != null ? args : []);
199 } 200 }
200 201
202 Map<String, dynamic> asDartMap() => new _JsObjectAsMap(this);
203
201 // Forward member accesses to the backing JavaScript object. 204 // Forward member accesses to the backing JavaScript object.
202 static _forward(JsObject receiver, String member, String kind, List args) { 205 static _forward(JsObject receiver, String member, String kind, List args) {
203 var result = receiver._port.callSync([receiver._id, member, kind, 206 var result = receiver._port.callSync([receiver._id, member, kind,
204 args.map(_serialize).toList()]); 207 args.map(_serialize).toList()]);
205 switch (result[0]) { 208 switch (result[0]) {
206 case 'return': return _deserialize(result[1]); 209 case 'return': return _deserialize(result[1]);
207 case 'throws': throw _deserialize(result[1]); 210 case 'throws': throw _deserialize(result[1]);
208 case 'none': throw new NoSuchMethodError(receiver, member, args, {}); 211 case 'none': throw new NoSuchMethodError(receiver, member, args, {});
209 default: throw 'Invalid return value'; 212 default: throw 'Invalid return value';
210 } 213 }
211 } 214 }
212 } 215 }
213 216
214 /// A [JsObject] subtype to JavaScript functions. 217 /// A [JsObject] subtype to JavaScript functions.
215 class JsFunction extends JsObject implements Serializable<JsFunction> { 218 class JsFunction extends JsObject implements Serializable<JsFunction> {
216 JsFunction._internal(SendPortSync port, String id) 219 JsFunction._internal(SendPortSync port, String id)
217 : super._internal(port, id); 220 : super._internal(port, id);
218 221
219 apply(thisArg, [List args]) { 222 apply(thisArg, [List args]) {
220 return JsObject._forward(this, '', 'apply', 223 return JsObject._forward(this, '', 'apply',
221 [thisArg]..addAll(args == null ? [] : args)); 224 [thisArg]..addAll(args == null ? [] : args));
222 } 225 }
223 } 226 }
224 227
228 /// A [JsObject] subtype for JavaScript arrays.
229 class JsArray extends JsObject with ListMixin {
230 JsArray._internal(SendPortSync port, String id) : super._internal(port, id);
231
232 // method to implement for ListMixin
233
234 int get length => super['length'];
235 void set length(int length) { super['length'] = length; }
236 operator [](index) {
237 if (index is int && (index < 0 || index >= this.length)) {
238 throw new RangeError.value(index);
239 }
240 return super[index];
241 }
242 void operator []=(index, value) {
243 if (index is int && (index < 0 || index >= this.length)) {
244 throw new RangeError.value(index);
245 }
246 super[index] = value;
247 }
248
249 // overriden methods for better performance
250
251 void add(value) { callMethod('push', [value]); }
252 void addAll(Iterable iterable) { callMethod('push', iterable.toList()); }
253 void sort([int compare(a, b)]) {
254 final sortedList = toList()..sort(compare);
255 setRange(0, sortedList.length, sortedList);
256 }
257 void insert(int index, element) {
258 callMethod('splice', [index, 0, element]);
259 }
260 removeAt(int index) {
261 if (index < 0 || index >= this.length) throw new RangeError.value(index);
262 return callMethod('splice', [index, 1])[0];
263 }
264 removeLast() => callMethod('pop');
265 void setRange(int start, int length, List from,
266 [int startFrom = 0]) {
267 final args = [start, length];
268 for(int i = startFrom; i < startFrom + length; i++) {
269 args.add(from[i]);
270 }
271 callMethod('splice', args);
272 }
273 void removeRange(int start, int end) {
274 callMethod('splice', [start, end - start]);
275 }
276 }
277
278 class _JsObjectAsMap implements Map<String, dynamic> {
279 JsObject _jsObject;
280
281 _JsObjectAsMap(this._jsObject);
282
283 operator [](String key) => _jsObject[key];
284 void operator []=(String key, value) {
285 _jsObject[key] = value;
286 }
287 remove(String key) {
288 final value = this[key];
289 _jsObject.deleteProperty(key);
290 return value;
291 }
292 Iterable<String> get keys =>
293 context['Object'].callMethod('keys', [_jsObject]);
294
295 bool containsValue(value) =>
296 JsObject._forward(_jsObject, 'containsValue', 'asMap', [value]);
297 bool containsKey(String key) => _jsObject.hasProperty(key);
298 putIfAbsent(String key, ifAbsent()) => Maps.putIfAbsent(this, key, ifAbsent);
299 void addAll(Map<String, dynamic> other) {
300 if (other != null) {
301 JsObject._forward(_jsObject, 'addAll', 'asMap', [jsify(other)]);
302 }
303 }
304 void clear() => Maps.clear(this);
305 void forEach(void f(String key, value)) => Maps.forEach(this, f);
306 Iterable get values =>
307 JsObject._forward(_jsObject, 'values', 'asMap', []);
308 int get length =>
309 JsObject._forward(_jsObject, 'length', 'asMap', []);
310 bool get isEmpty => Maps.isEmpty(this);
311 bool get isNotEmpty => Maps.isNotEmpty(this);
312 }
313
225 /// Marker class used to indicate it is serializable to js. If a class is a 314 /// Marker class used to indicate it is serializable to js. If a class is a
226 /// [Serializable] the "toJs" method will be called and the result will be used 315 /// [Serializable] the "toJs" method will be called and the result will be used
227 /// as value. 316 /// as value.
228 abstract class Serializable<T> { 317 abstract class Serializable<T> {
229 T toJs(); 318 T toJs();
230 } 319 }
231 320
232 // A table to managed local Dart objects that are proxied in JavaScript. 321 // A table to managed local Dart objects that are proxied in JavaScript.
233 class _ProxiedObjectTable { 322 class _ProxiedObjectTable {
234 // Debugging name. 323 // Debugging name.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 // Remote function proxy. 400 // Remote function proxy.
312 return [ 'funcref', message._id, message._port ]; 401 return [ 'funcref', message._id, message._port ];
313 } else if (message is JsObject) { 402 } else if (message is JsObject) {
314 // Remote object proxy. 403 // Remote object proxy.
315 return [ 'objref', message._id, message._port ]; 404 return [ 'objref', message._id, message._port ];
316 } else if (message is Serializable) { 405 } else if (message is Serializable) {
317 // use of result of toJs() 406 // use of result of toJs()
318 return _serialize(message.toJs()); 407 return _serialize(message.toJs());
319 } else if (message is Function) { 408 } else if (message is Function) {
320 return _serialize(new Callback(message)); 409 return _serialize(new Callback(message));
410 } else if (message is Map) {
411 return _serialize(jsify(message));
412 } else if (message is Iterable) {
413 return _serialize(jsify(message));
321 } else { 414 } else {
322 // Local object proxy. 415 // Local object proxy.
323 return [ 'objref', 416 return [ 'objref',
324 _proxiedObjectTable.add(message), 417 _proxiedObjectTable.add(message),
325 _proxiedObjectTable.sendPort ]; 418 _proxiedObjectTable.sendPort ];
326 } 419 }
327 } 420 }
328 421
329 _deserialize(var message) { 422 _deserialize(var message) {
330 deserializeFunction(message) { 423 deserializeFunction(message) {
(...skipping 13 matching lines...) Expand all
344 var port = message[2]; 437 var port = message[2];
345 if (port == _proxiedObjectTable.sendPort) { 438 if (port == _proxiedObjectTable.sendPort) {
346 // Local object. 439 // Local object.
347 return _proxiedObjectTable.get(id); 440 return _proxiedObjectTable.get(id);
348 } else { 441 } else {
349 // Remote object. 442 // Remote object.
350 return new JsObject._internal(port, id); 443 return new JsObject._internal(port, id);
351 } 444 }
352 } 445 }
353 446
447 deserializeArray(message) {
448 var id = message[1];
449 var port = message[2];
450 return new JsArray._internal(port, id);
451 }
452
354 if (message == null) { 453 if (message == null) {
355 return null; // Convert undefined to null. 454 return null; // Convert undefined to null.
356 } else if (message is String || 455 } else if (message is String ||
357 message is num || 456 message is num ||
358 message is bool) { 457 message is bool) {
359 // Primitives are passed directly through. 458 // Primitives are passed directly through.
360 return message; 459 return message;
361 } else if (message is SendPortSync) { 460 } else if (message is SendPortSync) {
362 // Serialized type. 461 // Serialized type.
363 return message; 462 return message;
364 } 463 }
365 var tag = message[0]; 464 var tag = message[0];
366 switch (tag) { 465 switch (tag) {
367 case 'funcref': return deserializeFunction(message); 466 case 'funcref': return deserializeFunction(message);
368 case 'objref': return deserializeObject(message); 467 case 'objref': return deserializeObject(message);
468 case 'arrayref': return deserializeArray(message);
369 } 469 }
370 throw 'Unsupported serialized data: $message'; 470 throw 'Unsupported serialized data: $message';
371 } 471 }
OLDNEW
« no previous file with comments | « sdk/lib/js/dart2js/js_dart2js.dart ('k') | tests/html/js_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698