Index: sdk/lib/js/dartium/js_dartium.dart |
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart |
index 393320f91ffd8f70fe532342e4164d54a8e452d1..94e46acde037f6a30854697b681ecae614f8efef 100644 |
--- a/sdk/lib/js/dartium/js_dartium.dart |
+++ b/sdk/lib/js/dartium/js_dartium.dart |
@@ -66,6 +66,7 @@ |
library dart.js; |
+import 'dart:collection' show ListMixin, Maps; |
import 'dart:html'; |
import 'dart:isolate'; |
@@ -198,6 +199,8 @@ class JsObject implements Serializable<JsObject> { |
return _forward(this, name, 'method', args != null ? args : []); |
} |
+ Map<String, dynamic> asDartMap() => new _JsObjectAsMap(this); |
+ |
// Forward member accesses to the backing JavaScript object. |
static _forward(JsObject receiver, String member, String kind, List args) { |
var result = receiver._port.callSync([receiver._id, member, kind, |
@@ -222,6 +225,92 @@ class JsFunction extends JsObject implements Serializable<JsFunction> { |
} |
} |
+/// A [JsObject] subtype for JavaScript arrays. |
+class JsArray extends JsObject with ListMixin { |
+ JsArray._internal(SendPortSync port, String id) : super._internal(port, id); |
+ |
+ // method to implement for ListMixin |
+ |
+ int get length => super['length']; |
+ void set length(int length) { super['length'] = length; } |
+ operator [](index) { |
+ if (index is int && (index < 0 || index >= this.length)) { |
+ throw new RangeError.value(index); |
+ } |
+ return super[index]; |
+ } |
+ void operator []=(index, value) { |
+ if (index is int && (index < 0 || index >= this.length)) { |
+ throw new RangeError.value(index); |
+ } |
+ super[index] = value; |
+ } |
+ |
+ // overriden methods for better performance |
+ |
+ void add(value) { callMethod('push', [value]); } |
+ void addAll(Iterable iterable) { callMethod('push', iterable.toList()); } |
+ void sort([int compare(a, b)]) { |
+ final sortedList = toList()..sort(compare); |
+ setRange(0, sortedList.length, sortedList); |
+ } |
+ void insert(int index, element) { |
+ callMethod('splice', [index, 0, element]); |
+ } |
+ removeAt(int index) { |
+ if (index < 0 || index >= this.length) throw new RangeError.value(index); |
+ return callMethod('splice', [index, 1])[0]; |
+ } |
+ removeLast() => callMethod('pop'); |
+ void setRange(int start, int length, List from, |
+ [int startFrom = 0]) { |
+ final args = [start, length]; |
+ for(int i = startFrom; i < startFrom + length; i++) { |
+ args.add(from[i]); |
+ } |
+ callMethod('splice', args); |
+ } |
+ void removeRange(int start, int end) { |
+ callMethod('splice', [start, end - start]); |
+ } |
+} |
+ |
+class _JsObjectAsMap implements Map<String, dynamic> { |
+ JsObject _jsObject; |
+ |
+ _JsObjectAsMap(this._jsObject); |
+ |
+ operator [](String key) => _jsObject[key]; |
+ void operator []=(String key, value) { |
+ _jsObject[key] = value; |
+ } |
+ remove(String key) { |
+ final value = this[key]; |
+ _jsObject.deleteProperty(key); |
+ return value; |
+ } |
+ Iterable<String> get keys => |
+ context['Object'].callMethod('keys', [_jsObject]); |
+ |
+ bool containsValue(value) => |
+ JsObject._forward(_jsObject, 'containsValue', 'asMap', [value]); |
+ bool containsKey(String key) => _jsObject.hasProperty(key); |
+ putIfAbsent(String key, ifAbsent()) => Maps.putIfAbsent(this, key, ifAbsent); |
+ void addAll(Map<String, dynamic> other) { |
+ if (other != null) { |
+ JsObject._forward(_jsObject, 'addAll', 'asMap', [jsify(other)]); |
+ } |
+ } |
+ void clear() => Maps.clear(this); |
+ void forEach(void f(String key, value)) => Maps.forEach(this, f); |
+ Iterable get values => |
+ JsObject._forward(_jsObject, 'values', 'asMap', []); |
+ int get length => |
+ JsObject._forward(_jsObject, 'length', 'asMap', []); |
+ bool get isEmpty => Maps.isEmpty(this); |
+ bool get isNotEmpty => Maps.isNotEmpty(this); |
+} |
+ |
/// Marker class used to indicate it is serializable to js. If a class is a |
/// [Serializable] the "toJs" method will be called and the result will be used |
/// as value. |
@@ -318,6 +407,10 @@ _serialize(var message) { |
return _serialize(message.toJs()); |
} else if (message is Function) { |
return _serialize(new Callback(message)); |
+ } else if (message is Map) { |
+ return _serialize(jsify(message)); |
+ } else if (message is Iterable) { |
+ return _serialize(jsify(message)); |
} else { |
// Local object proxy. |
return [ 'objref', |
@@ -351,6 +444,12 @@ _deserialize(var message) { |
} |
} |
+ deserializeArray(message) { |
+ var id = message[1]; |
+ var port = message[2]; |
+ return new JsArray._internal(port, id); |
+ } |
+ |
if (message == null) { |
return null; // Convert undefined to null. |
} else if (message is String || |
@@ -366,6 +465,7 @@ _deserialize(var message) { |
switch (tag) { |
case 'funcref': return deserializeFunction(message); |
case 'objref': return deserializeObject(message); |
+ case 'arrayref': return deserializeArray(message); |
} |
throw 'Unsupported serialized data: $message'; |
} |