class RubyRunJs::OPCODES::TRY_CATCH_FINALLY

Public Class Methods

new(label_try, label_catch, catch_var_name, label_finally, has_finally, label_end) click to toggle source
# File lib/ruby_run_js/opcodes.rb, line 750
def initialize(label_try, label_catch, catch_var_name, label_finally,
            has_finally, label_end)
  @label_try = label_try
  @label_catch = label_catch
  @catch_var_name = catch_var_name
  @label_finally = label_finally
  @has_finally = has_finally
  @label_end = label_end
end

Public Instance Methods

eval(ctx) click to toggle source

@return [status, value] status = 0 : normal status = 1 : return status = 2 : jump out status = 3 : error

# File lib/ruby_run_js/opcodes.rb, line 765
def eval(ctx)
  
  ctx.stack.pop()

  # execute try statement
  try_status = ctx.builtin.executor.run_under_control(
      ctx, @label_try, @label_catch)

  errors = try_status[0] == 3

  # catch
  if errors and @catch_var_name != nil
    # generate catch block context...
    catch_scope = LocalScope.new(ctx, ctx.builtin)
    js_error = try_status[1].throw_value.nil? ? ctx.builtin.new_error(try_status[1].type, try_status[1].msg) : try_status[1].throw_value
    catch_scope.own[@catch_var_name] = js_error
    catch_scope.this_binding = ctx.this_binding
    catch_status = ctx.builtin.executor.run_under_control(
      catch_scope, @label_catch, @label_finally)
  else
    catch_status = nil
  end

  # finally
  if @has_finally
    finally_status = ctx.builtin.executor.run_under_control(
        ctx, @label_finally, @label_end)
  else
    finally_status = nil
  end

  # now return controls
  other_status = catch_status || try_status
  if finally_status == nil || (finally_status[0] == 0 \
                                && other_status[0] != 0)
    winning_status = other_status
  else
    winning_status = finally_status
  end

  type, return_value, label = winning_status
  if type == 0  # normal
    ctx.stack.append(return_value)
    return @label_end
  elsif type == 1  # return
    ctx.stack.append(return_value)
    return :Return  # send return signal
  elsif type == 2  # jump outside
    ctx.stack.append(return_value)
    return label
  elsif type == 3
      # throw is made with empty stack as usual
    raise return_value
  else
    raise "Unexpected Type: #{type}"
  end
end