| Index: pkg/compiler/lib/src/js_backend/native_data.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
|
| index 6480e32885b5ae2474f7c3f7a322b699e9365b5f..283e16d1d08c1804d4cedd58eff5807cc71ce5ae 100644
|
| --- a/pkg/compiler/lib/src/js_backend/native_data.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/native_data.dart
|
| @@ -5,14 +5,7 @@
|
| library js_backend.native_data;
|
|
|
| import '../common.dart';
|
| -import '../elements/elements.dart'
|
| - show
|
| - ClassElement,
|
| - Element,
|
| - FieldElement,
|
| - LibraryElement,
|
| - MemberElement,
|
| - MethodElement;
|
| +import '../elements/elements.dart' show ClassElement;
|
| import '../elements/entities.dart';
|
| import '../native/behavior.dart' show NativeBehavior;
|
|
|
| @@ -29,13 +22,13 @@ abstract class NativeClassData {
|
| bool isNativeClass(ClassEntity element);
|
|
|
| /// Returns `true` if [element] or any of its superclasses is native.
|
| - bool isNativeOrExtendsNative(ClassElement element);
|
| + bool isNativeOrExtendsNative(ClassEntity element);
|
|
|
| /// Returns `true` if [element] is a JsInterop library.
|
| - bool isJsInteropLibrary(LibraryElement element);
|
| + bool isJsInteropLibrary(LibraryEntity element);
|
|
|
| /// Returns `true` if [element] is a JsInterop class.
|
| - bool isJsInteropClass(ClassElement element);
|
| + bool isJsInteropClass(ClassEntity element);
|
| }
|
|
|
| /// Additional element information for native classes and methods and js-interop
|
| @@ -52,17 +45,17 @@ abstract class NativeData extends NativeClassData {
|
| bool isNativeMember(MemberEntity element);
|
|
|
| /// Returns the [NativeBehavior] for calling the native [method].
|
| - NativeBehavior getNativeMethodBehavior(MethodElement method);
|
| + NativeBehavior getNativeMethodBehavior(FunctionEntity method);
|
|
|
| /// Returns the [NativeBehavior] for reading from the native [field].
|
| - NativeBehavior getNativeFieldLoadBehavior(FieldElement field);
|
| + NativeBehavior getNativeFieldLoadBehavior(FieldEntity field);
|
|
|
| /// Returns the [NativeBehavior] for writing to the native [field].
|
| - NativeBehavior getNativeFieldStoreBehavior(FieldElement field);
|
| + NativeBehavior getNativeFieldStoreBehavior(FieldEntity field);
|
|
|
| /// Returns `true` if the name of [element] is fixed for the generated
|
| /// JavaScript.
|
| - bool hasFixedBackendName(MemberElement element);
|
| + bool hasFixedBackendName(MemberEntity element);
|
|
|
| /// Computes the name for [element] to use in the generated JavaScript. This
|
| /// is either given through a native annotation or a js interop annotation.
|
| @@ -71,25 +64,25 @@ abstract class NativeData extends NativeClassData {
|
| /// Computes the name prefix for [element to use in the generated JavaScript.
|
| /// For static and top-level members and constructors this is based on the
|
| /// names for the library and/or the enclosing class.
|
| - String getFixedBackendMethodPath(MethodElement element);
|
| + String getFixedBackendMethodPath(FunctionEntity element);
|
|
|
| /// Returns the list of non-directive native tag words for [cls].
|
| - List<String> getNativeTagsOfClass(ClassElement cls);
|
| + List<String> getNativeTagsOfClass(ClassEntity cls);
|
|
|
| /// Returns `true` if [cls] has a `!nonleaf` tag word.
|
| - bool hasNativeTagsForcedNonLeaf(ClassElement cls);
|
| + bool hasNativeTagsForcedNonLeaf(ClassEntity cls);
|
|
|
| /// Returns `true` if [element] is a JsInterop method.
|
| bool isJsInteropMember(MemberEntity element);
|
|
|
| /// Returns the explicit js interop name for library [element].
|
| - String getJsInteropLibraryName(LibraryElement element);
|
| + String getJsInteropLibraryName(LibraryEntity element);
|
|
|
| /// Returns the explicit js interop name for class [element].
|
| - String getJsInteropClassName(ClassElement element);
|
| + String getJsInteropClassName(ClassEntity element);
|
|
|
| /// Returns the explicit js interop name for member [element].
|
| - String getJsInteropMemberName(MemberElement element);
|
| + String getJsInteropMemberName(MemberEntity element);
|
|
|
| /// Apply JS$ escaping scheme to convert possible escaped Dart names into
|
| /// JS names.
|
| @@ -102,112 +95,111 @@ abstract class NativeClassDataBuilder {
|
| /// The tag info string contains comma-separated 'words' which are either
|
| /// dispatch tags (having JavaScript identifier syntax) and directives that
|
| /// begin with `!`.
|
| - void setNativeClassTagInfo(ClassElement cls, String tagInfo);
|
| + void setNativeClassTagInfo(ClassEntity cls, String tagInfo);
|
|
|
| /// Marks [element] as an explicit part of JsInterop. The js interop name is
|
| /// expected to be computed later.
|
| - void markAsJsInteropLibrary(LibraryElement element);
|
| + void markAsJsInteropLibrary(LibraryEntity element);
|
|
|
| /// Marks [element] as an explicit part of JsInterop. The js interop name is
|
| /// expected to be computed later.
|
| - void markAsJsInteropClass(ClassElement element);
|
| + void markAsJsInteropClass(ClassEntity element);
|
| }
|
|
|
| abstract class NativeDataBuilder {
|
| /// Registers the [behavior] for calling the native [method].
|
| - void setNativeMethodBehavior(MethodElement method, NativeBehavior behavior);
|
| + void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior);
|
|
|
| /// Registers the [behavior] for reading from the native [field].
|
| - void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior);
|
| + void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior);
|
|
|
| /// Registers the [behavior] for writing to the native [field].
|
| - void setNativeFieldStoreBehavior(FieldElement field, NativeBehavior behavior);
|
| + void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior);
|
|
|
| /// Returns the list of native tag words for [cls].
|
| - List<String> getNativeTagsOfClassRaw(ClassElement cls);
|
| + List<String> getNativeTagsOfClassRaw(ClassEntity cls);
|
|
|
| /// Returns [element] as an explicit part of JsInterop. The js interop name is
|
| /// expected to be computed later.
|
| - void markAsJsInteropMember(MemberElement element);
|
| + void markAsJsInteropMember(MemberEntity element);
|
|
|
| /// Sets the native [name] for the member [element]. This name is used for
|
| /// [element] in the generated JavaScript.
|
| - void setNativeMemberName(MemberElement element, String name);
|
| + void setNativeMemberName(MemberEntity element, String name);
|
|
|
| /// Sets the explicit js interop [name] for the library [element].
|
| - void setJsInteropLibraryName(LibraryElement element, String name);
|
| + void setJsInteropLibraryName(LibraryEntity element, String name);
|
|
|
| /// Sets the explicit js interop [name] for the class [element].
|
| - void setJsInteropClassName(ClassElement element, String name);
|
| + void setJsInteropClassName(ClassEntity element, String name);
|
|
|
| /// Sets the explicit js interop [name] for the member [element].
|
| - void setJsInteropMemberName(MemberElement element, String name);
|
| + void setJsInteropMemberName(MemberEntity element, String name);
|
| }
|
|
|
| class NativeDataImpl
|
| implements NativeData, NativeDataBuilder, NativeClassDataBuilder {
|
| /// The JavaScript names for elements implemented via typed JavaScript
|
| /// interop.
|
| - Map<LibraryElement, String> jsInteropLibraryNames =
|
| - <LibraryElement, String>{};
|
| - Map<ClassElement, String> jsInteropClassNames = <ClassElement, String>{};
|
| - Map<MemberElement, String> jsInteropMemberNames = <MemberElement, String>{};
|
| + Map<LibraryEntity, String> jsInteropLibraryNames = <LibraryEntity, String>{};
|
| + Map<ClassEntity, String> jsInteropClassNames = <ClassEntity, String>{};
|
| + Map<MemberEntity, String> jsInteropMemberNames = <MemberEntity, String>{};
|
|
|
| /// The JavaScript names for native JavaScript elements implemented.
|
| - Map<Element, String> nativeMemberName = <Element, String>{};
|
| + Map<MemberEntity, String> nativeMemberName = <MemberEntity, String>{};
|
|
|
| /// Tag info for native JavaScript classes names. See
|
| /// [setNativeClassTagInfo].
|
| - Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
|
| + Map<ClassEntity, String> nativeClassTagInfo = <ClassEntity, String>{};
|
|
|
| /// Cache for [NativeBehavior]s for calling native methods.
|
| - Map<MethodElement, NativeBehavior> nativeMethodBehavior =
|
| - <MethodElement, NativeBehavior>{};
|
| + Map<FunctionEntity, NativeBehavior> nativeMethodBehavior =
|
| + <FunctionEntity, NativeBehavior>{};
|
|
|
| /// Cache for [NativeBehavior]s for reading from native fields.
|
| - Map<MemberElement, NativeBehavior> nativeFieldLoadBehavior =
|
| - <FieldElement, NativeBehavior>{};
|
| + Map<MemberEntity, NativeBehavior> nativeFieldLoadBehavior =
|
| + <FieldEntity, NativeBehavior>{};
|
|
|
| /// Cache for [NativeBehavior]s for writing to native fields.
|
| - Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior =
|
| - <FieldElement, NativeBehavior>{};
|
| + Map<MemberEntity, NativeBehavior> nativeFieldStoreBehavior =
|
| + <FieldEntity, NativeBehavior>{};
|
|
|
| /// Prefix used to escape JS names that are not valid Dart names
|
| /// when using JSInterop.
|
| static const String _jsInteropEscapePrefix = r'JS$';
|
|
|
| /// Returns `true` if [element] is explicitly marked as part of JsInterop.
|
| - bool _isJsInteropLibrary(LibraryElement element) {
|
| + bool _isJsInteropLibrary(LibraryEntity element) {
|
| return jsInteropLibraryNames.containsKey(element);
|
| }
|
|
|
| /// Returns `true` if [element] is explicitly marked as part of JsInterop.
|
| - bool _isJsInteropClass(ClassElement element) {
|
| + bool _isJsInteropClass(ClassEntity element) {
|
| return jsInteropClassNames.containsKey(element);
|
| }
|
|
|
| /// Returns `true` if [element] is explicitly marked as part of JsInterop.
|
| - bool _isJsInteropMember(MemberElement element) {
|
| + bool _isJsInteropMember(MemberEntity element) {
|
| return jsInteropMemberNames.containsKey(element);
|
| }
|
|
|
| @override
|
| - void markAsJsInteropLibrary(LibraryElement element) {
|
| + void markAsJsInteropLibrary(LibraryEntity element) {
|
| jsInteropLibraryNames[element] = null;
|
| }
|
|
|
| @override
|
| - void markAsJsInteropClass(ClassElement element) {
|
| + void markAsJsInteropClass(ClassEntity element) {
|
| jsInteropClassNames[element] = null;
|
| }
|
|
|
| @override
|
| - void markAsJsInteropMember(MemberElement element) {
|
| + void markAsJsInteropMember(MemberEntity element) {
|
| jsInteropMemberNames[element] = null;
|
| }
|
|
|
| /// Sets the explicit js interop [name] for the library [element].
|
| - void setJsInteropLibraryName(LibraryElement element, String name) {
|
| + void setJsInteropLibraryName(LibraryEntity element, String name) {
|
| assert(invariant(element, _isJsInteropLibrary(element),
|
| message:
|
| 'Library $element is not js interop but given a js interop name.'));
|
| @@ -215,7 +207,7 @@ class NativeDataImpl
|
| }
|
|
|
| /// Sets the explicit js interop [name] for the class [element].
|
| - void setJsInteropClassName(ClassElement element, String name) {
|
| + void setJsInteropClassName(ClassEntity element, String name) {
|
| assert(invariant(element, _isJsInteropClass(element),
|
| message:
|
| 'Class $element is not js interop but given a js interop name.'));
|
| @@ -223,7 +215,7 @@ class NativeDataImpl
|
| }
|
|
|
| /// Sets the explicit js interop [name] for the member [element].
|
| - void setJsInteropMemberName(MemberElement element, String name) {
|
| + void setJsInteropMemberName(MemberEntity element, String name) {
|
| assert(invariant(element, _isJsInteropMember(element),
|
| message:
|
| 'Member $element is not js interop but given a js interop name.'));
|
| @@ -231,35 +223,38 @@ class NativeDataImpl
|
| }
|
|
|
| /// Returns the explicit js interop name for library [element].
|
| - String getJsInteropLibraryName(LibraryElement element) {
|
| + String getJsInteropLibraryName(LibraryEntity element) {
|
| return jsInteropLibraryNames[element];
|
| }
|
|
|
| /// Returns the explicit js interop name for class [element].
|
| - String getJsInteropClassName(ClassElement element) {
|
| + String getJsInteropClassName(ClassEntity element) {
|
| return jsInteropClassNames[element];
|
| }
|
|
|
| /// Returns the explicit js interop name for member [element].
|
| - String getJsInteropMemberName(MemberElement element) {
|
| + String getJsInteropMemberName(MemberEntity element) {
|
| return jsInteropMemberNames[element];
|
| }
|
|
|
| /// Returns `true` if [element] is a JsInterop library.
|
| - bool isJsInteropLibrary(LibraryElement element) =>
|
| + bool isJsInteropLibrary(LibraryEntity element) =>
|
| _isJsInteropLibrary(element);
|
|
|
| /// Returns `true` if [element] is a JsInterop class.
|
| - bool isJsInteropClass(ClassElement element) => _isJsInteropClass(element);
|
| + bool isJsInteropClass(ClassEntity element) => _isJsInteropClass(element);
|
|
|
| /// Returns `true` if [element] is a JsInterop method.
|
| - bool isJsInteropMember(MemberElement element) {
|
| - if (element.isFunction || element.isConstructor || element.isAccessor) {
|
| - MethodElement function = element;
|
| + bool isJsInteropMember(MemberEntity element) {
|
| + if (element.isFunction ||
|
| + element.isConstructor ||
|
| + element.isGetter ||
|
| + element.isSetter) {
|
| + FunctionEntity function = element;
|
| if (!function.isExternal) return false;
|
|
|
| if (_isJsInteropMember(function)) return true;
|
| - if (function.isClassMember) {
|
| + if (function.enclosingClass != null) {
|
| return _isJsInteropClass(function.enclosingClass);
|
| }
|
| if (function.isTopLevel) {
|
| @@ -273,39 +268,38 @@ class NativeDataImpl
|
|
|
| /// Returns `true` if the name of [element] is fixed for the generated
|
| /// JavaScript.
|
| - bool hasFixedBackendName(MemberElement element) {
|
| - return isJsInteropMember(element) ||
|
| - nativeMemberName.containsKey(element.declaration);
|
| + bool hasFixedBackendName(MemberEntity element) {
|
| + return isJsInteropMember(element) || nativeMemberName.containsKey(element);
|
| }
|
|
|
| /// Computes the name for [element] to use in the generated JavaScript. This
|
| /// is either given through a native annotation or a js interop annotation.
|
| - String getFixedBackendName(MemberElement element) {
|
| - String name = nativeMemberName[element.declaration];
|
| + String getFixedBackendName(MemberEntity element) {
|
| + String name = nativeMemberName[element];
|
| if (name == null && isJsInteropMember(element)) {
|
| // If an element isJsInterop but _isJsInterop is false that means it is
|
| // considered interop as the parent class is interop.
|
| name = element.isConstructor
|
| ? _jsClassNameHelper(element.enclosingClass)
|
| : _jsMemberNameHelper(element);
|
| - nativeMemberName[element.declaration] = name;
|
| + nativeMemberName[element] = name;
|
| }
|
| return name;
|
| }
|
|
|
| - String _jsLibraryNameHelper(LibraryElement element) {
|
| + String _jsLibraryNameHelper(LibraryEntity element) {
|
| String jsInteropName = getJsInteropLibraryName(element);
|
| if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
|
| return 'self';
|
| }
|
|
|
| - String _jsClassNameHelper(ClassElement element) {
|
| + String _jsClassNameHelper(ClassEntity element) {
|
| String jsInteropName = getJsInteropClassName(element);
|
| if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
|
| return computeUnescapedJSInteropName(element.name);
|
| }
|
|
|
| - String _jsMemberNameHelper(MemberElement element) {
|
| + String _jsMemberNameHelper(MemberEntity element) {
|
| String jsInteropName = jsInteropMemberNames[element];
|
| assert(invariant(element,
|
| !(jsInteropMemberNames.containsKey(element) && jsInteropName == null),
|
| @@ -324,7 +318,7 @@ class NativeDataImpl
|
| /// For example: fixedBackendPath for the static method createMap in the
|
| /// Map class of the goog.map JavaScript library would have path
|
| /// "goog.maps.Map".
|
| - String getFixedBackendMethodPath(MethodElement element) {
|
| + String getFixedBackendMethodPath(FunctionEntity element) {
|
| if (!isJsInteropMember(element)) return null;
|
| if (element.isInstanceMember) return 'this';
|
| if (element.isConstructor) {
|
| @@ -338,19 +332,19 @@ class NativeDataImpl
|
| return sb.toString();
|
| }
|
|
|
| - String _fixedBackendClassPath(ClassElement element) {
|
| + String _fixedBackendClassPath(ClassEntity element) {
|
| if (!isJsInteropClass(element)) return null;
|
| return _jsLibraryNameHelper(element.library);
|
| }
|
|
|
| /// Returns `true` if [cls] is a native class.
|
| - bool isNativeClass(ClassElement element) {
|
| + bool isNativeClass(ClassEntity element) {
|
| if (isJsInteropClass(element)) return true;
|
| return nativeClassTagInfo.containsKey(element);
|
| }
|
|
|
| /// Returns `true` if [element] is a native member of a native class.
|
| - bool isNativeMember(MemberElement element) {
|
| + bool isNativeMember(MemberEntity element) {
|
| if (isJsInteropMember(element)) return true;
|
| return nativeMemberName.containsKey(element);
|
| }
|
| @@ -367,18 +361,16 @@ class NativeDataImpl
|
|
|
| /// Sets the native [name] for the member [element]. This name is used for
|
| /// [element] in the generated JavaScript.
|
| - void setNativeMemberName(MemberElement element, String name) {
|
| + void setNativeMemberName(MemberEntity element, String name) {
|
| // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
|
| // might enqueue [element] several times (before processing it) and computes
|
| // name on each call to `internalAddToWorkList`.
|
| - assert(invariant(
|
| - element,
|
| - nativeMemberName[element.declaration] == null ||
|
| - nativeMemberName[element.declaration] == name,
|
| + assert(invariant(element,
|
| + nativeMemberName[element] == null || nativeMemberName[element] == name,
|
| message: "Native member name set inconsistently on $element: "
|
| - "Existing name '${nativeMemberName[element.declaration]}', "
|
| + "Existing name '${nativeMemberName[element]}', "
|
| "new name '$name'."));
|
| - nativeMemberName[element.declaration] = name;
|
| + nativeMemberName[element] = name;
|
| }
|
|
|
| /// Sets the native tag info for [cls].
|
| @@ -386,48 +378,46 @@ class NativeDataImpl
|
| /// The tag info string contains comma-separated 'words' which are either
|
| /// dispatch tags (having JavaScript identifier syntax) and directives that
|
| /// begin with `!`.
|
| - void setNativeClassTagInfo(ClassElement cls, String tagInfo) {
|
| + void setNativeClassTagInfo(ClassEntity cls, String tagInfo) {
|
| // TODO(johnniwinther): Assert that this is only called once. The memory
|
| // compiler copies pre-processed elements into a new compiler through
|
| // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
|
| // method.
|
| - assert(invariant(
|
| - cls,
|
| - nativeClassTagInfo[cls.declaration] == null ||
|
| - nativeClassTagInfo[cls.declaration] == tagInfo,
|
| + assert(invariant(cls,
|
| + nativeClassTagInfo[cls] == null || nativeClassTagInfo[cls] == tagInfo,
|
| message: "Native tag info set inconsistently on $cls: "
|
| - "Existing tag info '${nativeClassTagInfo[cls.declaration]}', "
|
| + "Existing tag info '${nativeClassTagInfo[cls]}', "
|
| "new tag info '$tagInfo'."));
|
| - nativeClassTagInfo[cls.declaration] = tagInfo;
|
| + nativeClassTagInfo[cls] = tagInfo;
|
| }
|
|
|
| /// Returns the list of native tag words for [cls].
|
| - List<String> getNativeTagsOfClassRaw(ClassElement cls) {
|
| - String quotedName = nativeClassTagInfo[cls.declaration];
|
| + List<String> getNativeTagsOfClassRaw(ClassEntity cls) {
|
| + String quotedName = nativeClassTagInfo[cls];
|
| return quotedName.substring(1, quotedName.length - 1).split(',');
|
| }
|
|
|
| /// Returns the list of non-directive native tag words for [cls].
|
| - List<String> getNativeTagsOfClass(ClassElement cls) {
|
| + List<String> getNativeTagsOfClass(ClassEntity cls) {
|
| return getNativeTagsOfClassRaw(cls)
|
| .where((s) => !s.startsWith('!'))
|
| .toList();
|
| }
|
|
|
| /// Returns `true` if [cls] has a `!nonleaf` tag word.
|
| - bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
|
| + bool hasNativeTagsForcedNonLeaf(ClassEntity cls) {
|
| return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
|
| }
|
|
|
| /// Returns the [NativeBehavior] for calling the native [method].
|
| - NativeBehavior getNativeMethodBehavior(MethodElement method) {
|
| + NativeBehavior getNativeMethodBehavior(FunctionEntity method) {
|
| assert(invariant(method, nativeMethodBehavior.containsKey(method),
|
| message: "No native method behavior has been computed for $method."));
|
| return nativeMethodBehavior[method];
|
| }
|
|
|
| /// Returns the [NativeBehavior] for reading from the native [field].
|
| - NativeBehavior getNativeFieldLoadBehavior(FieldElement field) {
|
| + NativeBehavior getNativeFieldLoadBehavior(FieldEntity field) {
|
| assert(invariant(field, nativeFieldLoadBehavior.containsKey(field),
|
| message: "No native field load behavior has been "
|
| "computed for $field."));
|
| @@ -435,7 +425,7 @@ class NativeDataImpl
|
| }
|
|
|
| /// Returns the [NativeBehavior] for writing to the native [field].
|
| - NativeBehavior getNativeFieldStoreBehavior(FieldElement field) {
|
| + NativeBehavior getNativeFieldStoreBehavior(FieldEntity field) {
|
| assert(invariant(field, nativeFieldStoreBehavior.containsKey(field),
|
| message: "No native field store behavior has been "
|
| "computed for $field."));
|
| @@ -443,18 +433,17 @@ class NativeDataImpl
|
| }
|
|
|
| /// Registers the [behavior] for calling the native [method].
|
| - void setNativeMethodBehavior(MethodElement method, NativeBehavior behavior) {
|
| + void setNativeMethodBehavior(FunctionEntity method, NativeBehavior behavior) {
|
| nativeMethodBehavior[method] = behavior;
|
| }
|
|
|
| /// Registers the [behavior] for reading from the native [field].
|
| - void setNativeFieldLoadBehavior(FieldElement field, NativeBehavior behavior) {
|
| + void setNativeFieldLoadBehavior(FieldEntity field, NativeBehavior behavior) {
|
| nativeFieldLoadBehavior[field] = behavior;
|
| }
|
|
|
| /// Registers the [behavior] for writing to the native [field].
|
| - void setNativeFieldStoreBehavior(
|
| - FieldElement field, NativeBehavior behavior) {
|
| + void setNativeFieldStoreBehavior(FieldEntity field, NativeBehavior behavior) {
|
| nativeFieldStoreBehavior[field] = behavior;
|
| }
|
|
|
|
|