<commit_before>require "execjs/runtime"
require "json"

module ExecJS
  class DuktapeRuntime < Runtime
    class Context < Runtime::Context
      def initialize(runtime, source = "")
        @ctx = Duktape::Context.new
        exec(source)
      end

      def exec(source, options = {})
        source = encode(source)

        js = <<-JS
          (function(program, execJS) { return execJS(program); })(function() { #{source}
          }, function(program) {
            try {
              return JSON.stringify(['ok', program()]);
            } catch (err) {
              return JSON.stringify(['err', '' + err]);
            }
          });
        JS

        if json = @ctx.eval_string(js, '(execjs)')
          status, value = ::JSON.parse(json, create_additions: false)
          if status == "ok"
            value
          elsif value =~ /SyntaxError:/
            raise RuntimeError, value
          else
            raise ProgramError, value
          end
        end
      rescue Duktape::SyntaxError => e
        raise RuntimeError, e.message
      end

      def eval(source, options = {})
        source = encode(source)
<commit_msg>Use native error handling<commit_after>require "execjs/runtime"
require "json"

module ExecJS
  class DuktapeRuntime < Runtime
    class Context < Runtime::Context
      def initialize(runtime, source = "")
        @ctx = Duktape::Context.new
        exec(source)
      end

      def exec(source, options = {})
        source = encode(source)

        js = <<-JS
          (function(program) { return JSON.stringify([program()]); })(function() { #{source} });
        JS

        if json = @ctx.eval_string(js, '(execjs)')
          ::JSON.parse(json, create_additions: false)[0]
        end
      rescue Duktape::SyntaxError => e
        raise RuntimeError, e.message
      rescue Duktape::Error => e
        raise ProgramError, e.message
      end

      def eval(source, options = {})
        source = encode(source)

{'fraction_non_alphanumeric': 0.12107396149949341, 'fraction_numerical': 0.0005065856129685917, 'mean_word_length': 2.001519756838906, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '217652', 'n_tokens_mistral': 547, 'n_tokens_neox': 549, 'n_words': 141}