class Jsrb::Base
`Jsrb::Base` is a centralized class for Jsrb
template. `js`, accessed from views (i.e. `*.jsrb` files), is an instance of Jsrb::Base
.
`Jsrb::Base` provides the interface for pushing statements, constructing expressions and generating JavaScript outputs with handling an internal statement context properly.
Attributes
Public Class Methods
Shows JavaScript generator class name, `'Jsrb::NotFastGenerator'` by default.
### **Help wanted!**
*Jsrb::NotFastGenerator uses ExecJS and escodegen to generate JavaScript. It could be more efficient and get better error messages if we implement it in Ruby*.
@return [String] class name of a code generator
# File lib/jsrb/base.rb, line 218 def code_generator @code_generator || 'Jsrb::NotFastGenerator' end
@private
# File lib/jsrb/base.rb, line 225 def code_generator_class @code_generator_class ||= Object.const_get(code_generator) end
@private
# File lib/jsrb/base.rb, line 12 def initialize @context = JSStatementContext.new end
Public Instance Methods
Pushes an ExpressionStatement to the current context
@example
js.do!(js.expr[:x].set(100)) # => # x = 100;
@param [Jsrb::ExprChain] expr target expression. @return [nil]
# File lib/jsrb/base.rb, line 36 def do!(expr) ast = expr.object raise ArgumentError, 'Expression is empty' unless ast @context.push( type: 'ExpressionStatement', expression: ast ) end
Constructs a new expression chain with a given JavaScript AST node.
@param [convertible ruby values] object represents JavaScript expression AST node @return [Jsrb::ExprChain] chainable instance
# File lib/jsrb/base.rb, line 203 def expr(object = nil) @context.new_expression(object) end
Generates executable JavaScript code from current context.
@return [String] generated executable JavaScript code
# File lib/jsrb/base.rb, line 20 def generate_code generator = self.class.code_generator_class.new generator.call type: 'Program', sourceType: 'script', body: @context.stacks.first end
Constructs a new conditional chain that represents a conditional expression at end.
@example
result = var! js.do! result, js.if(expr1) { result_expr1 }.elsif(expr2) { result_expr2 }.else { result_expr3 } # => # // The actual output will have certain immediate functions # // that preserve variable scope for each case. # var _v1; # _v1 = (function() { # if (..expr1..) { # return ..result_expr1..; # } else if (..expr2..) { # return ..result_expr2..; # } else { # return ..result_expr3..; # } # })()
@param [Jsrb::ExprChain, convertible ruby values] cond_expr an expression for the test @yield new context block for the consequent case @return [Jsrb::CondChain] condition chainable instance
# File lib/jsrb/base.rb, line 194 def if(cond_expr, &block) CondChain.new(@context, true).elsif(cond_expr, &block) end
Starts a new conditional chain that pushes an IfStatement to the current context at end.
@example
js.if!(expr1) { # .. }.elsif(expr2) { # .. }.else { # .. } # => # // The actual output will have certain immediate functions # // that preserve variable scope for each case. # if (..expr1..) { # // .. # } else if (..expr2..) { # // .. # } else { # // .. # } # If you don't have else clause, close with `#end`. js.if!(expr1) { # .. }.elsif(expr2) { # .. }.end # => # if (..expr1..) { # // .. # } else if (..expr2..) { # // .. # }
@param [Jsrb::ExprChain, convertible ruby values] cond_expr an expression for the test @yield new context block for the consequent case @return [Jsrb::CondChain] condition chainable instance
# File lib/jsrb/base.rb, line 161 def if!(cond_expr, &block) CondChain.new(@context, false).elsif(cond_expr, &block) end
Pushes an assignment statement `lhs = rhs;`. This is a short hand of `js.do! lhs_expr.set(rhs_expr)`
@example
a = js.var! :a js.set!(a, 'dog') # => # var a; # a = 'dog'; # directly pass a symbol of identifier name js.set!(:x, 100) # => # x = 100;
@param [Jsrb::ExprChain, String, Symbol] expr target expression. @return [nil]
# File lib/jsrb/base.rb, line 63 def set!(lhs, rhs) lhs_expr = lhs.is_a?(ExprChain) ? lhs : expr(lhs) do! lhs_expr.set(rhs) end
Pushes a VariableDeclaration to the current context and returns an access to the created identifier. @example
name = js.var!(:name) { 'foo' } # var name = 'foo'; ary = js.var! :ary # var ary; obj = js.var! :obj # var obj; result = js.var! # var _v1; //<- auto generate variable name
@param [Symbol] name a name of identifier, autogenerated if not given @yield optional block for initializer @yieldreturn an initializer expression @return [Jsrb::ExprChain] the expression which represents a newly created identifier
# File lib/jsrb/base.rb, line 87 def var!(id = nil) id ||= @context.gen_var_name! val_ast = if block_given? raw_expr = yield raw_expr.is_a?(ExprChain) ? raw_expr.unwrap : @context.ruby_to_js_ast(raw_expr) end if val_ast @context.push( type: 'VariableDeclaration', declarations: [{ type: 'VariableDeclarator', id: { type: 'Identifier', name: id.to_s }, init: val_ast }], kind: 'var' ) else @context.push( type: 'VariableDeclaration', declarations: [{ type: 'VariableDeclarator', id: { type: 'Identifier', name: id.to_s } }], kind: 'var' ) end expr[id] end