Index: sdk/lib/_internal/js_runtime/lib/interceptors.dart |
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart |
index 23025ad578cc34276949080428a92a0e7b49fcab..516c43f90bd6d8b40bde15e3377922a321a57064 100644 |
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart |
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart |
@@ -168,7 +168,16 @@ getNativeInterceptor(object) { |
} |
} |
- var interceptor = lookupAndCacheInterceptor(object); |
+ // Check for cached UnknownJavaScriptObject. This avoids doing the slow |
+ // dispatch-record based lookup for repeated js-interop classes. |
+ var constructor = JS('', '#.constructor', object); |
+ var interceptor = JS('', '#.get(#)', constructorToInterceptor, constructor); |
+ if (interceptor != null) return interceptor; |
+ |
+ // This takes care of dispatch-record based caching, but not constructor based |
+ // caching of [UnknownJavaScriptObject]s. |
+ interceptor = lookupAndCacheInterceptor(object); |
+ |
if (interceptor == null) { |
// JavaScript Objects created via object literals and `Object.create(null)` |
// are 'plain' Objects. This test could be simplified and the dispatch path |
@@ -181,13 +190,18 @@ getNativeInterceptor(object) { |
if (JS('bool', '# == null || # === Object.prototype', proto, proto)) { |
return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject); |
} else { |
- return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject); |
+ interceptor = JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject); |
+ JS('', '#.set(#, #)', constructorToInterceptor, constructor, interceptor); |
+ return interceptor; |
} |
} |
return interceptor; |
} |
+var constructorToInterceptor = |
+ JS('', 'typeof(self.WeakMap) == "undefined" ? new Map() : new WeakMap()'); |
+ |
/** |
* Data structure used to map a [Type] to the [Interceptor] and constructors for |
* that type. It is JavaScript array of 3N entries of adjacent slots containing |