class ExecJS::ExternalRuntime::Context
def call(identifier, *args)
def call(identifier, *args) eval "#{identifier}.apply(this, #{::JSON.generate(args)})" end
def create_tempfile(basename)
def create_tempfile(basename) tmpfile = nil Dir::Tmpname.create(basename) do |tmpname| mode = File::WRONLY | File::CREAT | File::EXCL tmpfile = File.open(tmpname, mode, 0600) end tmpfile end
def eval(source, options = {})
def eval(source, options = {}) source = source.encode(Encoding::UTF_8) if /\S/ =~ source exec("return eval(#{::JSON.generate("(#{source})", quirks_mode: true)})") end end
def exec(source, options = {})
def exec(source, options = {}) source = source.encode(Encoding::UTF_8) source = "#{@source}\n#{source}" if @source != "" source = @runtime.compile_source(source) tmpfile = write_to_tempfile(source) if ExecJS.cygwin? filepath = `cygpath -m #{tmpfile.path}`.rstrip else filepath = tmpfile.path end begin extract_result(@runtime.exec_runtime(filepath), filepath) ensure File.unlink(tmpfile) end end
def extract_result(output, filename)
def extract_result(output, filename) status, value, stack = output.empty? ? [] : ::JSON.parse(output, create_additions: false) if status == "ok" value else stack ||= "" real_filename = File.realpath(filename) stack = stack.split("\n").map do |line| line.sub(" at ", "") .sub(real_filename, "(execjs)") .sub(filename, "(execjs)") .strip end stack.reject! { |line| ["eval code", "eval code@", "eval@[native code]"].include?(line) } stack.shift unless stack[0].to_s.include?("(execjs)") error_class = value =~ /SyntaxError:/ ? RuntimeError : ProgramError error = error_class.new(value) error.set_backtrace(stack + caller) raise error end end
def initialize(runtime, source = "", options = {})
def initialize(runtime, source = "", options = {}) source = source.encode(Encoding::UTF_8) @runtime = runtime @source = source # Test compile context source exec("") end
def write_to_tempfile(contents)
def write_to_tempfile(contents) tmpfile = create_tempfile(['execjs', 'js']) tmpfile.write(contents) tmpfile.close tmpfile end