| Index: pkg/compiler/lib/src/js_model/closure.dart
 | 
| diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
 | 
| index 1e086df0ee1e031e229e06446932c0be6b491f6b..bf4fad2c23e435e4caea867d47b2f3041d2dd06b 100644
 | 
| --- a/pkg/compiler/lib/src/js_model/closure.dart
 | 
| +++ b/pkg/compiler/lib/src/js_model/closure.dart
 | 
| @@ -96,25 +96,41 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
 | 
|        JsClosedWorld closedWorldRefiner) {
 | 
|      closureModels.forEach((MemberEntity member, ScopeModel model) {
 | 
|        KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
 | 
| -      if (model.scopeInfo != null) {
 | 
| -        _scopeMap[member] = new JsScopeInfo.from(model.scopeInfo, localsMap);
 | 
| -      }
 | 
| -
 | 
| +      assert(model.scopeInfo != null);
 | 
| +      var boxedVariables =
 | 
| +          _elementMap.makeRecordContainer(model.scopeInfo, member, localsMap);
 | 
| +      _scopeMap[member] =
 | 
| +          new JsScopeInfo.from(boxedVariables, model.scopeInfo, localsMap);
 | 
| +      print('created the following scope info $member ${_scopeMap[member]}');
 | 
| +
 | 
| +      Set<JsCapturedScope> capturedScopes = new Set<JsCaptuerdScope>();
 | 
|        model.capturedScopesMap
 | 
|            .forEach((ir.Node node, KernelCapturedScope scope) {
 | 
| +        boxedVariables = _elementMap.makeRecordContainer(
 | 
| +            model.scopeInfo,
 | 
| +            _elementMap.getMember(node),
 | 
| +            localsMap); // TODO: (maybe don't need to call this again.)
 | 
|          if (scope is KernelCapturedLoopScope) {
 | 
|            _capturedScopesMap[node] =
 | 
| -              new JsCapturedLoopScope.from(scope, localsMap);
 | 
| +              new JsCapturedLoopScope.from(boxedVariables, scope, localsMap);
 | 
|          } else {
 | 
| -          _capturedScopesMap[node] = new JsCapturedScope.from(scope, localsMap);
 | 
| +          _capturedScopesMap[node] =
 | 
| +              new JsCapturedScope.from(boxedVariables, scope, localsMap);
 | 
|          }
 | 
| +        capturedScopes.add(_capturedScopesMap[node]);
 | 
| +        print('captured scope info $node ${_capturedScopesMap[node]}');
 | 
|        });
 | 
|  
 | 
|        Map<ir.FunctionNode, KernelScopeInfo> closuresToGenerate =
 | 
|            model.closuresToGenerate;
 | 
|        for (ir.FunctionNode node in closuresToGenerate.keys) {
 | 
| -        _produceSyntheticElements(
 | 
| -            member, node, closuresToGenerate[node], closedWorldRefiner);
 | 
| +        KernelClosureClass closureClass = _produceSyntheticElements(member,
 | 
| +            node, closuresToGenerate[node], capturedScopes, closedWorldRefiner);
 | 
| +        // Add one for each call method.
 | 
| +        KernelToLocalsMap localsMap =
 | 
| +            _globalLocalsMap.getLocalsMap(closureClass.callMethod);
 | 
| +        _scopeMap[closureClass.callMethod] = closureClass;
 | 
| +        print('then we made $closureClass starting from ${node.parent}');
 | 
|        }
 | 
|      });
 | 
|    }
 | 
| @@ -125,11 +141,22 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
 | 
|    /// the closure accesses a variable that gets accessed at some point), then
 | 
|    /// boxForCapturedVariables stores the local context for those variables.
 | 
|    /// If no variables are captured, this parameter is null.
 | 
| -  void _produceSyntheticElements(MemberEntity member, ir.FunctionNode node,
 | 
| -      KernelScopeInfo info, JsClosedWorld closedWorldRefiner) {
 | 
| +  KernelClosureClass _produceSyntheticElements(
 | 
| +      MemberEntity member,
 | 
| +      ir.FunctionNode node,
 | 
| +      KernelScopeInfo info,
 | 
| +      Set<JsCaptuerdScope> capturedScopes,
 | 
| +      JsClosedWorld closedWorldRefiner) {
 | 
|      KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(member);
 | 
| +
 | 
|      KernelClosureClass closureClass = closedWorldRefiner.buildClosureClass(
 | 
| -        member, node, member.library, info, node.location, localsMap);
 | 
| +        member,
 | 
| +        node,
 | 
| +        member.library,
 | 
| +        capturedScopes,
 | 
| +        info,
 | 
| +        node.location,
 | 
| +        localsMap);
 | 
|  
 | 
|      // We want the original declaration where that function is used to point
 | 
|      // to the correct closure class.
 | 
| @@ -142,6 +169,7 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
 | 
|      }
 | 
|      assert(entity != null);
 | 
|      _closureRepresentationMap[entity] = closureClass;
 | 
| +    return closureClass;
 | 
|    }
 | 
|  
 | 
|    @override
 | 
| @@ -157,8 +185,6 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
 | 
|      return _scopeMap[entity] ?? getClosureRepresentationInfo(entity);
 | 
|    }
 | 
|  
 | 
| -  // TODO(efortuna): Eventually capturedScopesMap[node] should always
 | 
| -  // be non-null, and we should just test that with an assert.
 | 
|    @override
 | 
|    CapturedScope getCapturedScope(MemberEntity entity) {
 | 
|      MemberDefinition definition = _elementMap.getMemberDefinition(entity);
 | 
| @@ -174,8 +200,6 @@ class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> {
 | 
|    }
 | 
|  
 | 
|    @override
 | 
| -  // TODO(efortuna): Eventually capturedScopesMap[node] should always
 | 
| -  // be non-null, and we should just test that with an assert.
 | 
|    CapturedLoopScope getCapturedLoopScope(ir.Node loopNode) =>
 | 
|        _capturedScopesMap[loopNode] ?? const CapturedLoopScope();
 | 
|  
 | 
| @@ -208,6 +232,11 @@ class KernelScopeInfo {
 | 
|    /// this scope.
 | 
|    Set<ir.VariableDeclaration> freeVariables = new Set<ir.VariableDeclaration>();
 | 
|  
 | 
| +  /// The set of scopes that this scope captures. In practice we only populate
 | 
| +  /// it if this scope uses a particular variable that is defined in another
 | 
| +  /// scope, and this information is only really useful for closures.
 | 
| +  final Set<ir.Node> capturedScopes = new Set<ir.Node>();
 | 
| +
 | 
|    KernelScopeInfo(this.hasThisLocal)
 | 
|        : localsUsedInTryOrSync = new Set<ir.VariableDeclaration>(),
 | 
|          boxedVariables = new Set<ir.VariableDeclaration>(),
 | 
| @@ -228,7 +257,10 @@ class KernelScopeInfo {
 | 
|    String toString() {
 | 
|      StringBuffer sb = new StringBuffer();
 | 
|      sb.write('this=$hasThisLocal,');
 | 
| -    sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}');
 | 
| +    sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}},');
 | 
| +    sb.write('freeVariables={${freeVariables.join(', ')}},');
 | 
| +    sb.write('boxedVariables={${boxedVariables.join(', ')}},');
 | 
| +    sb.write('capturedVariablesAccessor=$capturedVariablesAccessor');
 | 
|      return sb.toString();
 | 
|    }
 | 
|  }
 | 
| @@ -236,29 +268,24 @@ class KernelScopeInfo {
 | 
|  class JsScopeInfo extends ScopeInfo {
 | 
|    final Set<Local> localsUsedInTryOrSync;
 | 
|    final Local thisLocal;
 | 
| -  final Set<Local> boxedVariables;
 | 
| +  final Map<Local, JRecord> boxedVariables;
 | 
|  
 | 
|    /// The set of variables that were defined in another scope, but are used in
 | 
|    /// this scope.
 | 
|    final Set<Local> freeVariables;
 | 
|  
 | 
| -  JsScopeInfo(this.thisLocal, this.localsUsedInTryOrSync, this.boxedVariables,
 | 
| -      this.freeVariables);
 | 
| -
 | 
| -  JsScopeInfo.from(KernelScopeInfo info, KernelToLocalsMap localsMap)
 | 
| +  JsScopeInfo.from(
 | 
| +      this.boxedVariables, KernelScopeInfo info, KernelToLocalsMap localsMap)
 | 
|        : this.thisLocal =
 | 
|              info.hasThisLocal ? new ThisLocal(localsMap.currentMember) : null,
 | 
|          this.localsUsedInTryOrSync =
 | 
|              info.localsUsedInTryOrSync.map(localsMap.getLocalVariable).toSet(),
 | 
| -        this.boxedVariables =
 | 
| -            info.boxedVariables.map(localsMap.getLocalVariable).toSet(),
 | 
|          this.freeVariables =
 | 
|              info.freeVariables.map(localsMap.getLocalVariable).toSet();
 | 
|  
 | 
|    void forEachBoxedVariable(f(Local local, FieldEntity field)) {
 | 
| -    boxedVariables.forEach((Local l) {
 | 
| -      // TODO(efortuna): add FieldEntities as created.
 | 
| -      f(l, null);
 | 
| +    boxedVariables.forEach((Local l, JRecord box) {
 | 
| +      f(l, box);
 | 
|      });
 | 
|    }
 | 
|  
 | 
| @@ -267,21 +294,21 @@ class JsScopeInfo extends ScopeInfo {
 | 
|  
 | 
|    String toString() {
 | 
|      StringBuffer sb = new StringBuffer();
 | 
| +    sb.write('JsScopeInfo: ');
 | 
|      sb.write('this=$thisLocal,');
 | 
|      sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}');
 | 
| +    sb.write('freeVariables={${freeVariables.join(', ')}}');
 | 
| +    sb.write('boxedVariables={$boxedVariables}');
 | 
|      return sb.toString();
 | 
|    }
 | 
|  
 | 
| -  bool isBoxed(Local variable) => boxedVariables.contains(variable);
 | 
| +  bool isBoxed(Local variable) => boxedVariables.containsKey(variable);
 | 
|  }
 | 
|  
 | 
|  class KernelCapturedScope extends KernelScopeInfo {
 | 
| -  final ir.TreeNode context;
 | 
| -
 | 
|    KernelCapturedScope(
 | 
|        Set<ir.VariableDeclaration> boxedVariables,
 | 
|        NodeBox capturedVariablesAccessor,
 | 
| -      this.context,
 | 
|        Set<ir.VariableDeclaration> localsUsedInTryOrSync,
 | 
|        Set<ir.VariableDeclaration> freeVariables,
 | 
|        bool hasThisLocal)
 | 
| @@ -292,14 +319,25 @@ class KernelCapturedScope extends KernelScopeInfo {
 | 
|  }
 | 
|  
 | 
|  class JsCapturedScope extends JsScopeInfo implements CapturedScope {
 | 
| -  final Local context;
 | 
| +  final BoxLocal context;
 | 
|  
 | 
| -  JsCapturedScope.from(
 | 
| +  JsCapturedScope.from(Map<Local, JRecord> boxedVariables,
 | 
|        KernelCapturedScope capturedScope, KernelToLocalsMap localsMap)
 | 
| -      : this.context = localsMap.getLocalVariable(capturedScope.context),
 | 
| -        super.from(capturedScope, localsMap);
 | 
| +      : this.context =
 | 
| +            boxedVariables.isNotEmpty ? boxedVariables.values.first.box : null,
 | 
| +        super.from(boxedVariables, capturedScope, localsMap);
 | 
|  
 | 
|    bool get requiresContextBox => boxedVariables.isNotEmpty;
 | 
| +
 | 
| +  String toString() {
 | 
| +    StringBuffer sb = new StringBuffer();
 | 
| +    sb.write('this=$thisLocal,');
 | 
| +    sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}');
 | 
| +    sb.write('freeVariables={${freeVariables.join(', ')}}');
 | 
| +    sb.write('boxedVariables={$boxedVariables}');
 | 
| +    sb.write('context={$context}');
 | 
| +    return sb.toString();
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  class KernelCapturedLoopScope extends KernelCapturedScope {
 | 
| @@ -309,12 +347,11 @@ class KernelCapturedLoopScope extends KernelCapturedScope {
 | 
|        Set<ir.VariableDeclaration> boxedVariables,
 | 
|        NodeBox capturedVariablesAccessor,
 | 
|        this.boxedLoopVariables,
 | 
| -      ir.TreeNode context,
 | 
|        Set<ir.VariableDeclaration> localsUsedInTryOrSync,
 | 
|        Set<ir.VariableDeclaration> freeVariables,
 | 
|        bool hasThisLocal)
 | 
| -      : super(boxedVariables, capturedVariablesAccessor, context,
 | 
| -            localsUsedInTryOrSync, freeVariables, hasThisLocal);
 | 
| +      : super(boxedVariables, capturedVariablesAccessor, localsUsedInTryOrSync,
 | 
| +            freeVariables, hasThisLocal);
 | 
|  
 | 
|    bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
 | 
|  }
 | 
| @@ -322,36 +359,36 @@ class KernelCapturedLoopScope extends KernelCapturedScope {
 | 
|  class JsCapturedLoopScope extends JsCapturedScope implements CapturedLoopScope {
 | 
|    final List<Local> boxedLoopVariables;
 | 
|  
 | 
| -  JsCapturedLoopScope.from(
 | 
| +  JsCapturedLoopScope.from(Map<Local, JRecord> boxedVariables,
 | 
|        KernelCapturedLoopScope capturedScope, KernelToLocalsMap localsMap)
 | 
|        : this.boxedLoopVariables = capturedScope.boxedLoopVariables
 | 
|              .map(localsMap.getLocalVariable)
 | 
|              .toList(),
 | 
| -        super.from(capturedScope, localsMap);
 | 
| +        super.from(boxedVariables, capturedScope, localsMap);
 | 
|  
 | 
|    bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
 | 
|  }
 | 
|  
 | 
|  // TODO(johnniwinther): Add unittest for the computed [ClosureClass].
 | 
|  class KernelClosureClass extends JsScopeInfo
 | 
| -    implements ClosureRepresentationInfo, JClass {
 | 
| -  final String name;
 | 
| -  final JLibrary library;
 | 
| +    implements ClosureRepresentationInfo {
 | 
|    JFunction callMethod;
 | 
|    final Local closureEntity;
 | 
|    final Local thisLocal;
 | 
| -
 | 
| -  /// Index into the classData, classList and classEnvironment lists where this
 | 
| -  /// entity is stored in [JsToFrontendMapImpl].
 | 
| -  final int classIndex;
 | 
| +  final ClassEntity closureClassEntity;
 | 
|  
 | 
|    final Map<Local, JField> localToFieldMap = new Map<Local, JField>();
 | 
|  
 | 
| +  /// The set of scopes that this scope captures. In practice we only populate
 | 
| +  /// it if this scope uses a particular variable that is defined in another
 | 
| +  /// scope, and this information is only really useful for closures.
 | 
| +  final Set<JsCapturedScope> capturedScopes;
 | 
| +
 | 
|    KernelClosureClass.fromScopeInfo(
 | 
| +      this.closureClassEntity,
 | 
|        ir.FunctionNode closureSourceNode,
 | 
| -      this.name,
 | 
| -      this.classIndex,
 | 
| -      this.library,
 | 
| +      Map<Local, JRecord> boxedVariables,
 | 
| +      this.capturedScopes,
 | 
|        KernelScopeInfo info,
 | 
|        KernelToLocalsMap localsMap)
 | 
|        : closureEntity = closureSourceNode.parent is ir.Member
 | 
| @@ -359,9 +396,7 @@ class KernelClosureClass extends JsScopeInfo
 | 
|              : localsMap.getLocalFunction(closureSourceNode.parent),
 | 
|          thisLocal =
 | 
|              info.hasThisLocal ? new ThisLocal(localsMap.currentMember) : null,
 | 
| -        super.from(info, localsMap);
 | 
| -
 | 
| -  ClassEntity get closureClassEntity => this;
 | 
| +        super.from(boxedVariables, info, localsMap);
 | 
|  
 | 
|    List<Local> get createdFieldEntities => localToFieldMap.keys.toList();
 | 
|  
 | 
| @@ -374,25 +409,36 @@ class KernelClosureClass extends JsScopeInfo
 | 
|    @override
 | 
|    void forEachBoxedVariable(f(Local local, JField field)) {
 | 
|      for (Local l in localToFieldMap.keys) {
 | 
| -      if (localToFieldMap[l] is JBoxedField) f(l, localToFieldMap[l]);
 | 
| +      if (localToFieldMap[l] is JRecord) f(l, localToFieldMap[l]);
 | 
| +    }
 | 
| +    for (JsCapturedScope scope in capturedScopes) {
 | 
| +      scope.forEachBoxedVariable(f);
 | 
|      }
 | 
|    }
 | 
|  
 | 
|    void forEachFreeVariable(f(Local variable, JField field)) {
 | 
|      for (Local l in localToFieldMap.keys) {
 | 
|        var jField = localToFieldMap[l];
 | 
| -      if (jField is! JBoxedField && jField is! BoxLocal) f(l, jField);
 | 
| +      if (jField is! BoxLocal) f(l, jField);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  bool isVariableBoxed(Local variable) =>
 | 
| -      localToFieldMap.keys.contains(variable);
 | 
| -
 | 
| -  bool get isClosure => true;
 | 
| +  bool isVariableBoxed(Local variable) {
 | 
| +    print(
 | 
| +        'RRRRRRRRRRR ${localToFieldMap.keys.contains(variable)} ${capturedScopes}');
 | 
| +    return localToFieldMap.keys.contains(variable) ||
 | 
| +        capturedScopes.any((JsCapturedScope scope) => scope.isBoxed(variable));
 | 
| +  }
 | 
|  
 | 
| -  bool get isAbstract => false;
 | 
| +  @override
 | 
| +  bool isBoxed(Local variable) {
 | 
| +    print(
 | 
| +        'RRRRRRRRRRR ${localToFieldMap.keys.contains(variable)} ${capturedScopes}');
 | 
| +    return localToFieldMap.keys.contains(variable) ||
 | 
| +        capturedScopes.any((JsCapturedScope scope) => scope.isBoxed(variable));
 | 
| +  }
 | 
|  
 | 
| -  String toString() => '${jsElementPrefix}class($name)';
 | 
| +  bool get isClosure => true;
 | 
|  }
 | 
|  
 | 
|  /// A local variable to disambiguate between a variable that has been captured
 | 
| @@ -404,23 +450,62 @@ class NodeBox {
 | 
|    NodeBox(this.name, this.executableContext);
 | 
|  }
 | 
|  
 | 
| +class JClosureClass extends JClass {
 | 
| +  // TODO(efortuna): omg this is so horrible.
 | 
| +  final KernelToLocalsMap localsMap;
 | 
| +
 | 
| +  JClosureClass(this.localsMap, JLibrary library, int classIndex, String name)
 | 
| +      : super(library, classIndex, name, isAbstract: false);
 | 
| +
 | 
| +  @override
 | 
| +  bool get isClosure => true;
 | 
| +
 | 
| +  String toString() => '${jsElementPrefix}closure_class($name)';
 | 
| +}
 | 
| +
 | 
|  class JClosureField extends JField {
 | 
|    JClosureField(String name, int memberIndex,
 | 
|        KernelClosureClass containingClass, bool isConst, bool isAssignable)
 | 
| -      : super(memberIndex, containingClass.library, containingClass,
 | 
| -            new Name(name, containingClass.library),
 | 
| -            isAssignable: isAssignable, isConst: isConst, isStatic: false);
 | 
| +      : super(
 | 
| +            memberIndex,
 | 
| +            containingClass.closureClassEntity.library,
 | 
| +            containingClass.closureClassEntity,
 | 
| +            new Name(name, containingClass.closureClassEntity.library),
 | 
| +            isAssignable: isAssignable,
 | 
| +            isConst: isConst,
 | 
| +            isStatic: false);
 | 
| +}
 | 
| +
 | 
| +/// A container for variables declared in a particular scope that are accessed
 | 
| +/// elsewhere.
 | 
| +// TODO(efortuna, johnniwinther): Don't implement JClass. This isn't actually a
 | 
| +// class.
 | 
| +class JRecordContainer implements JClass {
 | 
| +  final JLibrary library;
 | 
| +  final String name;
 | 
| +
 | 
| +  /// Index into the classData, classList and classEnvironment lists where this
 | 
| +  /// entity is stored in [JsToFrontendMapImpl].
 | 
| +  final int classIndex;
 | 
| +
 | 
| +  JRecordContainer(this.library, this.classIndex, this.name);
 | 
| +
 | 
| +  bool get isAbstract => false;
 | 
| +
 | 
| +  bool get isClosure => false;
 | 
| +
 | 
| +  String toString() => '${jsElementPrefix}record_container($name)';
 | 
|  }
 | 
|  
 | 
| -/// A ClosureField that has been "boxed" to prevent name shadowing with the
 | 
| +/// A variable that has been "boxed" to prevent name shadowing with the
 | 
|  /// original variable and ensure that this variable is updated/read with the
 | 
|  /// most recent value.
 | 
|  /// This corresponds to BoxFieldElement; we reuse BoxLocal from the original
 | 
|  /// algorithm to correspond to the actual name of the variable.
 | 
| -class JBoxedField extends JField {
 | 
| +class JRecord extends JField {
 | 
|    final BoxLocal box;
 | 
| -  JBoxedField(String name, int memberIndex, this.box,
 | 
| -      KernelClosureClass containingClass, bool isConst, bool isAssignable)
 | 
| +  JRecord(String name, int memberIndex, this.box, JClass containingClass,
 | 
| +      bool isConst, bool isAssignable)
 | 
|        : super(memberIndex, containingClass.library, containingClass,
 | 
|              new Name(name, containingClass.library),
 | 
|              isAssignable: isAssignable, isConst: isConst);
 | 
| @@ -434,11 +519,9 @@ class ClosureClassDefinition implements ClassDefinition {
 | 
|  
 | 
|    ClassKind get kind => ClassKind.closure;
 | 
|  
 | 
| -  ir.Node get node =>
 | 
| -      throw new UnsupportedError('ClosureClassDefinition.node for $cls');
 | 
| +  ir.Node get node => throw new UnsupportedError('JRecord.node for $cls');
 | 
|  
 | 
| -  String toString() =>
 | 
| -      'ClosureClassDefinition(kind:$kind,cls:$cls,location:$location)';
 | 
| +  String toString() => 'JRecord(kind:$kind,cls:$cls,location:$location)';
 | 
|  }
 | 
|  
 | 
|  class ClosureMemberData implements MemberData {
 | 
| @@ -517,6 +600,21 @@ class ClosureMemberDefinition implements MemberDefinition {
 | 
|        'ClosureMemberDefinition(kind:$kind,member:$member,location:$location)';
 | 
|  }
 | 
|  
 | 
| +class RecordContainerDefinition implements ClassDefinition {
 | 
| +  final ClassEntity cls;
 | 
| +  final SourceSpan location;
 | 
| +
 | 
| +  RecordContainerDefinition(this.cls, this.location);
 | 
| +
 | 
| +  ClassKind get kind => ClassKind.container;
 | 
| +
 | 
| +  ir.Node get node =>
 | 
| +      throw new UnsupportedError('RecordContainerDefinition.node for $cls');
 | 
| +
 | 
| +  String toString() =>
 | 
| +      'RecordContainerDefinition(kind:$kind,cls:$cls,location:$location)';
 | 
| +}
 | 
| +
 | 
|  /// Collection of scope data collected for a single member.
 | 
|  class ScopeModel {
 | 
|    /// Collection [ScopeInfo] data for the member.
 | 
| 
 |