class Opal::CliRunners::Compiler

The compiler runner will just output the compiled JavaScript

Public Class Methods

call(data) click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 7
def self.call(data)
  new(data).start
end
new(data) click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 11
def initialize(data)
  @options         = data[:options] || {}
  @builder_factory = data.fetch(:builder)
  @map_file        = @options[:map_file]
  @output          = data.fetch(:output)
  @watch           = @options[:watch]
end

Public Instance Methods

compile() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 19
def compile
  builder = @builder_factory.call
  compiled_source = builder.to_s
  compiled_source += "\n" + builder.source_map.to_data_uri_comment unless @options[:no_source_map]

  rewind_output if @watch

  @output.puts compiled_source
  @output.flush

  File.write(@map_file, builder.source_map.to_json) if @map_file

  builder
end
compile_noraise() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 34
def compile_noraise
  compile
rescue StandardError, Opal::SyntaxError => e
  $stderr.puts "* Compilation failed: #{e.message}"
  nil
end
fail_no_listen!() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 61
  def fail_no_listen!
    abort <<~ERROR
      --watch mode requires the `listen` gem present. Please try to run:

          gem install listen

      Or if you are using bundler, add listen to your Gemfile.
    ERROR
  end
fail_unrewindable!() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 54
  def fail_unrewindable!
    abort <<~ERROR
      You have specified --watch, but for watch to work, you must specify an
      --output file.
    ERROR
  end
files_to_directories() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 118
def files_to_directories
  directories = @files.map { |file| File.dirname(file) }.uniq

  previous_dir = nil
  # Only get the topmost directories
  directories = directories.sort.map do |dir|
    if previous_dir && dir.start_with?(previous_dir + '/')
      nil
    else
      previous_dir = dir
    end
  end

  directories.compact
end
on_code_change(modified) click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 98
def on_code_change(modified)
  if !(modified & @opal_deps).empty?
    $stderr.puts "* Modified core Opal files: #{modified.join(', ')}; reexecuting"
    reexec
  elsif !modified.all? { |file| @directories.any? { |dir| file.start_with?(dir + '/') } }
    $stderr.puts "* New unwatched files: #{modified.join(', ')}; reexecuting"
    reexec
  end

  $stderr.puts "* Modified code: #{modified.join(', ')}; rebuilding"

  builder = compile_noraise

  # Ignore the bad compilation
  if builder
    code_deps = builder.dependent_files
    @files = @opal_deps + code_deps
  end
end
reexec() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 94
def reexec
  Process.kill('USR2', Process.pid)
end
rewind_output() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 41
def rewind_output
  if !@output.is_a?(File) || @output.tty?
    fail_unrewindable!
  else
    begin
      @output.rewind
      @output.truncate(0)
    rescue Errno::ESPIPE
      fail_unrewindable!
    end
  end
end
start() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 143
def start
  if @watch
    watch_compile
  else
    compile
  end

  0
end
watch_compile() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 71
def watch_compile
  begin
    require 'listen'
  rescue LoadError
    fail_no_listen!
  end

  @opal_deps = Opal.dependent_files

  builder = compile
  code_deps = builder.dependent_files
  @files = @opal_deps + code_deps
  @code_listener = watch_files
  @code_listener.start

  $stderr.puts "* Opal v#{Opal::VERSION} successfully compiled your program in --watch mode"

  sleep
rescue Interrupt
  $stderr.puts '* Stopping watcher...'
  @code_listener.stop
end
watch_files() click to toggle source
# File lib/opal/cli_runners/compiler.rb, line 134
def watch_files
  @directories = files_to_directories

  Listen.to(*@directories, ignore!: []) do |modified, added, removed|
    our_modified = @files & (modified + added + removed)
    on_code_change(our_modified) unless our_modified.empty?
  end
end