Class: Opal::Optimizer::Step::TreeShaking

Inherits:
Opal::Optimizer::Step show all
Defined in:
lib/opal/optimizer/step/tree_shaking.rb

Instance Method Summary collapse

Methods inherited from Opal::Optimizer::Step

#initialize

Methods included from Helpers

#parse_js

Constructor Details

This class inherits a constructor from Opal::Optimizer::Step

Instance Method Details

#runObject



101
102
103
104
105
106
107
108
# File 'lib/opal/optimizer/step/tree_shaking.rb', line 101

def run
  loop do
    removed = shake_methods
    # $stdout.puts removed.inspect
    reload
    break if removed.length == 0
  end
end

#shake_methodsObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/opal/optimizer/step/tree_shaking.rb', line 6

def shake_methods
  aliases = corelib_calls["alias"].map do |i|
    old = i.arguments.value[2]
    [i, "$"+old.value[1..-2]] if StringNode === old
  end.compact.to_h

  method_defs = corelib_calls["def"] +
                corelib_calls["defs"] +
                corelib_calls["defn"] +
                corelib_calls["udef"] +
                aliases.keys

  method_calls = Set.new(['$method_missing'])

  method_calls += ( function_calls + exports.function_calls ).map do |i|
    out = if i.value_path?(DotAccessorNode) && i.value.accessor.start_with?("$")
      i.value.accessor
    elsif i.value_path?(BracketAccessorNode) &&
          StringNode === i.value.accessor &&
          i.value.accessor.value[1] == '$'
      i.value.accessor.value[1..-2]
    elsif i.value_path?(ResolveNode, ->(i) { %w[$send $send2 $refined_send].include? i })
      if i.value.value == '$send'
        old = i.arguments.value[1]
      else
        old = i.arguments.value[2]
      end
      "$" + old.value[1..-2] if StringNode === old
    end

    out = [out]

    case out.first
    when /\A\$(public_|private_|protected_)?(class_|instance_|singleton_)?(send|method(_defined\?)?)\z/,
         '$__send__'

      old = i.arguments.value[0]
      out << "$" + old.value[1..-2] if StringNode === old
    end

    out
  end.flatten.compact

  method_calls += aliases.values

  # Protected methods
  method_calls += []

  removed = Set.new

  method_defs.each do |m|
    name = m.arguments.value[1]
    case name
    when AddNode
      if StringNode === name.left && StringNode === name.value
        name = name.left.value[1..-2] + name.value.value[1..-2]
      else
        next
      end
    when StringNode
      name = name.value[1..-2]
      case m.value
      when ResolveNode
        name = "$" + name if m.value.value == "$alias"
      when DotAccessorNode
        name = "$" + name if m.value.accessor == "alias"
      end
    else
      next
    end

    next if method_calls.include? name

    removed << name
    m.destroy! "TreeShaking#shake_methods/#{name}"
  end

  corelib_calls["add_stubs"].each do |stubcall|
    if opal_version >= 1.4
      stubs = stubcall.arguments.value.first.value
      new_stubs = stubs[1..-2].split(",").reject do |i|
        removed.include? i[1..-1]
      end.join(',')
      new_stubs = "'#{new_stubs}'"
      stubs.replace(new_stubs)
    else
      stubcall.arguments.value.first.value.reject! do |i|
        removed.include? i.value.value[1..-2]
      end
    end
  end

  removed
end