| 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..ceb81c775ba13aacc8c1cc900331a8ee52e98de7 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> asJsMap() => 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,90 @@ 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);
|
| +
|
| + // Iterable
|
| + /*@override*/ int get length => super['length'];
|
| +
|
| + // Collection
|
| + /*@override*/ void add(value) { callMethod('push', [value]); }
|
| +
|
| + // List
|
| + /*@override*/ operator [](index) {
|
| + if (index is int && (index < 0 || index >= this.length)) {
|
| + throw new RangeError.value(index);
|
| + }
|
| + return super[index];
|
| + }
|
| + /*@override*/ void operator []=(index, value) {
|
| + if (index is int && (index < 0 || index >= this.length)) {
|
| + throw new RangeError.value(index);
|
| + }
|
| + super[index] = value;
|
| + }
|
| + /*@override*/ void set length(int length) { super['length'] = length; }
|
| + /*@override*/ void sort([int compare(a, b)]) {
|
| + final sortedList = toList()..sort(compare);
|
| + setRange(0, sortedList.length, sortedList);
|
| + }
|
| + /*@override*/ void insert(int index, element) {
|
| + callMethod('splice', [index, 0, element]);
|
| + }
|
| + /*@override*/ removeAt(int index) {
|
| + if (index < 0 || index >= this.length) throw new RangeError.value(index);
|
| + return callMethod('splice', [index, 1])[0];
|
| + }
|
| + /*@override*/ removeLast() => callMethod('pop');
|
| + /*@override*/ 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);
|
| + }
|
| + /*@override*/ void removeRange(int start, int end) {
|
| + callMethod('splice', [start, end - start]);
|
| + }
|
| +}
|
| +
|
| +class _JsObjectAsMap implements Map<String, dynamic> {
|
| + JsObject _jsObject;
|
| +
|
| + _JsObjectAsMap(this._jsObject);
|
| +
|
| + /*@override*/ operator [](String key) => _jsObject[key];
|
| + /*@override*/ void operator []=(String key, value) {
|
| + _jsObject[key] = value;
|
| + }
|
| + /*@override*/ remove(String key) {
|
| + final value = this[key];
|
| + _jsObject.deleteProperty(key);
|
| + return value;
|
| + }
|
| + /*@override*/ Iterable<String> get keys =>
|
| + context['Object'].callMethod('keys', [_jsObject]);
|
| +
|
| + // use Maps to implement functions
|
| + /*@override*/ bool containsValue(value) => Maps.containsValue(this, value);
|
| + /*@override*/ bool containsKey(String key) => Maps.containsKey(this, key);
|
| + /*@override*/ putIfAbsent(String key, ifAbsent()) =>
|
| + Maps.putIfAbsent(this, key, ifAbsent);
|
| + /*@override*/ void addAll(Map<String, dynamic> other) {
|
| + if (other != null) {
|
| + other.forEach((k,v) => this[k] = v);
|
| + }
|
| + }
|
| + /*@override*/ void clear() => Maps.clear(this);
|
| + /*@override*/ void forEach(void f(String key, value)) => Maps.forEach(this, f);
|
| + /*@override*/ Iterable get values => Maps.getValues(this);
|
| + /*@override*/ int get length => Maps.length(this);
|
| + /*@override*/ bool get isEmpty => Maps.isEmpty(this);
|
| + /*@override*/ 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 +405,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 +442,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 +463,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';
|
| }
|
|
|