lib/execjs/external_runtime.rb in execjs-2.3.0 vs lib/execjs/external_runtime.rb in execjs-2.4.0
- old
+ new
@@ -22,16 +22,16 @@
end
end
def exec(source, options = {})
source = encode(source)
- source = "#{@source}\n#{source}" if @source
+ source = "#{@source}\n#{source}" if @source != ""
source = @runtime.compile_source(source)
tmpfile = write_to_tempfile(source)
begin
- extract_result(@runtime.exec_runtime(tmpfile.path))
+ extract_result(@runtime.exec_runtime(tmpfile.path), tmpfile.path)
ensure
File.unlink(tmpfile)
end
end
@@ -55,18 +55,29 @@
tmpfile.write(contents)
tmpfile.close
tmpfile
end
- def extract_result(output)
- status, value = output.empty? ? [] : ::JSON.parse(output, create_additions: false)
+ def extract_result(output, filename)
+ status, value, stack = output.empty? ? [] : ::JSON.parse(output, create_additions: false)
if status == "ok"
value
- elsif value =~ /SyntaxError:/
- raise RuntimeError, value
else
- raise ProgramError, value
+ 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@[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
end
attr_reader :name
@@ -156,11 +167,11 @@
end
if $?.success?
output
else
- raise RuntimeError, output
+ raise exec_runtime_error(output)
end
end
def shell_escape(*args)
# see http://technet.microsoft.com/en-us/library/cc723564.aspx#XSLTsection123121120120
@@ -179,11 +190,11 @@
io.close
if $?.success?
output
else
- raise RuntimeError, output
+ raise exec_runtime_error(output)
end
end
else
def exec_runtime(filename)
io = IO.popen(binary.split(' ') << filename, @popen_options.merge({err: [:child, :out]}))
@@ -191,15 +202,24 @@
io.close
if $?.success?
output
else
- raise RuntimeError, output
+ raise exec_runtime_error(output)
end
end
end
# Internally exposed for Context.
public :exec_runtime
+
+ def exec_runtime_error(output)
+ error = RuntimeError.new(output)
+ lines = output.split("\n")
+ lineno = lines[0][/:(\d+)$/, 1] if lines[0]
+ lineno ||= 1
+ error.set_backtrace(["(execjs):#{lineno}"] + caller)
+ error
+ end
def which(command)
Array(command).find do |name|
name, args = name.split(/\s+/, 2)
path = locate_executable(name)