Module: Opal::BuilderScheduler::Prefork::OrderCorrector

Defined in:
opal/lib/opal/builder_scheduler/prefork.rb

Overview

Prefork is not deterministic. This module corrects an order of processed files so that it would be exactly the same as if building sequentially. While for Ruby files it usually isn't a problem, because the real order stems from how Opal.modules array is accessed, the JavaScript files are executed verbatim and their order may be important. Also, having deterministic output is always a good thing.

Class Method Summary collapse

Class Method Details

.build_require_order_array(requires, requires_hash, built_for = Set.new) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
# File 'opal/lib/opal/builder_scheduler/prefork.rb', line 61

def build_require_order_array(requires, requires_hash, built_for = Set.new)
  array = []
  requires.each do |name|
    next if built_for.include?(name)
    built_for << name

    asset_requires = requires_hash[name]
    array += build_require_order_array(asset_requires, requires_hash, built_for) if asset_requires
    array << name
  end
  array
end

.correct_order(processed, requires, builder) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'opal/lib/opal/builder_scheduler/prefork.rb', line 36

def correct_order(processed, requires, builder)
  # Let's build a hash that maps a filename to an array of files it requires
  requires_hash = processed.to_h do |i|
    [i.filename, expand_requires(i.requires, builder)]
  end
  # Let's build an array with a correct order of requires
  order_array = build_require_order_array(expand_requires(requires, builder), requires_hash)
  # If a key is duplicated, remove the last duplicate
  order_array = order_array.uniq
  # Create a hash from this array: [a,b,c] => [a => 0, b => 1, c => 2]
  order_hash = order_array.each_with_index.to_h
  # Let's return a processed array that has elements in the order provided
  processed.sort_by do |asset|
    # If a filename isn't present somehow in our hash, let's put it at the end
    order_hash[asset.filename] || order_array.length
  end
end

.expand_requires(requires, builder) ⇒ Object

Expand a requires array, so that the requires filenames will be matching BuilderProcessor#. Builder needs to be passed so that we can access an expand_ext function from its context.



57
58
59
# File 'opal/lib/opal/builder_scheduler/prefork.rb', line 57

def expand_requires(requires, builder)
  requires.map { |i| builder.expand_ext(i) }
end