class Opal::Nodes::IfNode
def compile
def compile if should_compile_as_simple_expression? if true_body == s(:true) compile_with_binary_or elsif false_body == s(:false) compile_with_binary_and else compile_with_ternary end else compile_with_if end end
def compile_with_binary_and
def compile_with_binary_and if sexp.meta[:do_js_truthy_on_true_body] truthy = js_truthy(true_body || s(:nil)) else truthy = expr(true_body || s(:nil)) end push '(' push js_truthy(test), ' && ' push '(', truthy, ')' push ')' end
def compile_with_binary_or
def compile_with_binary_or if sexp.meta[:do_js_truthy_on_false_body] falsy = js_truthy(false_body || s(:nil)) else falsy = expr(false_body || s(:nil)) end push '(' push js_truthy(test), ' || ' push '(', falsy, ')' push ')' end
def compile_with_if
def compile_with_if truthy = self.truthy falsy = self.falsy if falsy && !truthy # Let's optimize a little bit `unless` calls. push 'if (!', js_truthy(test), ') {' falsy, truthy = truthy, falsy else push 'if (', js_truthy(test), ') {' end # skip if-body if no truthy sexp indent { line stmt(truthy) } if truthy if falsy if falsy.type == :if line '} else ', stmt(falsy) else line '} else {' indent do line stmt(falsy) end line '}' end else line '}' # This resolution isn't finite. Let's ensure this block # always return something if we expect a return line 'return nil;' if expects_expression? end if expects_expression? if scope.await_encountered wrap '(await (async function() {', '})())' else wrap '(function() {', '})()' end end end
def compile_with_ternary
def compile_with_ternary truthy = true_body falsy = false_body push '(' push js_truthy(test), ' ? ' push '(', expr(truthy || s(:nil)), ') : ' if !falsy || falsy.type == :if push expr(falsy || s(:nil)) else push '(', expr(falsy || s(:nil)), ')' end push ')' end
def expects_expression?
def expects_expression? expr? || recv? end
def falsy
def falsy returnify(false_body) end
def returnify(body)
def returnify(body) if expects_expression? && body compiler.returns(body) else body end end
def should_compile_as_simple_expression?
a ternary operator instead and possibly a binary operator
This addition tries to make a few cases compiled with
it. This produced an ugly code that was hard to minify.
expected an expression from if, we always had to closure
There was a particular case in the past, that when we
def should_compile_as_simple_expression? expects_expression? && simple?(true_body) && simple?(false_body) end
def simple?(body)
def simple?(body) case body when AST::Node case body.type when :return, :js_return, :break, :next, :redo, :retry false when :xstr XStringNode.single_line?( XStringNode.strip_empty_children(body.children) ) else body.children.all? { |i| simple?(i) } end else true end end
def truthy
def truthy returnify(true_body) end