| 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..7246c406edf480acb8857ee3b5d3d439082cdc11 100644
|
| --- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart
|
| +++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
|
| @@ -168,24 +168,69 @@ getNativeInterceptor(object) {
|
| }
|
| }
|
|
|
| - var 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
|
| - // be faster if Object.prototype was pre-patched with a non-leaf dispatch
|
| - // record.
|
| - if (JS('bool', 'typeof # == "function"', object)) {
|
| - return JS_INTERCEPTOR_CONSTANT(JavaScriptFunction);
|
| - }
|
| - var proto = JS('', 'Object.getPrototypeOf(#)', object);
|
| - if (JS('bool', '# == null || # === Object.prototype', proto, proto)) {
|
| - return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject);
|
| - } else {
|
| - return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject);
|
| - }
|
| + // 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 = lookupInterceptorByConstructor(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) return interceptor;
|
| +
|
| + // JavaScript Objects created via object literals and `Object.create(null)`
|
| + // are 'plain' Objects. This test could be simplified and the dispatch path
|
| + // be faster if Object.prototype was pre-patched with a non-leaf dispatch
|
| + // record.
|
| + if (JS('bool', 'typeof # == "function"', object)) {
|
| + interceptor = JS_INTERCEPTOR_CONSTANT(JavaScriptFunction);
|
| + // TODO(sra): Investigate caching on `Function`. It might be impossible if
|
| + // some HTML embedded objects on some browsers are (still) JS functions.
|
| + return interceptor;
|
| + }
|
| + var proto = JS('', 'Object.getPrototypeOf(#)', object);
|
| + if (JS('bool', '# == null', proto)) {
|
| + // Nowhere to cache output.
|
| + return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject);
|
| + }
|
| + interceptor = JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject);
|
| + if (JS('bool', '# === Object.prototype', proto)) {
|
| + interceptor = JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject);
|
| + // TODO(sra): Investigate caching on 'Object'. It might be impossible if
|
| + // some native class is plain Object (e.g. like Firefox's ImageData).
|
| + return interceptor;
|
| }
|
| + if (JS('bool', 'typeof # == "function"', constructor)) {
|
| + cacheInterceptorOnConstructor(constructor, interceptor);
|
| + return interceptor;
|
| + }
|
| + return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject);
|
| +}
|
| +
|
| +
|
| +// A JS String or Symbol.
|
| +final JS_INTEROP_INTERCEPTOR_TAG = getIsolateAffinityTag(r'_$dart_js');
|
| +
|
| +lookupInterceptorByConstructor(constructor) {
|
| + return constructor == null
|
| + ? null
|
| + : JS('', '#[#]', constructor, JS_INTEROP_INTERCEPTOR_TAG);
|
| +}
|
| +
|
| +void cacheInterceptorOnConstructor(constructor, interceptor) {
|
| + defineProperty(constructor, JS_INTEROP_INTERCEPTOR_TAG, interceptor);
|
| +}
|
| +
|
| +var constructorToInterceptor =
|
| + JS('', 'typeof(self.WeakMap) == "undefined" ? new Map() : new WeakMap()');
|
| +
|
| +XlookupInterceptorByConstructor(constructor) {
|
| + return JS('', '#.get(#)', constructorToInterceptor, constructor);
|
| +}
|
|
|
| - return interceptor;
|
| +void XcacheInterceptorOnConstructor(constructor, interceptor) {
|
| + JS('', '#.set(#, #)', constructorToInterceptor, constructor, interceptor);
|
| }
|
|
|
| /**
|
|
|