• Jump To … +
    frontend.coffee node.coffee untar.coffee util.coffee ClassData.coffee ClassLoader.coffee ConstantPool.coffee attributes.coffee disassembler.coffee exceptions.coffee java_object.coffee jvm.coffee logging.coffee methods.coffee natives.coffee opcodes.coffee runtime.coffee testing.coffee util.coffee
  • exceptions.coffee

  • ¶
  • ¶

    pull in external modules

    _ = require '../vendor/_.js'
    {error,debug} = require './logging'
    
    "use strict"
  • ¶

    things assigned to root will be available outside this module

    root = exports ? window.exceptions ?= {}
    
    class root.HaltException
      constructor: (@exit_code) ->
      toplevel_catch_handler: () ->
        error "\nExited with code #{@exit_code}" unless @exit_code is 0
    
    root.ReturnException = 'RETURNEXCEPTION'
    
    class root.YieldException
      constructor: (@condition) ->
    
    class root.YieldIOException extends root.YieldException
  • ¶

    empty class

    class root.JavaException
      constructor: (@exception) ->
    
      method_catch_handler: (rs, cf, top_of_stack) ->
        method = cf.method
        if not top_of_stack and method.has_bytecode
          cf.pc -= 3  # rewind the invoke opcode
          --cf.pc until cf.pc <= 0 or method.code.opcodes[cf.pc]?.name.match /^invoke/
  • ¶

    Switch the native frame's runner to its error handler, if it exists.

        if cf.native
          if cf.error?
            cf.runner = ()=>cf.error @
            return true
          return false
    
        exception_handlers = method.code?.exception_handlers
        ecls = @exception.cls
        handler = _.find exception_handlers, (eh) ->
  • ¶

    XXX: Kludge. If the class is not loaded, then it is not possible for this to be the correct exception handler

          eh.start_pc <= cf.pc < eh.end_pc and method.cls.loader.get_resolved_class(eh.catch_type, true)? and
            (eh.catch_type == "<any>" or ecls.is_castable method.cls.loader.get_resolved_class(eh.catch_type))
        if handler?
          debug "caught #{@exception.cls.get_type()} in #{method.full_signature()} as subclass of #{handler.catch_type}"
          cf.stack = [@exception]  # clear out anything on the stack; it was made during the try block
          cf.pc = handler.handler_pc
          return true
  • ¶

    abrupt method invocation completion

        debug "exception not caught, terminating #{method.full_signature()}"
        return false
    
      toplevel_catch_handler: (rs) ->
        debug "\nUncaught #{@exception.cls.get_type()}"
        msg = @exception.get_field rs, 'Ljava/lang/Throwable;detailMessage'
        debug "\t#{msg.jvm2js_str()}" if msg?
        rs.push2 rs.curr_thread, @exception
        thread_cls = rs.get_bs_class('Ljava/lang/Thread;')
        thread_cls.method_lookup(rs,
          { class: 'Ljava/lang/Thread;'
          sig: 'dispatchUncaughtException(Ljava/lang/Throwable;)V'} ).setup_stack(rs)