# module Byebug::Helpers::EvalHelper

Utilities to assist evaluation of code strings

### Public Instance Methods

error_eval(str, binding = frame._binding) click to toggle source

Evaluates a string containing Ruby code in a specific binding, handling the errors at an error level.

    # File lib/byebug/helpers/eval.rb, line 46
    def error_eval(str, binding = frame._binding)
      safe_eval(str, binding) { |e| raise(e, msg(e)) }
    end

multiple_thread_eval(expression) click to toggle source

Evaluates an `expression` that might use or defer execution to threads other than the current one.

@note This is necessary because when in byebug's prompt, every thread is “frozen” so that nothing gets run. So we need to unlock threads prior to evaluation or we will run into a deadlock.

@param expression [String] Expression to evaluate

    # File lib/byebug/helpers/eval.rb, line 30
    def multiple_thread_eval(expression)
      allowing_other_threads { warning_eval(expression) }
    end

separate_thread_eval(expression) click to toggle source

Evaluates an `expression` in a separate thread.

@param expression [String] Expression to evaluate

    # File lib/byebug/helpers/eval.rb, line 14
    def separate_thread_eval(expression)
      allowing_other_threads do
        in_new_thread { warning_eval(expression) }
      end
    end

silent_eval(str, binding = frame._binding) click to toggle source

Evaluates a string containing Ruby code in a specific binding, returning nil in an error happens.

    # File lib/byebug/helpers/eval.rb, line 38
    def silent_eval(str, binding = frame._binding)
      safe_eval(str, binding) { |_e| nil }
    end

warning_eval(str, binding = frame._binding) click to toggle source

Evaluates a string containing Ruby code in a specific binding, handling the errors at a warning level.

    # File lib/byebug/helpers/eval.rb, line 54
    def warning_eval(str, binding = frame._binding)
      safe_eval(str, binding) { |e| errmsg(msg(e)) }
    end

### Private Instance Methods

allowing_other_threads() { || ... } click to toggle source

Run block temporarily ignoring all TracePoint events.

Used to evaluate stuff within Byebug's prompt. Otherwise, any code creating new threads won't be properly evaluated because new threads will get blocked by byebug's main thread.

    # File lib/byebug/helpers/eval.rb, line 91
    def allowing_other_threads
      Byebug.unlock

      res = yield

      Byebug.lock

      res
    end

error_msg(exception) click to toggle source

    # File lib/byebug/helpers/eval.rb, line 72
    def error_msg(exception)
      at = exception.backtrace

      locations = ["#{at.shift}: #{warning_msg(exception)}"]
      locations += at.map { |path| "  from #{path}" }
      locations.join("\n")
    end

in_new_thread() { || ... } click to toggle source

Runs the given block in a new thread, waits for it to finish and returns the new thread's result.

    # File lib/byebug/helpers/eval.rb, line 105
    def in_new_thread
      res = nil

      Thread.new { res = yield }.join

      res
    end

msg(exception) click to toggle source

    # File lib/byebug/helpers/eval.rb, line 66
    def msg(exception)
      msg = Setting[:stack_on_error] ? error_msg(exception) : warning_msg(exception)

      pr("eval.exception", text_message: msg)
    end

safe_eval(str, binding) { |e| ... } click to toggle source

    # File lib/byebug/helpers/eval.rb, line 60
    def safe_eval(str, binding)
      binding.eval(str.gsub(/\Aeval /, ""), "(byebug)", 1)
    rescue StandardError, ScriptError => e
      yield(e)
    end

safe_inspect(var) click to toggle source

    # File lib/byebug/helpers/eval.rb, line 113
    def safe_inspect(var)
      var.inspect
    rescue StandardError
      safe_to_s(var)
    end

safe_to_s(var) click to toggle source

    # File lib/byebug/helpers/eval.rb, line 119
    def safe_to_s(var)
      var.to_s
    rescue StandardError
      "*Error in evaluation*"
    end

warning_msg(exception) click to toggle source

    # File lib/byebug/helpers/eval.rb, line 80
    def warning_msg(exception)
      "#{exception.class} Exception: #{exception.message}"
    end