Skip to content
This repository has been archived by the owner on Jun 10, 2018. It is now read-only.

Commit

Permalink
Merge pull request #150 from sstephenson/fast-compile
Browse files Browse the repository at this point in the history
Optimize: Generate compile substitution method
  • Loading branch information
josh committed Jun 5, 2014
2 parents 397d61c + 01510e0 commit de124aa
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 37 deletions.
71 changes: 36 additions & 35 deletions lib/execjs/external_runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ def eval(source, options = {})
def exec(source, options = {})
source = encode(source)
source = "#{@source}\n#{source}" if @source
source = @runtime.compile_source(source)

tmpfile = compile_to_tempfile(source)
tmpfile = write_to_tempfile(source)
begin
extract_result(@runtime.send(:exec_runtime, tmpfile.path))
extract_result(@runtime.exec_runtime(tmpfile.path))
ensure
File.unlink(tmpfile)
end
Expand All @@ -46,32 +47,11 @@ def create_tempfile(basename)
tmpfile
end

def compile_to_tempfile(source)
def write_to_tempfile(contents)
tmpfile = create_tempfile(['execjs', 'js'])
begin
tmpfile.write compile(source)
tmpfile.close
tmpfile
rescue => e
tmpfile.close unless tmpfile.closed?
File.unlink(tmpfile)
raise e
end
end

def compile(source)
@runtime.send(:runner_source).dup.tap do |output|
output.sub!('#{source}') do
source
end
output.sub!('#{encoded_source}') do
encoded_source = encode_unicode_codepoints(source)
::JSON.generate("(function(){ #{encoded_source} })()", quirks_mode: true)
end
output.sub!('#{json2_source}') do
IO.read(ExecJS.root + "/support/json2.js")
end
end
tmpfile.write(contents)
tmpfile.close
tmpfile
end

def extract_result(output)
Expand All @@ -84,12 +64,6 @@ def extract_result(output)
raise ProgramError, value
end
end

def encode_unicode_codepoints(str)
str.gsub(/[\u0080-\uffff]/) do |ch|
"\\u%04x" % ch.codepoints.to_a
end
end
end

attr_reader :name
Expand All @@ -101,6 +75,10 @@ def initialize(options)
@encoding = options[:encoding]
@deprecated = !!options[:deprecated]
@binary = nil

if @runner_path
instance_eval generate_compile_method(@runner_path)
end
end

def available?
Expand Down Expand Up @@ -134,8 +112,29 @@ def locate_executable(cmd)
end

protected
def runner_source
@runner_source ||= IO.read(@runner_path)
def generate_compile_method(path)
<<-RUBY
def compile_source(source)
<<-RUNNER
#{IO.read(path)}
RUNNER
end
RUBY
end

def json2_source
@json2_source ||= IO.read(ExecJS.root + "/support/json2.js")
end

def encode_source(source)
encoded_source = encode_unicode_codepoints(source)
::JSON.generate("(function(){ #{encoded_source} })()", quirks_mode: true)
end

def encode_unicode_codepoints(str)
str.gsub(/[\u0080-\uffff]/) do |ch|
"\\u%04x" % ch.codepoints.to_a
end
end

def exec_runtime(filename)
Expand All @@ -146,6 +145,8 @@ def exec_runtime(filename)
raise RuntimeError, output
end
end
# Internally exposed for Context.
public :exec_runtime

def which(command)
Array(command).find do |name|
Expand Down
2 changes: 1 addition & 1 deletion lib/execjs/support/jsc_runner.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(function(program, execJS) { execJS(program) })(function() {
return eval(#{encoded_source});
return eval(#{encode_source(source)});
}, function(program) {
var output;
try {
Expand Down
2 changes: 1 addition & 1 deletion lib/execjs/support/jscript_runner.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(function(program, execJS) { execJS(program) })(function() {
return eval(#{encoded_source});
return eval(#{encode_source(source)});
}, function(program) {
#{json2_source}
var output, print = function(string) {
Expand Down

0 comments on commit de124aa

Please sign in to comment.