Exemple #1
0
    def run(self, arguments, options):
        # It's a good habit to explicitly cast the type of all return
        # values and arguments. LLDB can't always find them on its own.
        subviews = fb.evaluateInputExpression(arguments[0])
        # subviews = subviewsOfView(selfView)
        view = fb.evaluateInputExpression(arguments[1])

        index = fb.evaluateIntegerExpression('[[' + subviews + ' subviews] indexOfObject:' + view + ']')
        # index = fb.evaluateIntegerExpression('[(id)' + subviews + '.subviews indexOfObject:' + view + ']')

        # index = fb.evaluateExpression('[(UIView *)%s.subviews indexOfObject:(UIView *)%s]' % (subviews, view))

        # pdb.set_trace()
        print ('index: %d' % index)
Exemple #2
0
  def run(self, arguments, options):
    objectToPrint = fb.evaluateInputExpression(arguments[0])
    pretty = 1 if options.plain is None else 0
    jsonData = fb.evaluateObjectExpression('[NSJSONSerialization dataWithJSONObject:(id){} options:{} error:nil]'.format(objectToPrint, pretty))
    jsonString = fb.evaluateExpressionValue('(NSString*)[[NSString alloc] initWithData:(id){} encoding:4]'.format(jsonData)).GetObjectDescription()

    print jsonString
  def run(self, args, options):
    def setBorder(layer, width, color, colorClass):
      fb.evaluateEffect('[%s setBorderWidth:(CGFloat)%s]' % (layer, width))
      fb.evaluateEffect('[%s setBorderColor:(CGColorRef)[(id)[%s %sColor] CGColor]]' % (layer, colorClass, color))

    obj = fb.evaluateInputExpression(args[0])
    depth = int(options.depth)
    isMac = runtimeHelpers.isMacintoshArch()
    color = options.color
    assert color in self.colors, "Color must be one of the following: {}".format(" ".join(self.colors))
    colorClassName = 'UIColor'
    if isMac:
      colorClassName = 'NSColor'

    if viewHelpers.isView(obj):
      prevLevel = 0
      for view, level in viewHelpers.subviewsOfView(obj):
        if level > depth:
           break
        if prevLevel != level:
          color = self.nextColorAfterColor(color)
          prevLevel = level
        layer = viewHelpers.convertToLayer(view)
        setBorder(layer, options.width, color, colorClassName)
    else:
      # `obj` is not a view, make sure recursive bordering is not requested
      assert depth <= 0, "Recursive bordering is only supported for UIViews or NSViews"
      layer = viewHelpers.convertToLayer(obj)
      setBorder(layer, options.width, color, colorClassName)

    lldb.debugger.HandleCommand('caflush')
Exemple #4
0
def _visualize(target):
    target = fb.evaluateInputExpression(target)

    if fb.evaluateBooleanExpression('(unsigned long)CFGetTypeID((CFTypeRef)' +
                                    target +
                                    ') == (unsigned long)CGImageGetTypeID()'):
        _showImage('(id)[UIImage imageWithCGImage:' + target + ']')
    else:
        if objectHelpers.isKindOfClass(target, 'UIImage'):
            _showImage(target)
        elif objectHelpers.isKindOfClass(target, 'UIView'):
            _showLayer('[(id)' + target + ' layer]')
        elif objectHelpers.isKindOfClass(target, 'CALayer'):
            _showLayer(target)
        elif objectHelpers.isKindOfClass(
                target, 'UIColor') or objectHelpers.isKindOfClass(
                    target, 'CIColor') or _colorIsCGColorRef(target):
            _showColor(target)
        elif objectHelpers.isKindOfClass(target, 'NSData'):
            if _dataIsImage(target):
                _showImage('(id)[UIImage imageWithData:' + target + ']')
            elif _dataIsString(target):
                print(
                    fb.describeObject('[[NSString alloc] initWithData:' +
                                      target + ' encoding:4]'))
            else:
                print('Data isn\'t an image and isn\'t a string.')
        else:
            print(
                '{} isn\'t supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, or CGColorRef.'
                .format(objectHelpers.className(target)))
Exemple #5
0
 def run(self, arguments, options):
     view = fb.evaluateInputExpression(arguments[0])
     opt = fb.evaluateBooleanExpression(
         '[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]'
     )
     traceCall = '_autolayoutTraceRecursively:1' if opt else '_autolayoutTrace'
     print(fb.describeObject('[{} {}]'.format(view, traceCall)))
Exemple #6
0
 def run(self, arguments, options):
     view = fb.evaluateInputExpression(arguments[0])
     opt = fb.evaluateBooleanExpression(
         "[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]"  # noqa B950
     )
     traceCall = "_autolayoutTraceRecursively:1" if opt else "_autolayoutTrace"
     print(fb.describeObject("[{} {}]".format(view, traceCall)))
Exemple #7
0
    def run(self, args, options):
        def setBorder(layer, width, color, colorClass):
            fb.evaluateEffect('[%s setBorderWidth:(CGFloat)%s]' %
                              (layer, width))
            fb.evaluateEffect(
                '[%s setBorderColor:(CGColorRef)[(id)[%s %sColor] CGColor]]' %
                (layer, colorClass, color))

        obj = fb.evaluateInputExpression(args[0])
        depth = int(options.depth)
        isMac = runtimeHelpers.isMacintoshArch()
        color = options.color
        assert color in self.colors, "Color must be one of the following: {}".format(
            " ".join(self.colors))
        colorClassName = 'UIColor'
        if isMac:
            colorClassName = 'NSColor'

        if viewHelpers.isView(obj):
            prevLevel = 0
            for view, level in viewHelpers.subviewsOfView(obj):
                if level > depth:
                    break
                if prevLevel != level:
                    color = self.nextColorAfterColor(color)
                    prevLevel = level
                layer = viewHelpers.convertToLayer(view)
                setBorder(layer, options.width, color, colorClassName)
        else:
            # `obj` is not a view, make sure recursive bordering is not requested
            assert depth <= 0, "Recursive bordering is only supported for UIViews or NSViews"
            layer = viewHelpers.convertToLayer(obj)
            setBorder(layer, options.width, color, colorClassName)

        lldb.debugger.HandleCommand('caflush')
Exemple #8
0
def _visualize(target):
    target = fb.evaluateInputExpression(target)

    if fb.evaluateBooleanExpression("(unsigned long)CFGetTypeID((CFTypeRef)" +
                                    target +
                                    ") == (unsigned long)CGImageGetTypeID()"):
        _showImage("(id)[UIImage imageWithCGImage:" + target + "]")
    else:
        if objectHelpers.isKindOfClass(target, "UIImage"):
            _showImage(target)
        elif objectHelpers.isKindOfClass(target, "UIView"):
            _showLayer("[(id)" + target + " layer]")
        elif objectHelpers.isKindOfClass(target, "CALayer"):
            _showLayer(target)
        elif (objectHelpers.isKindOfClass(target, "UIColor")
              or objectHelpers.isKindOfClass(target, "CIColor")
              or _colorIsCGColorRef(target)):
            _showColor(target)
        elif objectHelpers.isKindOfClass(target, "NSData"):
            if _dataIsImage(target):
                _showImage("(id)[UIImage imageWithData:" + target + "]")
            elif _dataIsString(target):
                print(
                    fb.describeObject("[[NSString alloc] initWithData:" +
                                      target + " encoding:4]"))
            else:
                print("Data isn't an image and isn't a string.")
        else:
            print(
                "{} isn't supported. You can visualize UIImage, CGImageRef, UIView, CALayer, NSData, UIColor, CIColor, or CGColorRef."
                .format(  # noqa B950
                    objectHelpers.className(target)))
Exemple #9
0
    def run(self, arguments, options):
        control = fb.evaluateInputExpression(arguments[0])
        targets = fb.evaluateObjectExpression(
            "[[{control} allTargets] allObjects]".format(control=control)
        )
        targetCount = fb.evaluateIntegerExpression(
            "[{targets} count]".format(targets=targets)
        )

        for index in range(0, targetCount):
            target = fb.evaluateObjectExpression(
                "[{targets} objectAtIndex:{index}]".format(targets=targets, index=index)
            )
            actions = fb.evaluateObjectExpression(
                "[{control} actionsForTarget:{target} forControlEvent:0]".format(
                    control=control, target=target
                )
            )

            targetDescription = fb.evaluateExpressionValue(
                "(id){target}".format(target=target)
            ).GetObjectDescription()
            actionsDescription = fb.evaluateExpressionValue(
                '(id)[{actions} componentsJoinedByString:@", "]'.format(actions=actions)
            ).GetObjectDescription()

            print(
                "{target}: {actions}".format(
                    target=targetDescription, actions=actionsDescription
                )
            )
Exemple #10
0
  def run(self, arguments, options):
    objectToPrint = fb.evaluateInputExpression(arguments[0])
    pretty = 1 if options.plain is None else 0
    jsonData = fb.evaluateObjectExpression('[NSJSONSerialization dataWithJSONObject:(id){} options:{} error:nil]'.format(objectToPrint, pretty))
    jsonString = fb.evaluateExpressionValue('(NSString*)[[NSString alloc] initWithData:(id){} encoding:4]'.format(jsonData)).GetObjectDescription()

    print jsonString
Exemple #11
0
    def run(self, arguments, options):
        print(
            '\nUse the following and (q) to quit.\n(w) move to superview\n(s) move to first subview\n(a) move to previous sibling\n(d) move to next sibling\n(p) print the hierarchy\n'
        )

        object = fb.evaluateInputExpression(arguments[0])
        walker = FlickerWalker(object)
        walker.run()
Exemple #12
0
  def run(self, arguments, options):
      #Convert to NSObject first to allow for objc runtime to process it
      objectToPrint = fb.evaluateInputExpression('{obj} as NSObject'.format(obj=arguments[0]))
      pretty = 1 if options.plain is None else 0
      jsonData = fb.evaluateObjectExpression('[NSJSONSerialization dataWithJSONObject:(NSObject*){} options:{} error:nil]'.format(objectToPrint, pretty))
      jsonString = fb.evaluateExpressionValue('(NSString*)[[NSString alloc] initWithData:(NSObject*){} encoding:4]'.format(jsonData)).GetObjectDescription()

      print jsonString
Exemple #13
0
  def run(self, arguments, options):
      #Convert to NSObject first to allow for objc runtime to process it
      objectToPrint = fb.evaluateInputExpression('{obj} as NSObject'.format(obj=arguments[0]))
      pretty = 1 if options.plain is None else 0
      jsonData = fb.evaluateObjectExpression('[NSJSONSerialization dataWithJSONObject:(NSObject*){} options:{} error:nil]'.format(objectToPrint, pretty))
      jsonString = fb.evaluateExpressionValue('(NSString*)[[NSString alloc] initWithData:(NSObject*){} encoding:4]'.format(jsonData)).GetObjectDescription()

      print jsonString
Exemple #14
0
    def run(self, arguments, options):
        upwards = 'YES' if options.upwards else 'NO'
        showViews = 'YES' if options.showViews == 'YES' else 'NO'

        view = fb.evaluateInputExpression(arguments[0])
        print fb.describeObject(
            '[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)'
            + view + ' searchUpwards:' + upwards + ' showViews:' + showViews +
            ']')
  def run(self, arguments, options):
    upwards = 'YES' if options.upwards else 'NO'
    showViews = 'YES' if options.showViews == 'YES' else 'NO'

    view = fb.evaluateInputExpression(arguments[0])
    if not viewHelpers.isView(view):
        # assume it's a CKComponent
        view = fb.evaluateExpression('((CKComponent *)%s).viewContext.view' % view)

    print fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']')
Exemple #16
0
  def run(self, arguments, options):
    upwards = 'YES' if options.upwards else 'NO'
    showViews = 'YES' if options.showViews == 'YES' else 'NO'

    view = fb.evaluateInputExpression(arguments[0])
    if not viewHelpers.isView(view):
        # assume it's a CKComponent
        view = fb.evaluateExpression('((CKComponent *)%s).viewContext.view' % view)

    print(fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']'))
Exemple #17
0
  def run(self, arguments, options):
    object = fb.evaluateInputExpression(arguments[0])
    ivarName = arguments[1]

    objectClass = fb.evaluateExpressionValue('(id)[(' + object + ') class]').GetObjectDescription()

    ivarTypeCommand = '((char *)ivar_getTypeEncoding((void*)object_getInstanceVariable((id){}, \"{}\", 0)))[0]'.format(object, ivarName)
    ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand)

    result = fb.evaluateExpressionValue('(({} *)({}))->{}'.format(objectClass, object, ivarName))
    print result.GetObjectDescription() if '@' in ivarTypeEncodingFirstChar else result
Exemple #18
0
  def run(self, arguments, options):
    object = fb.evaluateInputExpression(arguments[0])
    ivarName = arguments[1]

    objectClass = fb.evaluateExpressionValue('(id)[(' + object + ') class]').GetObjectDescription()

    ivarTypeCommand = '((char *)ivar_getTypeEncoding((void*)object_getInstanceVariable((id){}, \"{}\", 0)))[0]'.format(object, ivarName)
    ivarTypeEncodingFirstChar = fb.evaluateExpression(ivarTypeCommand)

    result = fb.evaluateExpressionValue('(({} *)({}))->{}'.format(printCommand, objectClass, object, ivarName))
    return result.GetObjectDescription() if '@' in ivarTypeEncodingFirstChar else result.GetValue()
Exemple #19
0
  def run(self, arguments, options):
    control = fb.evaluateInputExpression(arguments[0])
    targets = fb.evaluateObjectExpression('[[{control} allTargets] allObjects]'.format(control=control))
    targetCount = fb.evaluateIntegerExpression('[{targets} count]'.format(targets=targets))

    for index in range(0, targetCount):
      target = fb.evaluateObjectExpression('[{targets} objectAtIndex:{index}]'.format(targets=targets, index=index))
      actions = fb.evaluateObjectExpression('[{control} actionsForTarget:{target} forControlEvent:0]'.format(control=control, target=target))

      targetDescription = fb.evaluateExpressionValue('(id){target}'.format(target=target)).GetObjectDescription()
      actionsDescription = fb.evaluateExpressionValue('(id)[{actions} componentsJoinedByString:@", "]'.format(actions=actions)).GetObjectDescription()

      print '{target}: {actions}'.format(target=targetDescription, actions=actionsDescription)
Exemple #20
0
  def run(self, arguments, options):
    startResponder = fb.evaluateInputExpression(arguments[0])

    isMac = runtimeHelpers.isMacintoshArch()
    responderClass = 'UIResponder'
    if isMac:
      responderClass = 'NSResponder'

    if not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[' + responderClass + ' class]]'):
      print 'Whoa, ' + startResponder + ' is not a ' + responderClass + '. =('
      return

    _printIterative(startResponder, _responderChain)
Exemple #21
0
  def run(self, arguments, options):
    startResponder = fb.evaluateInputExpression(arguments[0])

    isMac = runtimeHelpers.isMacintoshArch()
    responderClass = 'UIResponder'
    if isMac:
      responderClass = 'NSResponder'

    if not fb.evaluateBooleanExpression('(BOOL)[(id)' + startResponder + ' isKindOfClass:[' + responderClass + ' class]]'):
      print 'Whoa, ' + startResponder + ' is not a ' + responderClass + '. =('
      return

    _printIterative(startResponder, _responderChain)
Exemple #22
0
  def run(self, arguments, options):
    request = fb.evaluateInputExpression(arguments[0])
    HTTPHeaderSring = ''
    HTTPMethod = fb.evaluateExpressionValue('(id)[{} HTTPMethod]'.format(request)).GetObjectDescription()
    URL = fb.evaluateExpressionValue('(id)[{} URL]'.format(request)).GetObjectDescription()
    timeout = fb.evaluateExpression('(NSTimeInterval)[{} timeoutInterval]'.format(request))
    HTTPHeaders = fb.evaluateObjectExpression('(id)[{} allHTTPHeaderFields]'.format(request))
    HTTPHeadersCount = fb.evaluateIntegerExpression('[{} count]'.format(HTTPHeaders))
    allHTTPKeys = fb.evaluateObjectExpression('[{} allKeys]'.format(HTTPHeaders))
    for index in range(0, HTTPHeadersCount):
        key = fb.evaluateObjectExpression('[{} objectAtIndex:{}]'.format(allHTTPKeys, index))
        keyDescription = fb.evaluateExpressionValue('(id){}'.format(key)).GetObjectDescription()
        value = fb.evaluateExpressionValue('(id)[(id){} objectForKey:{}]'.format(HTTPHeaders, key)).GetObjectDescription()
        if len(HTTPHeaderSring) > 0:
            HTTPHeaderSring += ' '
        HTTPHeaderSring += '-H "{}: {}"'.format(keyDescription, value)
    HTTPData = fb.evaluateObjectExpression('[{} HTTPBody]'.format(request))
    dataFile = None
    dataAsString = None
    if fb.evaluateIntegerExpression('[{} length]'.format(HTTPData)) > 0:
        if options.embed:
          if fb.evaluateIntegerExpression('[{} respondsToSelector:@selector(base64EncodedStringWithOptions:)]'.format(HTTPData)):
            dataAsString = fb.evaluateExpressionValue('(id)[(id){} base64EncodedStringWithOptions:0]'.format(HTTPData)).GetObjectDescription()
          else :
            print 'This version of OS doesn\'t supports base64 data encoding'
            return False
        elif not runtimeHelpers.isIOSDevice():
          dataFile = self.generateTmpFilePath()
          if not fb.evaluateBooleanExpression('(BOOL)[{} writeToFile:@"{}" atomically:NO]'.format(HTTPData, dataFile)):
            print 'Can\'t write data to file {}'.format(dataFile)
            return False
        else:
          print 'HTTPBody data for iOS Device is supported only with "--embed-data" flag'
          return False

    commandString = ''
    if dataAsString is not None and len(dataAsString) > 0:
      dataFile = self.generateTmpFilePath()
      commandString += 'echo "{}" | base64 -D -o "{}" && '.format(dataAsString, dataFile)
    commandString += 'curl -X {} --connect-timeout {}'.format(HTTPMethod, timeout)
    if len(HTTPHeaderSring) > 0:
        commandString += ' ' + HTTPHeaderSring
    if dataFile is not None:
        commandString += ' --data-binary @"{}"'.format(dataFile)

    commandString += ' "{}"'.format(URL)
    print commandString
Exemple #23
0
  def run(self, arguments, options):
    request = fb.evaluateInputExpression(arguments[0])
    HTTPHeaderSring = ''
    HTTPMethod = fb.evaluateExpressionValue('(id)[{} HTTPMethod]'.format(request)).GetObjectDescription()
    URL = fb.evaluateExpressionValue('(id)[{} URL]'.format(request)).GetObjectDescription()
    timeout = fb.evaluateExpression('(NSTimeInterval)[{} timeoutInterval]'.format(request))
    HTTPHeaders = fb.evaluateObjectExpression('(id)[{} allHTTPHeaderFields]'.format(request))
    HTTPHeadersCount = fb.evaluateIntegerExpression('[{} count]'.format(HTTPHeaders))
    allHTTPKeys = fb.evaluateObjectExpression('[{} allKeys]'.format(HTTPHeaders))
    for index in range(0, HTTPHeadersCount):
        key = fb.evaluateObjectExpression('[{} objectAtIndex:{}]'.format(allHTTPKeys, index))
        keyDescription = fb.evaluateExpressionValue('(id){}'.format(key)).GetObjectDescription()
        value = fb.evaluateExpressionValue('(id)[(id){} objectForKey:{}]'.format(HTTPHeaders, key)).GetObjectDescription()
        if len(HTTPHeaderSring) > 0:
            HTTPHeaderSring += ' '
        HTTPHeaderSring += '-H "{}: {}"'.format(keyDescription, value)
    HTTPData = fb.evaluateObjectExpression('[{} HTTPBody]'.format(request))
    dataFile = None
    dataAsString = None
    if fb.evaluateIntegerExpression('[{} length]'.format(HTTPData)) > 0:
        if options.embed:
          if fb.evaluateIntegerExpression('[{} respondsToSelector:@selector(base64EncodedStringWithOptions:)]'.format(HTTPData)):
            dataAsString = fb.evaluateExpressionValue('(id)[(id){} base64EncodedStringWithOptions:0]'.format(HTTPData)).GetObjectDescription()
          else :
            print 'This version of OS doesn\'t supports base64 data encoding'
            return False
        elif not runtimeHelpers.isIOSDevice():
          dataFile = self.generateTmpFilePath()
          if not fb.evaluateBooleanExpression('(BOOL)[{} writeToFile:@"{}" atomically:NO]'.format(HTTPData, dataFile)):
            print 'Can\'t write data to file {}'.format(dataFile)
            return False
        else:
          print 'HTTPBody data for iOS Device is supported only with "--embed-data" flag'
          return False

    commandString = ''
    if dataAsString is not None and len(dataAsString) > 0:
      dataFile = self.generateTmpFilePath()
      commandString += 'echo "{}" | base64 -D -o "{}" && '.format(dataAsString, dataFile)
    commandString += 'curl -X {} --connect-timeout {}'.format(HTTPMethod, timeout)
    if len(HTTPHeaderSring) > 0:
        commandString += ' ' + HTTPHeaderSring
    if dataFile is not None:
        commandString += ' --data-binary @"{}"'.format(dataFile)

    commandString += ' "{}"'.format(URL)
    print commandString
Exemple #24
0
    def run(self, arguments, options):
        startResponder = fb.evaluateInputExpression(arguments[0])

        isMac = runtimeHelpers.isMacintoshArch()
        responderClass = "UIResponder"
        if isMac:
            responderClass = "NSResponder"

        if not fb.evaluateBooleanExpression(
            "(BOOL)[(id)"
            + startResponder
            + " isKindOfClass:["
            + responderClass
            + " class]]"
        ):
            print("Whoa, " + startResponder + " is not a " + responderClass + ". =(")
            return

        _printIterative(startResponder, _responderChain)
Exemple #25
0
    def run(self, arguments, options):
        upwards = "YES" if options.upwards else "NO"
        showViews = "YES" if options.showViews == "YES" else "NO"

        view = fb.evaluateInputExpression(arguments[0])
        if not viewHelpers.isView(view):
            # assume it's a CKComponent
            view = fb.evaluateExpression("((CKComponent *)%s).viewContext.view" % view)

        print(
            fb.describeObject(
                "[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)"  # noqa B950
                + view
                + " searchUpwards:"
                + upwards
                + " showViews:"
                + showViews
                + "]"
            )
        )
 def run(self, arguments, options):
   view = fb.evaluateInputExpression(arguments[0])
   opt = fb.evaluateBooleanExpression('[UIView instancesRespondToSelector:@selector(_autolayoutTraceRecursively:)]')
   traceCall = '_autolayoutTraceRecursively:1' if opt else '_autolayoutTrace'
   print fb.describeObject('[{} {}]'.format(view, traceCall))
Exemple #27
0
 def run(self, arguments, options):
     view = fb.evaluateInputExpression(arguments[0])
     print fb.describeObject('[{} _autolayoutTrace]'.format(view))
Exemple #28
0
  def run(self, arguments, options):
    print '\nUse the following and (q) to quit.\n(w) move to superview\n(s) move to first subview\n(a) move to previous sibling\n(d) move to next sibling\n(p) print the hierarchy\n'

    object = fb.evaluateInputExpression(arguments[0])
    walker = FlickerWalker(object)
    walker.run()
  def run(self, arguments, options):
    upwards = 'YES' if options.upwards else 'NO'
    showViews = 'YES' if options.showViews == 'YES' else 'NO'

    view = fb.evaluateInputExpression(arguments[0])
    print fb.describeObject('[CKComponentHierarchyDebugHelper componentHierarchyDescriptionForView:(UIView *)' + view + ' searchUpwards:' + upwards + ' showViews:' + showViews + ']')
 def run(self, arguments, options):
   view = fb.evaluateInputExpression(arguments[0])
   print fb.describeObject('[{} _autolayoutTrace]'.format(view))