<commit_before>
require 'therubyracer'
require 'oj'

module Shin
  class JsContext

    DEBUG = true

    def initialize
      @context = V8::Context.new
      @seed = 0

      @context.eval %Q{
        this.$kir = {
          modules: {},

          define: function (name, deps, factory) {
            return $kir.modules[name] = {
              deps: deps,
              factory: factory,
              exports: {}
            };
          }
        }
      }
    end

    def context
      @context
    end

    def eval(source)
      @context.eval(source)
    end

    def spec_loaded?(spec)
      @context.eval("$kir.modules[#{escape(spec.name)}] != null")
    end

    def fresh_seed
      @seed += 1
    end

    def load(spec_input, inline: false)
      spec = if inline
        parse_spec("anon_#{fresh_seed}")
      else
        parse_spec(spec_input)
      end

      debug "Loading #{spec.name}"

      if spec.text?
        text_content = File.read(resource_path(spec.name))
        @context.eval %Q{
          $kir.define(#{escape(spec.name)}, [], null).exports = #{escape(text_content)};
        }
        return
      end

      # use globals so we can use V8::Context.load
      # and retain stack trace information.
      # the alternative is to eval the code, but
      # it makes debugging a lot harder.
      
      @context.eval %Q{
        this.$define_called = false;
        this.define = function (a, b, c) {
          $define_called = true; 
          if (typeof a === 'function') {
            $kir.define(#{escape(spec.name)}, [], a);
          } else if (typeof a === 'string') {
            $kir.define(a, b, c);
          } else {
            $kir.define(#{escape(spec.name)}, a, b);
          }
        }
        this.define.amd = true;
      }

      if inline
        @context.eval spec_input
      else
        path = resource_path(spec.name + ".js")
        @context.load path
      end

      mod = @context.eval %Q{
        var name = #{escape(spec.name)};

        if (!$define_called) {
          $kir.define(name, [], null);
        }

        delete this.$define_called;
        delete this.define;
        $kir.modules[name];
      }

      if mod[:factory].nil?
        debug "#{spec.name} doesn't look AMD-ready."

        # we have no factory to run.
        return
      end

      js = []
      js << "var deps = ["

      uses_exports = false

      mod[:deps].each do |dep|
        dep_spec = parse_spec(dep)
        if dep_spec.exports?
          uses_exports = true
          js << "$kir.modules[#{escape(spec.name)}].exports, "
        else
          debug "#{spec.name} => #{dep_spec.name}"
          unless spec_loaded?(dep_spec)
            load(dep_spec.input)
          end
          js << "$kir.modules[#{escape(dep_spec.name)}].exports, "
        end
      end
      js << "];"

      js << "var result = $kir.modules[#{escape(spec.name)}].factory.apply(null, deps);"

      # not requesting 'exports' and just returning an object
      # is valid AMD apparently. It won't work with circular 
      # references but whatever.
      unless uses_exports
        js << "$kir.modules[#{escape(spec.name)}].exports = result;"
      end

      # actually call the factory!
      debug "Calling the factory of #{spec.name}"
      @context.eval js.join("\n")

    end

    def resource_path(name)
      File.expand_path("../js/#{name}", __FILE__)
    end

    def escape(input)
      Oj.dump(input)
    end

    def set(key, val)
      @context[key] = val
    end

    def context
      @context
    end

    private

    def parse_spec(spec_input)
      _, text, _, name = /^(text!)?(\.\/)?(.*)$/.match(spec_input).to_a
      Struct.
        new(:input, :name, :exports?, :text?).
        new(spec_input, name, name == 'exports', !!text)
    end

    def debug(*args)
      puts(*args) if DEBUG
    end

  end
end

<commit_msg>Debug--<commit_after>
require 'therubyracer'
require 'oj'

module Shin
  class JsContext

    DEBUG = false

    def initialize
      @context = V8::Context.new
      @seed = 0

      @context.eval %Q{
        this.$kir = {
          modules: {},

          define: function (name, deps, factory) {
            return $kir.modules[name] = {
              deps: deps,
              factory: factory,
              exports: {}
            };
          }
        }
      }
    end

    def context
      @context
    end

    def eval(source)
      @context.eval(source)
    end

    def spec_loaded?(spec)
      @context.eval("$kir.modules[#{escape(spec.name)}] != null")
    end

    def fresh_seed
      @seed += 1
    end

    def load(spec_input, inline: false)
      spec = if inline
        parse_spec("anon_#{fresh_seed}")
      else
        parse_spec(spec_input)
      end

      debug "Loading #{spec.name}"

      if spec.text?
        text_content = File.read(resource_path(spec.name))
        @context.eval %Q{
          $kir.define(#{escape(spec.name)}, [], null).exports = #{escape(text_content)};
        }
        return
      end

      # use globals so we can use V8::Context.load
      # and retain stack trace information.
      # the alternative is to eval the code, but
      # it makes debugging a lot harder.
      
      @context.eval %Q{
        this.$define_called = false;
        this.define = function (a, b, c) {
          $define_called = true; 
          if (typeof a === 'function') {
            $kir.define(#{escape(spec.name)}, [], a);
          } else if (typeof a === 'string') {
            $kir.define(a, b, c);
          } else {
            $kir.define(#{escape(spec.name)}, a, b);
          }
        }
        this.define.amd = true;
      }

      if inline
        @context.eval spec_input
      else
        path = resource_path(spec.name + ".js")
        @context.load path
      end

      mod = @context.eval %Q{
        var name = #{escape(spec.name)};

        if (!$define_called) {
          $kir.define(name, [], null);
        }

        delete this.$define_called;
        delete this.define;
        $kir.modules[name];
      }

      if mod[:factory].nil?
        debug "#{spec.name} doesn't look AMD-ready."

        # we have no factory to run.
        return
      end

      js = []
      js << "var deps = ["

      uses_exports = false

      mod[:deps].each do |dep|
        dep_spec = parse_spec(dep)
        if dep_spec.exports?
          uses_exports = true
          js << "$kir.modules[#{escape(spec.name)}].exports, "
        else
          debug "#{spec.name} => #{dep_spec.name}"
          unless spec_loaded?(dep_spec)
            load(dep_spec.input)
          end
          js << "$kir.modules[#{escape(dep_spec.name)}].exports, "
        end
      end
      js << "];"

      js << "var result = $kir.modules[#{escape(spec.name)}].factory.apply(null, deps);"

      # not requesting 'exports' and just returning an object
      # is valid AMD apparently. It won't work with circular 
      # references but whatever.
      unless uses_exports
        js << "$kir.modules[#{escape(spec.name)}].exports = result;"
      end

      # actually call the factory!
      debug "Calling the factory of #{spec.name}"
      @context.eval js.join("\n")

    end

    def resource_path(name)
      File.expand_path("../js/#{name}", __FILE__)
    end

    def escape(input)
      Oj.dump(input)
    end

    def set(key, val)
      @context[key] = val
    end

    def context
      @context
    end

    private

    def parse_spec(spec_input)
      _, text, _, name = /^(text!)?(\.\/)?(.*)$/.match(spec_input).to_a
      Struct.
        new(:input, :name, :exports?, :text?).
        new(spec_input, name, name == 'exports', !!text)
    end

    def debug(*args)
      puts(*args) if DEBUG
    end

  end
end


{'fraction_non_alphanumeric': 0.1345534218327104, 'fraction_numerical': 0.0010310607036989304, 'mean_word_length': 1.7218519817607858, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 5, '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': '3588148', 'n_tokens_mistral': 2440, 'n_tokens_neox': 2396, 'n_words': 586}