Index: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
index 4a8670bd65178dbd7914982df4ac822520dfaddc..9f4449d9553869aa66619d446048d105f9597664 100644 |
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart |
@@ -391,7 +391,28 @@ bool hasField(type, name) => _hasSigEntry(type, _fieldSig, name); |
final _extensionType = JS('', 'Symbol("extensionType")'); |
-getExtensionType(obj) => JS('', '#[#]', obj, _extensionType); |
+getExtensionType(obj) { |
+ var result = JS('', '#[#]', obj, _extensionType); |
+ if (result != null) return result; |
+ |
+ if (JS('bool', 'typeof # != "object" || # instanceof #.Object', obj, obj, |
+ global_)) { |
+ return null; |
+ } |
+ |
+ // This is an object from another frame. Check to see if we have registered |
+ // an extension in case this is a DOM/native type. |
+ var jsType = JS('', '#.constructor', obj); |
+ var tag = JS('', '#.name', jsType); |
+ if (JS('bool', '#.has(#)', _extMap, tag)) { |
+ var jsProto = JS('', '#.__proto__', obj); |
+ var dartType = JS('', '#.get(#)', _extMap, tag); |
+ _installExtension(jsType, jsProto, dartType); |
+ return dartType; |
+ } |
+ |
+ return null; |
+} |
final dartx = JS('', 'dartx'); |
@@ -437,6 +458,15 @@ void _installPropertiesForObject(jsProto) { |
} |
} |
+var _extMap; |
+ |
+_cacheExtension(jsProto, dartType) { |
+ if (_extMap == null) _extMap = JS('', 'new Map()'); |
+ // TODO(vsm): Make this work on non-Chrome browsers. |
+ var tag = JS('', '#.constructor.name', jsProto); |
+ JS('', '#.set(#, #)', _extMap, tag, dartType); |
+} |
+ |
/// Copy symbols from the prototype of the source to destination. |
/// These are the only properties safe to copy onto an existing public |
/// JavaScript class. |
@@ -452,13 +482,21 @@ registerExtension(jsType, dartExtType) => JS( |
// broken. |
if (!jsProto) return; |
- $_installProperties(jsProto, $dartExtType, jsProto[$_extensionType]); |
+ $_cacheExtension(jsProto, $dartExtType); |
// Mark the JS type's instances so we can easily check for extensions. |
- jsProto[$_extensionType] = $dartExtType; |
+ $_installExtension(jsType, jsProto, dartExtType); |
+})()'''); |
+ |
+_installExtension(jsType, jsProto, dartType) => JS( |
+ '', |
+ '''(() => { |
+ $_installProperties(jsProto, $dartType, jsProto[$_extensionType]); |
+ // Mark the JS type's instances so we can easily check for extensions. |
+ jsProto[$_extensionType] = $dartType; |
function updateSig(sigF) { |
- let originalDesc = $getOwnPropertyDescriptor($dartExtType, sigF); |
+ let originalDesc = $getOwnPropertyDescriptor($dartType, sigF); |
if (originalDesc === void 0) return; |
let originalSigFn = originalDesc.get; |
$assert_(originalSigFn); |
@@ -468,7 +506,7 @@ registerExtension(jsType, dartExtType) => JS( |
updateSig($_fieldSig); |
updateSig($_getterSig); |
updateSig($_setterSig); |
-})()'''); |
+ })()'''); |
/// |
/// Mark a concrete type as implementing extension methods. |