Index: sdk/lib/_internal/lib/isolate_helper.dart |
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart |
index 6debde78c441cbb2d4bc1600e8212a7b9371beb4..05208648a9a3f0e46e579ed2cf703337350684ee 100644 |
--- a/sdk/lib/_internal/lib/isolate_helper.dart |
+++ b/sdk/lib/_internal/lib/isolate_helper.dart |
@@ -11,7 +11,8 @@ import 'dart:_js_helper' show |
Closure, |
Null, |
Primitives, |
- convertDartClosureToJS; |
+ convertDartClosureToJS, |
+ random64; |
import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS, |
JS, |
JS_CREATE_ISOLATE, |
@@ -921,6 +922,13 @@ class _JsSerializer extends _Serializer { |
throw "Illegal underlying port $x"; |
} |
+ visitCapability(Capability x) { |
+ if (x is CapabilityImpl) { |
+ return ['capability', x._id]; |
+ } |
+ throw "Capability not serializable: $x"; |
+ } |
+ |
visitNativeJsSendPort(_NativeJsSendPort port) { |
return ['sendport', _globalState.currentManagerId, |
port._isolateId, port._receivePort._id]; |
@@ -942,6 +950,13 @@ class _JsCopier extends _Copier { |
throw "Illegal underlying port $x"; |
} |
+ visitCapability(Capability x) { |
+ if (x is CapabilityImpl) { |
+ return new CapabilityImpl._internal(x._id); |
+ } |
+ throw "Capability not serializable: $x"; |
+ } |
+ |
SendPort visitNativeJsSendPort(_NativeJsSendPort port) { |
return new _NativeJsSendPort(port._receivePort, port._isolateId); |
} |
@@ -970,6 +985,10 @@ class _JsDeserializer extends _Deserializer { |
return new _WorkerSendPort(managerId, isolateId, receivePortId); |
} |
} |
+ |
+ Capability deserializeCapability(List list) { |
+ return new CapabilityImpl._internal(list[1]); |
+ } |
} |
class _JsVisitedMap implements _MessageTraverserVisitedMap { |
@@ -1062,10 +1081,13 @@ abstract class _MessageTraverser { |
} |
_dispatch(var x) { |
+ // This code likely fails for user classes implementing |
+ // SendPort and Capability because it assumes the internal classes. |
if (isPrimitive(x)) return visitPrimitive(x); |
if (x is List) return visitList(x); |
if (x is Map) return visitMap(x); |
if (x is SendPort) return visitSendPort(x); |
+ if (x is Capability) return visitCapability(x); |
// Overridable fallback. |
return visitObject(x); |
@@ -1075,6 +1097,7 @@ abstract class _MessageTraverser { |
visitList(List x); |
visitMap(Map x); |
visitSendPort(SendPort x); |
+ visitCapability(Capability x); |
visitObject(Object x) { |
// TODO(floitsch): make this a real exception. (which one)? |
@@ -1121,6 +1144,8 @@ class _Copier extends _MessageTraverser { |
} |
visitSendPort(SendPort x) => throw new UnimplementedError(); |
+ |
+ visitCapability(Capability x) => throw new UnimplementedError(); |
} |
/** Visitor that serializes a message as a JSON array. */ |
@@ -1164,6 +1189,8 @@ class _Serializer extends _MessageTraverser { |
} |
visitSendPort(SendPort x) => throw new UnimplementedError(); |
+ |
+ visitCapability(Capability x) => throw new UnimplementedError(); |
} |
/** Deserializes arrays created with [_Serializer]. */ |
@@ -1191,6 +1218,7 @@ abstract class _Deserializer { |
case 'list': return _deserializeList(x); |
case 'map': return _deserializeMap(x); |
case 'sendport': return deserializeSendPort(x); |
+ case 'capability': return deserializeCapability(x); |
default: return deserializeObject(x); |
} |
} |
@@ -1232,6 +1260,8 @@ abstract class _Deserializer { |
deserializeSendPort(List x); |
+ deserializeCapability(List x); |
+ |
deserializeObject(List x) { |
// TODO(floitsch): Use real exception (which one?). |
throw "Unexpected serialized object"; |
@@ -1319,3 +1349,41 @@ class TimerImpl implements Timer { |
} |
bool hasTimer() => JS('', '#.setTimeout', globalThis) != null; |
+ |
+ |
+/** |
+ * Implementation class for [Capability]. |
+ * |
+ * It has the same name to make it harder for users to distinguish. |
+ */ |
+class CapabilityImpl implements Capability { |
+ /** Internal random secret identifying the capability. */ |
+ final int _id; |
+ |
+ CapabilityImpl() : this._internal(random64()); |
+ |
+ CapabilityImpl._internal(this._id); |
+ |
+ int get hashCode { |
+ // Thomas Wang 32 bit Mix. |
+ // http://www.concentric.net/~Ttwang/tech/inthash.htm |
+ // (via https://gist.github.com/badboy/6267743) |
+ int hash = _id; |
+ hash = (hash >> 0) ^ (hash ~/ 0x100000000); // To 32 bit from ~64. |
+ hash = (~hash + (hash << 15)) & 0xFFFFFFFF; |
+ hash ^= hash >> 12; |
+ hash = (hash * 5) & 0xFFFFFFFF; |
+ hash ^= hash >> 4; |
+ hash = (hash * 2057) & 0xFFFFFFFF; |
+ hash ^= hash >> 16; |
+ return hash; |
+ } |
+ |
+ bool operator==(Object other) { |
+ if (identical(other, this)) return true; |
+ if (other is CapabilityImpl) { |
+ return identical(_id, other._id); |
+ } |
+ return false; |
+ } |
+} |