Module: Opal::Nodes::Helpers
- Included in:
- Base
- Defined in:
- opal/lib/opal/nodes/helpers.rb
Constant Summary
- ES51_RESERVED_WORD =
Reserved javascript keywords - we cannot create variables with the same name (ref: http://stackoverflow.com/a/9337272/601782)
/#{REGEXP_START}(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)#{REGEXP_END}/
- ES3_RESERVED_WORD_EXCLUSIVE =
ES3 reserved words that aren’t ES5.1 reserved words
/#{REGEXP_START}(?:int|byte|char|goto|long|final|float|short|double|native|throws|boolean|abstract|volatile|transient|synchronized)#{REGEXP_END}/
- PROTO_SPECIAL_PROPS =
Prototype special properties.
/#{REGEXP_START}(?:constructor|displayName|__proto__|__parent__|__noSuchMethod__|__count__)#{REGEXP_END}/
- PROTO_SPECIAL_METHODS =
Prototype special methods.
/#{REGEXP_START}(?:hasOwnProperty|valueOf)#{REGEXP_END}/
- IMMUTABLE_PROPS =
Immutable properties of the global object
/#{REGEXP_START}(?:NaN|Infinity|undefined)#{REGEXP_END}/
- BASIC_IDENTIFIER_RULES =
Doesn't take in account utf8
/#{REGEXP_START}[$_a-z][$_a-z\d]*#{REGEXP_END}/i
- RESERVED_FUNCTION_NAMES =
Defining a local function like Array may break everything
/#{REGEXP_START}(?:Array)#{REGEXP_END}/
Instance Method Summary collapse
- #current_indent ⇒ Object
- #empty_line ⇒ Object
- #indent(&block) ⇒ Object
- #ivar(name) ⇒ Object
- #js_falsy(sexp) ⇒ Object
- #js_truthy(sexp) ⇒ Object
- #js_truthy_optimize(sexp) ⇒ Object
- #line(*strs) ⇒ Object
-
#lvar_to_js(var) ⇒ Object
Converts a ruby lvar/arg name to a js identifier.
-
#mid_to_jsid(mid) ⇒ Object
Converts a ruby method name into its javascript equivalent for a method/function call.
- #property(name) ⇒ Object
- #valid_ivar_name?(name) ⇒ Boolean
- #valid_name?(name) ⇒ Boolean
- #variable(name) ⇒ Object
Instance Method Details
#current_indent ⇒ Object
79 80 81 |
# File 'opal/lib/opal/nodes/helpers.rb', line 79 def current_indent compiler.parser_indent end |
#empty_line ⇒ Object
88 89 90 |
# File 'opal/lib/opal/nodes/helpers.rb', line 88 def empty_line push "\n" end |
#indent(&block) ⇒ Object
75 76 77 |
# File 'opal/lib/opal/nodes/helpers.rb', line 75 def indent(&block) compiler.indent(&block) end |
#ivar(name) ⇒ Object
50 51 52 |
# File 'opal/lib/opal/nodes/helpers.rb', line 50 def ivar(name) valid_ivar_name?(name.to_s) ? name : "#{name}$" end |
#js_falsy(sexp) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'opal/lib/opal/nodes/helpers.rb', line 102 def js_falsy(sexp) if sexp.type == :call mid = sexp[2] if mid == :block_given? scope.uses_block! return "#{scope.block_name} === nil" end end with_temp do |tmp| [fragment("((#{tmp} = "), expr(sexp), fragment(") === nil || #{tmp} == null || (#{tmp}.$$is_boolean && #{tmp} == false))")] end end |
#js_truthy(sexp) ⇒ Object
92 93 94 95 96 97 98 99 100 |
# File 'opal/lib/opal/nodes/helpers.rb', line 92 def js_truthy(sexp) if optimize = js_truthy_optimize(sexp) return optimize end with_temp do |tmp| [fragment("((#{tmp} = "), expr(sexp), fragment(") !== nil && #{tmp} != null && (!#{tmp}.$$is_boolean || #{tmp} == true))")] end end |
#js_truthy_optimize(sexp) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'opal/lib/opal/nodes/helpers.rb', line 116 def js_truthy_optimize(sexp) if sexp.type == :call mid = sexp[2] receiver_handler_class = (receiver = sexp[1]) && 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? || mid == :==" expr(sexp) end elsif [:lvar, :self].include? sexp.type [expr(sexp.dup), fragment(" !== false && "), expr(sexp.dup), fragment(" !== nil && "), expr(sexp.dup), fragment(" != null")] end end |
#line(*strs) ⇒ Object
83 84 85 86 |
# File 'opal/lib/opal/nodes/helpers.rb', line 83 def line(*strs) push "\n#{current_indent}" push(*strs) end |
#lvar_to_js(var) ⇒ Object
Converts a ruby lvar/arg name to a js identifier. Not all ruby names are valid in javascript. A $ suffix is added to non-valid names. varibales
57 58 59 60 |
# File 'opal/lib/opal/nodes/helpers.rb', line 57 def lvar_to_js(var) var = "#{var}$" unless valid_name? var.to_s var.to_sym 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.
67 68 69 70 71 72 73 |
# File 'opal/lib/opal/nodes/helpers.rb', line 67 def mid_to_jsid(mid) if /\=|\+|\-|\*|\/|\!|\?|<|\>|\&|\||\^|\%|\~|\[/ =~ mid.to_s "['$#{mid}']" else '.$' + mid end end |
#property(name) ⇒ Object
30 31 32 |
# File 'opal/lib/opal/nodes/helpers.rb', line 30 def property(name) valid_name?(name) ? ".#{name}" : "[#{name.inspect}]" end |
#valid_ivar_name?(name) ⇒ Boolean
46 47 48 |
# File 'opal/lib/opal/nodes/helpers.rb', line 46 def valid_ivar_name?(name) not (PROTO_SPECIAL_PROPS =~ name or PROTO_SPECIAL_METHODS =~ name) end |
#valid_name?(name) ⇒ Boolean
34 35 36 37 38 39 40 |
# File 'opal/lib/opal/nodes/helpers.rb', line 34 def valid_name?(name) BASIC_IDENTIFIER_RULES =~ name and not( ES51_RESERVED_WORD =~ name or ES3_RESERVED_WORD_EXCLUSIVE =~ name or IMMUTABLE_PROPS =~ name ) end |
#variable(name) ⇒ Object
42 43 44 |
# File 'opal/lib/opal/nodes/helpers.rb', line 42 def variable(name) valid_name?(name.to_s) ? name : "#{name}$" end |