| Index: sdk/lib/_internal/lib/native_helper.dart
|
| diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
|
| index 5c311f4f69196f764bb7acc1d9aec14534964db1..952f903a8c42ab6a4397c8c1560e6c9eaf129f44 100644
|
| --- a/sdk/lib/_internal/lib/native_helper.dart
|
| +++ b/sdk/lib/_internal/lib/native_helper.dart
|
| @@ -240,6 +240,10 @@ var interceptorsByTag;
|
| /// A JavaScript object mapping tags to `true` or `false`.
|
| var leafTags;
|
|
|
| +/// A JavaScript list mapping subclass interceptor constructors to the native
|
| +/// superclass tag.
|
| +var interceptorToTag;
|
| +
|
| /**
|
| * Associates tags with an interceptor. Called from generated code. The tags
|
| * are all 'leaf' tags representing classes that have no subclasses with
|
| @@ -260,6 +264,28 @@ void defineNativeMethodsNonleaf(String tags, interceptorClass) {
|
| defineNativeMethodsCommon(tags, interceptorClass, false);
|
| }
|
|
|
| +/**
|
| + * Associates tags with an interceptor. Called from generated code. The tags
|
| + * are all non-'leaf' tags, representing classes that have a user defined
|
| + * subclass that requires additional dispatch. [subclassInterceptorClasses] is a
|
| + * list of interceptor classes (i.e. constructors) for the user defined
|
| + * subclasses.
|
| + */
|
| +void defineNativeMethodsExtended(String tags, interceptorClass,
|
| + subclassInterceptorClasses) {
|
| + if (interceptorToTag == null) {
|
| + interceptorToTag = [];
|
| + }
|
| + List classes = JS('JSFixedArray', '#', subclassInterceptorClasses);
|
| + for (int i = 0; i < classes.length; i++) {
|
| + interceptorToTag.add(classes[i]);
|
| + // 'tags' is a single tag.
|
| + interceptorToTag.add(tags);
|
| + }
|
| +
|
| + defineNativeMethodsCommon(tags, interceptorClass, false);
|
| +}
|
| +
|
| void defineNativeMethodsCommon(String tags, var interceptorClass, bool isLeaf) {
|
| var methods = JS('', '#.prototype', interceptorClass);
|
| if (interceptorsByTag == null) interceptorsByTag = JS('=Object', '{}');
|
| @@ -280,6 +306,14 @@ void defineNativeMethodsFinish() {
|
| // classes over unknown.
|
| }
|
|
|
| +String findDispatchTagForInterceptorClass(interceptorClassConstructor) {
|
| + if (interceptorToTag == null) return null;
|
| + int i =
|
| + JS('int', '#.indexOf(#)', interceptorToTag, interceptorClassConstructor);
|
| + if (i < 0) return null;
|
| + return JS('', '#[#]', interceptorToTag, i + 1);
|
| +}
|
| +
|
| lookupInterceptor(var hasOwnPropertyFunction, String tag) {
|
| var map = interceptorsByTag;
|
| if (map == null) return null;
|
| @@ -313,11 +347,23 @@ lookupDispatchRecord(obj) {
|
| var isLeaf =
|
| (leafTags != null) && JS('bool', '(#[#]) === true', leafTags, tag);
|
| if (isLeaf) {
|
| - var fieldName = JS_IS_INDEXABLE_FIELD_NAME();
|
| - bool indexability = JS('bool', r'!!#[#]', interceptor, fieldName);
|
| - return makeDispatchRecord(interceptor, false, null, indexability);
|
| + return makeLeafDispatchRecord(interceptor);
|
| } else {
|
| var proto = JS('', 'Object.getPrototypeOf(#)', obj);
|
| return makeDispatchRecord(interceptor, proto, null, null);
|
| }
|
| }
|
| +
|
| +makeLeafDispatchRecord(interceptor) {
|
| + var fieldName = JS_IS_INDEXABLE_FIELD_NAME();
|
| + bool indexability = JS('bool', r'!!#[#]', interceptor, fieldName);
|
| + return makeDispatchRecord(interceptor, false, null, indexability);
|
| +}
|
| +
|
| +/**
|
| + * [proto] should have no shadowing prototypes that are not also assigned a
|
| + * dispatch rescord.
|
| + */
|
| +setNativeSubclassDispatchRecord(proto, interceptor) {
|
| + setDispatchProperty(proto, makeLeafDispatchRecord(interceptor));
|
| +}
|
|
|