Module: Opal::Nodes::Helpers

Included in:
Base
Defined in:
opal/lib/opal/nodes/helpers.rb

Instance Method Summary collapse

Instance Method Details

#conditional_send(recvr) {|receiver_temp| ... } ⇒ Object

Usefule for safe-operator calls: foo&.bar / foo&.bar ||= baz / ...

Parameters:

  • recvr (sexp_pushable)

    The receiver of the call that will be stored in a temporary variable

Yields:

  • (receiver_temp)


126
127
128
129
130
131
132
133
134
135
# File 'opal/lib/opal/nodes/helpers.rb', line 126

def conditional_send(recvr)
  # temporary variable that stores method receiver
  receiver_temp = scope.new_temp
  push "#{receiver_temp} = ", recvr

  # execute the sexp only if the receiver isn't nil
  push ", (#{receiver_temp} === nil || #{receiver_temp} == null) ? nil : "
  yield receiver_temp
  wrap '(', ')'
end

#current_indentObject



33
34
35
# File 'opal/lib/opal/nodes/helpers.rb', line 33

def current_indent
  compiler.parser_indent
end

#empty_lineObject



42
43
44
# File 'opal/lib/opal/nodes/helpers.rb', line 42

def empty_line
  push fragment("\n", loc: false)
end

#indent(&block) ⇒ Object



29
30
31
# File 'opal/lib/opal/nodes/helpers.rb', line 29

def indent(&block)
  compiler.indent(&block)
end

#js_truthy(sexp) ⇒ Object



46
47
48
49
50
51
52
53
# File 'opal/lib/opal/nodes/helpers.rb', line 46

def js_truthy(sexp)
  if optimize = js_truthy_optimize(sexp)
    return optimize
  end

  helper :truthy
  [fragment('$truthy('), expr(sexp), fragment(')')]
end

#js_truthy_optimize(sexp) ⇒ Object



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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'opal/lib/opal/nodes/helpers.rb', line 55

def js_truthy_optimize(sexp)
  case sexp.type
  when :send
    receiver, mid, *args = *sexp
    receiver_handler_class = receiver && compiler.handlers[receiver.type]

    # Only operator calls on the truthy_optimize? node classes should be optimized.
    # Monkey patch method calls might return 'self'/aka a bridged instance and need
    # the nil check - see discussion at https://github.com/opal/opal/pull/1097
    allow_optimization_on_type = Compiler::COMPARE.include?(mid.to_s) &&
                                 receiver_handler_class &&
                                 receiver_handler_class.truthy_optimize?

    if allow_optimization_on_type ||
       mid == :block_given?
      expr(sexp)
    elsif args.count == 1
      case mid
      when :==
        helper :eqeq
        compiler.method_calls << mid
        [fragment('$eqeq('), expr(receiver), fragment(', '), expr(args.first), fragment(')')]
      when :===
        helper :eqeqeq
        compiler.method_calls << mid
        [fragment('$eqeqeq('), expr(receiver), fragment(', '), expr(args.first), fragment(')')]
      when :!=
        helper :neqeq
        compiler.method_calls << mid
        [fragment('$neqeq('), expr(receiver), fragment(', '), expr(args.first), fragment(')')]
      end
    elsif args.count == 0
      case mid
      when :!
        helper :not
        compiler.method_calls << mid
        [fragment('$not('), expr(receiver), fragment(')')]
      end
    end
  when :begin
    if sexp.children.count == 1
      js_truthy_optimize(sexp.children.first)
    end
  when :if
    _test, true_body, false_body = *sexp
    if true_body == s(:true)
      # Ensure we recurse the js_truthy call on the `false_body` of the if `expr`.
      # This transforms an expression like:
      #
      # $truthy($truthy(a) || b)
      #
      # Into:
      #
      # $truthy(a) || $truthy(b)
      sexp.meta[:do_js_truthy_on_false_body] = true
      expr(sexp)
    elsif false_body == s(:false)
      sexp.meta[:do_js_truthy_on_true_body] = true
      expr(sexp)
    end
  end
end

#line(*strs) ⇒ Object



37
38
39
40
# File 'opal/lib/opal/nodes/helpers.rb', line 37

def line(*strs)
  push fragment("\n#{current_indent}", loc: false)
  push(*strs)
end

#mid_to_jsid(mid) ⇒ Object

Converts a ruby method name into its javascript equivalent for a method/function call. All ruby method names get prefixed with a '$', and if the name is a valid javascript identifier, it will have a '.' prefix (for dot-calling), otherwise it will be wrapped in brackets to use reference notation calling.



21
22
23
24
25
26
27
# File 'opal/lib/opal/nodes/helpers.rb', line 21

def mid_to_jsid(mid)
  if %r{\=|\+|\-|\*|\/|\!|\?|<|\>|\&|\||\^|\%|\~|\[|`} =~ mid.to_s
    "['$#{mid}']"
  else
    '.$' + mid
  end
end

#property(name) ⇒ Object



8
9
10
# File 'opal/lib/opal/nodes/helpers.rb', line 8

def property(name)
  valid_name?(name) ? ".#{name}" : "[#{name.inspect}]"
end

#valid_name?(name) ⇒ Boolean

Returns:

  • (Boolean)


12
13
14
# File 'opal/lib/opal/nodes/helpers.rb', line 12

def valid_name?(name)
  Opal::Rewriters::JsReservedWords.valid_name?(name)
end