ruby2js 3.5.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -662
- data/lib/ruby2js.rb +61 -10
- data/lib/ruby2js/converter.rb +10 -4
- data/lib/ruby2js/converter/assign.rb +159 -0
- data/lib/ruby2js/converter/begin.rb +7 -2
- data/lib/ruby2js/converter/case.rb +7 -2
- data/lib/ruby2js/converter/class.rb +77 -21
- data/lib/ruby2js/converter/class2.rb +102 -31
- data/lib/ruby2js/converter/def.rb +7 -3
- data/lib/ruby2js/converter/dstr.rb +8 -3
- data/lib/ruby2js/converter/hash.rb +9 -5
- data/lib/ruby2js/converter/hide.rb +13 -0
- data/lib/ruby2js/converter/if.rb +10 -2
- data/lib/ruby2js/converter/import.rb +35 -4
- data/lib/ruby2js/converter/kwbegin.rb +9 -2
- data/lib/ruby2js/converter/literal.rb +14 -2
- data/lib/ruby2js/converter/module.rb +41 -4
- data/lib/ruby2js/converter/opasgn.rb +8 -0
- data/lib/ruby2js/converter/send.rb +45 -5
- data/lib/ruby2js/converter/vasgn.rb +5 -0
- data/lib/ruby2js/converter/xstr.rb +1 -1
- data/lib/ruby2js/demo.rb +53 -0
- data/lib/ruby2js/es2022.rb +5 -0
- data/lib/ruby2js/es2022/strict.rb +3 -0
- data/lib/ruby2js/filter.rb +9 -1
- data/lib/ruby2js/filter/active_functions.rb +44 -0
- data/lib/ruby2js/filter/camelCase.rb +4 -3
- data/lib/ruby2js/filter/cjs.rb +2 -0
- data/lib/ruby2js/filter/esm.rb +133 -7
- data/lib/ruby2js/filter/functions.rb +107 -98
- data/lib/ruby2js/filter/{wunderbar.rb → jsx.rb} +29 -7
- data/lib/ruby2js/filter/node.rb +95 -74
- data/lib/ruby2js/filter/nokogiri.rb +15 -41
- data/lib/ruby2js/filter/react.rb +191 -56
- data/lib/ruby2js/filter/require.rb +100 -5
- data/lib/ruby2js/filter/return.rb +15 -1
- data/lib/ruby2js/filter/securerandom.rb +33 -0
- data/lib/ruby2js/filter/stimulus.rb +185 -0
- data/lib/ruby2js/filter/vue.rb +9 -0
- data/lib/ruby2js/jsx.rb +291 -0
- data/lib/ruby2js/namespace.rb +75 -0
- data/lib/ruby2js/rails.rb +15 -9
- data/lib/ruby2js/serializer.rb +3 -1
- data/lib/ruby2js/version.rb +3 -3
- data/ruby2js.gemspec +1 -1
- metadata +14 -5
- data/lib/ruby2js/filter/esm_migration.rb +0 -72
- data/lib/ruby2js/filter/fast-deep-equal.rb +0 -23
    
        data/lib/ruby2js/filter.rb
    CHANGED
    
    | @@ -13,6 +13,14 @@ module Ruby2JS | |
| 13 13 | 
             
                @@included = nil
         | 
| 14 14 | 
             
                @@excluded = []
         | 
| 15 15 |  | 
| 16 | 
            +
                def self.included_methods
         | 
| 17 | 
            +
                  @@included&.dup
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def self.excluded_methods
         | 
| 21 | 
            +
                  @@excluded&.dup
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 16 24 | 
             
                # indicate that the specified methods are not to be processed
         | 
| 17 25 | 
             
                def self.exclude(*methods)
         | 
| 18 26 | 
             
                  if @@included
         | 
| @@ -52,7 +60,7 @@ module Ruby2JS | |
| 52 60 | 
             
                    not @included.include? method
         | 
| 53 61 | 
             
                  else
         | 
| 54 62 | 
             
                    return true if @exclude_methods.flatten.include? method
         | 
| 55 | 
            -
                    @excluded | 
| 63 | 
            +
                    @excluded&.include? method
         | 
| 56 64 | 
             
                  end
         | 
| 57 65 | 
             
                end
         | 
| 58 66 |  | 
| @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            require 'ruby2js'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Ruby2JS
         | 
| 4 | 
            +
              module Filter
         | 
| 5 | 
            +
                module ActiveFunctions
         | 
| 6 | 
            +
                  include SEXP
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def on_send(node)
         | 
| 9 | 
            +
                    target, method, *args = node.children
         | 
| 10 | 
            +
                    return super unless args.empty?
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    if es2015 and method == :blank?
         | 
| 13 | 
            +
                      create_or_update_import("blank$")
         | 
| 14 | 
            +
                      process node.updated :send, [nil, "blank$", target]
         | 
| 15 | 
            +
                    elsif es2015 and method == :present?
         | 
| 16 | 
            +
                      create_or_update_import("present$")
         | 
| 17 | 
            +
                      process node.updated :send, [nil, "present$", target]
         | 
| 18 | 
            +
                    elsif es2015 and method == :presence
         | 
| 19 | 
            +
                      create_or_update_import("presence$")
         | 
| 20 | 
            +
                      process node.updated :send, [nil, "presence$", target]
         | 
| 21 | 
            +
                    else
         | 
| 22 | 
            +
                      super
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  private
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def create_or_update_import(token)
         | 
| 29 | 
            +
                    af_import = @options[:import_from_skypack] ? "https://cdn.skypack.dev/@ruby2js/active-functions" : "@ruby2js/active-functions"
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    if found_node = prepend_list.find {|ast| ast.type == :import && ast.children.first == af_import}
         | 
| 32 | 
            +
                      unless found_node.children.last.find {|const| const.children.last == token}
         | 
| 33 | 
            +
                        prepend_list.delete found_node
         | 
| 34 | 
            +
                        prepend_list << s(:import, found_node.children.first, found_node.children.last.push(s(:const, nil, token)))
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
                    else
         | 
| 37 | 
            +
                      prepend_list << s(:import, af_import, [s(:const, nil, token)])
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                DEFAULTS.push ActiveFunctions
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| @@ -9,8 +9,9 @@ module Ruby2JS | |
| 9 9 | 
             
                module CamelCase
         | 
| 10 10 | 
             
                  include SEXP
         | 
| 11 11 |  | 
| 12 | 
            -
                   | 
| 12 | 
            +
                  ALLOWLIST = %w{
         | 
| 13 13 | 
             
                    attr_accessor
         | 
| 14 | 
            +
                    method_missing
         | 
| 14 15 | 
             
                  }
         | 
| 15 16 |  | 
| 16 17 | 
             
                  CAPS_EXCEPTIONS = {
         | 
| @@ -37,7 +38,7 @@ module Ruby2JS | |
| 37 38 | 
             
                    node = super
         | 
| 38 39 | 
             
                    return node unless [:send, :csend, :attr].include? node.type
         | 
| 39 40 |  | 
| 40 | 
            -
                    if node.children[0] == nil and  | 
| 41 | 
            +
                    if node.children[0] == nil and ALLOWLIST.include? node.children[1].to_s
         | 
| 41 42 | 
             
                      node
         | 
| 42 43 | 
             
                    elsif node.children[0] && [:ivar, :cvar].include?(node.children[0].type)
         | 
| 43 44 | 
             
                      S(node.type, s(node.children[0].type, camelCase(node.children[0].children[0])),
         | 
| @@ -61,7 +62,7 @@ module Ruby2JS | |
| 61 62 | 
             
                  def handle_generic_node(node, node_type)
         | 
| 62 63 | 
             
                    return node if node.type != node_type
         | 
| 63 64 |  | 
| 64 | 
            -
                    if node.children[0] =~ /_.*\w$/
         | 
| 65 | 
            +
                    if node.children[0] =~ /_.*\w$/ and !ALLOWLIST.include?(node.children[0].to_s)
         | 
| 65 66 | 
             
                      S(node_type , camelCase(node.children[0]), *node.children[1..-1])
         | 
| 66 67 | 
             
                    else
         | 
| 67 68 | 
             
                      node
         | 
    
        data/lib/ruby2js/filter/cjs.rb
    CHANGED
    
    
    
        data/lib/ruby2js/filter/esm.rb
    CHANGED
    
    | @@ -1,13 +1,83 @@ | |
| 1 1 | 
             
            require 'ruby2js'
         | 
| 2 2 |  | 
| 3 | 
            +
            Ruby2JS.module_default = :esm
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            module Ruby2JS
         | 
| 4 6 | 
             
              module Filter
         | 
| 5 7 | 
             
                module ESM
         | 
| 6 8 | 
             
                  include SEXP
         | 
| 7 9 |  | 
| 8 | 
            -
                  def  | 
| 10 | 
            +
                  def options=(options)
         | 
| 11 | 
            +
                    super
         | 
| 12 | 
            +
                    @esm_autoexports = !@disable_autoexports && options[:autoexports]
         | 
| 13 | 
            +
                    @esm_autoimports = options[:autoimports]
         | 
| 14 | 
            +
                    @esm_defs = options[:defs] || {}
         | 
| 15 | 
            +
                    @esm_explicit_tokens = Set.new
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def process(node)
         | 
| 19 | 
            +
                    return super unless @esm_autoexports
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    list = [node]
         | 
| 22 | 
            +
                    while list.length == 1 and list.first.type == :begin
         | 
| 23 | 
            +
                      list = list.first.children.dup
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    replaced = []
         | 
| 27 | 
            +
                    list.map! do |child|
         | 
| 28 | 
            +
                      replacement = child
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      if [:module, :class].include? child.type and
         | 
| 31 | 
            +
                        child.children.first.type == :const and
         | 
| 32 | 
            +
                        child.children.first.children.first == nil \
         | 
| 33 | 
            +
                      then
         | 
| 34 | 
            +
                        replacement = s(:export, child)
         | 
| 35 | 
            +
                      elsif child.type == :casgn and child.children.first == nil
         | 
| 36 | 
            +
                        replacement = s(:export, child)
         | 
| 37 | 
            +
                      elsif child.type == :def
         | 
| 38 | 
            +
                        replacement = s(:export, child)
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                      if replacement != child
         | 
| 42 | 
            +
                        replaced << replacement
         | 
| 43 | 
            +
                        @comments[replacement] = @comments[child] if @comments[child]
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      replacement
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    if replaced.length == 1 and @esm_autoexports == :default
         | 
| 50 | 
            +
                      list.map! do |child|
         | 
| 51 | 
            +
                        if child == replaced.first
         | 
| 52 | 
            +
                          replacement = s(:export, s(:send, nil, :default, *child.children))
         | 
| 53 | 
            +
                          @comments[replacement] = @comments[child] if @comments[child]
         | 
| 54 | 
            +
                          replacement
         | 
| 55 | 
            +
                        else
         | 
| 56 | 
            +
                          child
         | 
| 57 | 
            +
                        end
         | 
| 58 | 
            +
                      end
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    @esm_autoexports = false
         | 
| 62 | 
            +
                    process s(:begin, *list)
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  def on_class(node)
         | 
| 66 | 
            +
                    @esm_explicit_tokens << node.children.first.children.last
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    super
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def on_def(node)
         | 
| 72 | 
            +
                    @esm_explicit_tokens << node.children.first
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    super
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def on_lvasgn(node)
         | 
| 78 | 
            +
                    @esm_explicit_tokens << node.children.first
         | 
| 79 | 
            +
             | 
| 9 80 | 
             
                    super
         | 
| 10 | 
            -
                    @esm = true # signal for other filters
         | 
| 11 81 | 
             
                  end
         | 
| 12 82 |  | 
| 13 83 | 
             
                  def on_send(node)
         | 
| @@ -23,7 +93,7 @@ module Ruby2JS | |
| 23 93 | 
             
                        end
         | 
| 24 94 | 
             
                      end
         | 
| 25 95 |  | 
| 26 | 
            -
                      if args[0].type == :str
         | 
| 96 | 
            +
                      if args[0].type == :str and args.length == 1
         | 
| 27 97 | 
             
                        # import "file.css"
         | 
| 28 98 | 
             
                        #   => import "file.css"
         | 
| 29 99 | 
             
                        s(:import, args[0].children[0])
         | 
| @@ -36,6 +106,8 @@ module Ruby2JS | |
| 36 106 | 
             
                        args[0].children[2].children[2].type == :str
         | 
| 37 107 | 
             
                        # import name from "file.js"
         | 
| 38 108 | 
             
                        #  => import name from "file.js"
         | 
| 109 | 
            +
                        @esm_explicit_tokens << args[0].children[1]
         | 
| 110 | 
            +
             | 
| 39 111 | 
             
                        s(:import,
         | 
| 40 112 | 
             
                          [args[0].children[2].children[2].children[0]],
         | 
| 41 113 | 
             
                          process(s(:attr, nil, args[0].children[1])))
         | 
| @@ -49,17 +121,71 @@ module Ruby2JS | |
| 49 121 | 
             
                        #   => import Stuff as * from "file.js"
         | 
| 50 122 | 
             
                        # import [ Some, Stuff ], from: "file.js"
         | 
| 51 123 | 
             
                        #   => import { Some, Stuff } from "file.js"
         | 
| 52 | 
            -
                         | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
                         | 
| 124 | 
            +
                        # import Some, [ More, Stuff ], from: "file.js"
         | 
| 125 | 
            +
                        #   => import Some, { More, Stuff } from "file.js"
         | 
| 126 | 
            +
                        imports = []
         | 
| 127 | 
            +
                        if %i(const send str).include? args[0].type
         | 
| 128 | 
            +
                          @esm_explicit_tokens << args[0].children.last
         | 
| 129 | 
            +
                          imports << process(args.shift)
         | 
| 130 | 
            +
                        end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                        if args[0].type == :array
         | 
| 133 | 
            +
                          args[0].children.each {|i| @esm_explicit_tokens << i.children.last}
         | 
| 134 | 
            +
                          imports << process_all(args.shift.children)
         | 
| 135 | 
            +
                        end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                        s(:import, args[0].children, *imports) unless args[0].nil?
         | 
| 56 138 | 
             
                      end
         | 
| 57 139 | 
             
                    elsif method == :export          
         | 
| 58 140 | 
             
                      s(:export, *process_all(args))
         | 
| 141 | 
            +
                    elsif target.nil? and found_import = find_autoimport(method)
         | 
| 142 | 
            +
                      prepend_list << s(:import, found_import[0], found_import[1])
         | 
| 143 | 
            +
                      super
         | 
| 59 144 | 
             
                    else
         | 
| 60 145 | 
             
                      super
         | 
| 61 146 | 
             
                    end
         | 
| 62 147 | 
             
                  end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  def on_const(node)
         | 
| 150 | 
            +
                    if node.children.first == nil and found_import = find_autoimport(node.children.last)
         | 
| 151 | 
            +
                      prepend_list << s(:import, found_import[0], found_import[1])
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                      values = @esm_defs[node.children.last]
         | 
| 154 | 
            +
                      
         | 
| 155 | 
            +
            	  if values
         | 
| 156 | 
            +
            	    values = values.map {|value| 
         | 
| 157 | 
            +
            	      if value.to_s.start_with? "@" 
         | 
| 158 | 
            +
            		[value.to_s[1..-1].to_sym, s(:self)]
         | 
| 159 | 
            +
            	      else
         | 
| 160 | 
            +
            		[value.to_sym, s(:autobind, s(:self))]
         | 
| 161 | 
            +
            	      end
         | 
| 162 | 
            +
            	    }.to_h
         | 
| 163 | 
            +
             | 
| 164 | 
            +
            	    @namespace.defineProps values, [node.children.last]
         | 
| 165 | 
            +
            	  end
         | 
| 166 | 
            +
                    end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                    super
         | 
| 169 | 
            +
                  end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  def on_export(node)
         | 
| 172 | 
            +
                    s(:export, *process_all(node.children))
         | 
| 173 | 
            +
                  end
         | 
| 174 | 
            +
                end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                private
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                def find_autoimport(token)
         | 
| 179 | 
            +
                  return nil if @esm_autoimports.nil?
         | 
| 180 | 
            +
                  return nil if @esm_explicit_tokens.include?(token)
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                  token = camelCase(token) if respond_to?(:camelCase)
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                  if @esm_autoimports[token]
         | 
| 185 | 
            +
                    [@esm_autoimports[token], s(:const, nil, token)]
         | 
| 186 | 
            +
                  elsif found_key = @esm_autoimports.keys.find {|key| key.is_a?(Array) && key.include?(token)}
         | 
| 187 | 
            +
                    [@esm_autoimports[found_key], found_key.map {|key| s(:const, nil, key)}]
         | 
| 188 | 
            +
                  end
         | 
| 63 189 | 
             
                end
         | 
| 64 190 |  | 
| 65 191 | 
             
                DEFAULTS.push ESM
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            require 'ruby2js'
         | 
| 2 | 
            -
            require 'regexp_parser'
         | 
| 2 | 
            +
            require 'regexp_parser/scanner'
         | 
| 3 3 |  | 
| 4 4 | 
             
            module Ruby2JS
         | 
| 5 5 | 
             
              module Filter
         | 
| @@ -26,9 +26,15 @@ module Ruby2JS | |
| 26 26 | 
             
                    return super if excluded?(method)
         | 
| 27 27 |  | 
| 28 28 | 
             
                    if [:max, :min].include? method and args.length == 0
         | 
| 29 | 
            -
                       | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 29 | 
            +
                      if target.type == :array
         | 
| 30 | 
            +
                        process S(:send, s(:const, nil, :Math), node.children[1],
         | 
| 31 | 
            +
                          *target.children)
         | 
| 32 | 
            +
                      elsif node.is_method?
         | 
| 33 | 
            +
                        process S(:send, s(:const, nil, :Math), node.children[1],
         | 
| 34 | 
            +
                          s(:splat, target))
         | 
| 35 | 
            +
                      else
         | 
| 36 | 
            +
                        return super
         | 
| 37 | 
            +
                      end
         | 
| 32 38 |  | 
| 33 39 | 
             
                    elsif method == :call and target and target.type == :ivar
         | 
| 34 40 | 
             
                      process S(:send, s(:self), "_#{target.children.first.to_s[1..-1]}",
         | 
| @@ -43,71 +49,78 @@ module Ruby2JS | |
| 43 49 |  | 
| 44 50 | 
             
                    elsif method == :[]= and args.length == 3 and
         | 
| 45 51 | 
             
                      args[0].type == :regexp and args[1].type == :int
         | 
| 52 | 
            +
             | 
| 46 53 | 
             
                      index = args[1].children.first
         | 
| 47 54 |  | 
| 48 | 
            -
                       | 
| 49 | 
            -
                       | 
| 50 | 
            -
             | 
| 55 | 
            +
                      # identify groups
         | 
| 56 | 
            +
                      regex = args[0].children.first.children.first
         | 
| 57 | 
            +
                      tokens = Regexp::Scanner.scan(regex)
         | 
| 58 | 
            +
                      groups = []
         | 
| 59 | 
            +
                      stack = []
         | 
| 60 | 
            +
                      tokens.each do |token|
         | 
| 61 | 
            +
                        next unless token[0] == :group
         | 
| 62 | 
            +
                        if token[1] == :capture
         | 
| 63 | 
            +
                          groups.push token.dup
         | 
| 64 | 
            +
                          return super if groups.length == index and not stack.empty?
         | 
| 65 | 
            +
                          stack.push groups.last
         | 
| 66 | 
            +
                        elsif token[1] == :close
         | 
| 67 | 
            +
                          stack.pop[-1]=token.last
         | 
| 68 | 
            +
                        end
         | 
| 51 69 | 
             
                      end
         | 
| 70 | 
            +
                      group = groups[index-1]
         | 
| 52 71 |  | 
| 53 | 
            -
                       | 
| 54 | 
            -
             | 
| 55 | 
            -
                       | 
| 72 | 
            +
                      # rewrite regex
         | 
| 73 | 
            +
                      prepend = nil
         | 
| 74 | 
            +
                      append = nil
         | 
| 56 75 |  | 
| 57 | 
            -
                       | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
                         | 
| 76 | 
            +
                      if group[4] < regex.length
         | 
| 77 | 
            +
                        regex = (regex[0...group[4]] + '(' + regex[group[4]..-1] + ')').
         | 
| 78 | 
            +
                          sub(/\$\)$/, ')$')
         | 
| 79 | 
            +
                        append = 2
         | 
| 61 80 | 
             
                      end
         | 
| 62 81 |  | 
| 63 | 
            -
                       | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
                      if parts.first.type == :anchor
         | 
| 67 | 
            -
                        pre = parts.shift.to_s
         | 
| 68 | 
            -
                        split -= 1
         | 
| 82 | 
            +
                      if group[4] - group[3] == 2
         | 
| 83 | 
            +
                        regex = regex[0...group[3]] + regex[group[4]..-1]
         | 
| 84 | 
            +
                        append = 1 if append
         | 
| 69 85 | 
             
                      end
         | 
| 70 86 |  | 
| 71 | 
            -
                      if  | 
| 72 | 
            -
                         | 
| 73 | 
            -
                           | 
| 74 | 
            -
                         | 
| 75 | 
            -
             | 
| 76 | 
            -
                          index += 1
         | 
| 77 | 
            -
                        end
         | 
| 78 | 
            -
                        dstr.unshift s(:send, s(:lvar, :match), :[], s(:int, 0))
         | 
| 87 | 
            +
                      if group[3] > 0
         | 
| 88 | 
            +
                        regex = ('(' + regex[0...group[3]] + ')' + regex[group[3]..-1]).
         | 
| 89 | 
            +
                          sub(/^\(\^/, '^(')
         | 
| 90 | 
            +
                        prepend = 1
         | 
| 91 | 
            +
                        append += 1 if append
         | 
| 79 92 | 
             
                      end
         | 
| 80 93 |  | 
| 94 | 
            +
                      regex = process s(:regexp, s(:str, regex), args[0].children.last)
         | 
| 81 95 |  | 
| 82 | 
            -
                       | 
| 83 | 
            -
                      if  | 
| 84 | 
            -
                         | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
                         | 
| 91 | 
            -
                           | 
| 96 | 
            +
                      # 
         | 
| 97 | 
            +
                      if args.last.type == :str
         | 
| 98 | 
            +
                        str = args.last.children.first.gsub('$', '$$')
         | 
| 99 | 
            +
                        str = "$#{prepend}#{str}" if prepend
         | 
| 100 | 
            +
                        str = "#{str}$#{append}" if append
         | 
| 101 | 
            +
                        expr = s(:send, target, :replace, regex, s(:str, str))
         | 
| 102 | 
            +
                      else
         | 
| 103 | 
            +
                        dstr = args.last.type == :dstr ? args.last.children.dup : [args.last]
         | 
| 104 | 
            +
                        if prepend
         | 
| 105 | 
            +
                          dstr.unshift s(:send, s(:lvar, :match), :[], s(:int, prepend-1))
         | 
| 106 | 
            +
                        end
         | 
| 107 | 
            +
                        if append
         | 
| 108 | 
            +
                          dstr << s(:send, s(:lvar, :match), :[], s(:int, append-1))
         | 
| 92 109 | 
             
                        end
         | 
| 93 | 
            -
                        dstr << s(:send, s(:lvar, :match), :[], s(:int, index))
         | 
| 94 | 
            -
                      end
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                      rewritten = pre + rewritten + post
         | 
| 97 110 |  | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 111 | 
            +
                        expr = s(:block,
         | 
| 112 | 
            +
                          s(:send, target, :replace, regex),
         | 
| 113 | 
            +
                          s(:args, s(:arg, :match)),
         | 
| 114 | 
            +
                          process(s(:dstr, *dstr)))
         | 
| 115 | 
            +
                      end
         | 
| 103 116 |  | 
| 104 117 | 
             
                      if VAR_TO_ASSIGN.keys.include? target.type
         | 
| 105 | 
            -
                        S(VAR_TO_ASSIGN[target.type], target.children.first,  | 
| 118 | 
            +
                        S(VAR_TO_ASSIGN[target.type], target.children.first, expr)
         | 
| 106 119 | 
             
                      elsif target.type == :send
         | 
| 107 120 | 
             
                        if target.children[0] == nil
         | 
| 108 | 
            -
                          S(:lvasgn, target.children[1],  | 
| 121 | 
            +
                          S(:lvasgn, target.children[1], expr)
         | 
| 109 122 | 
             
                        else
         | 
| 110 | 
            -
                          S(:send, target.children[0], :"#{target.children[1]}=",  | 
| 123 | 
            +
                          S(:send, target.children[0], :"#{target.children[1]}=", expr)
         | 
| 111 124 | 
             
                        end
         | 
| 112 125 | 
             
                      else
         | 
| 113 126 | 
             
                        super
         | 
| @@ -116,57 +129,14 @@ module Ruby2JS | |
| 116 129 | 
             
                    elsif method == :merge
         | 
| 117 130 | 
             
                      args.unshift target
         | 
| 118 131 |  | 
| 119 | 
            -
                      if  | 
| 120 | 
            -
                         | 
| 121 | 
            -
                          process S(:hash, *args.map {|arg| s(:kwsplat, arg)})
         | 
| 122 | 
            -
                        else
         | 
| 123 | 
            -
                          process S(:send, s(:const, nil, :Object), :assign, s(:hash),
         | 
| 124 | 
            -
                            *args)
         | 
| 125 | 
            -
                        end
         | 
| 132 | 
            +
                      if es2018
         | 
| 133 | 
            +
                        process S(:hash, *args.map {|arg| s(:kwsplat, arg)})
         | 
| 126 134 | 
             
                      else
         | 
| 127 | 
            -
                         | 
| 128 | 
            -
             | 
| 129 | 
            -
                        s(:send, s(:block, s(:send, nil, :lambda), s(:args),
         | 
| 130 | 
            -
                          s(:begin, *copy, *args.map {|modname|
         | 
| 131 | 
            -
                          if modname.type == :hash
         | 
| 132 | 
            -
                            s(:begin, *modname.children.map {|pair|
         | 
| 133 | 
            -
                                s(:send, s(:gvar, :$$), :[]=, *pair.children)
         | 
| 134 | 
            -
                              })
         | 
| 135 | 
            -
                          else
         | 
| 136 | 
            -
                            s(:for, s(:lvasgn, :$_), modname,
         | 
| 137 | 
            -
                            s(:send, s(:gvar, :$$), :[]=,
         | 
| 138 | 
            -
                            s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
         | 
| 139 | 
            -
                          end
         | 
| 140 | 
            -
                          }, s(:return, s(:gvar, :$$)))), :[])
         | 
| 135 | 
            +
                        process S(:assign, s(:hash), *args)
         | 
| 141 136 | 
             
                      end
         | 
| 142 137 |  | 
| 143 138 | 
             
                    elsif method == :merge!
         | 
| 144 | 
            -
                       | 
| 145 | 
            -
                        process S(:send, s(:const, nil, :Object), :assign, target, *args)
         | 
| 146 | 
            -
                      else
         | 
| 147 | 
            -
                        copy = []
         | 
| 148 | 
            -
             | 
| 149 | 
            -
                        unless
         | 
| 150 | 
            -
                           target.type == :send and target.children.length == 2 and
         | 
| 151 | 
            -
                           target.children[0] == nil
         | 
| 152 | 
            -
                        then
         | 
| 153 | 
            -
                           copy << s(:gvasgn, :$0, target)
         | 
| 154 | 
            -
                           target = s(:gvar, :$0)
         | 
| 155 | 
            -
                        end
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                        s(:send, s(:block, s(:send, nil, :lambda), s(:args),
         | 
| 158 | 
            -
                          s(:begin, *copy, *args.map {|modname|
         | 
| 159 | 
            -
                          if modname.type == :hash
         | 
| 160 | 
            -
                            s(:begin, *modname.children.map {|pair|
         | 
| 161 | 
            -
                                s(:send, target, :[]=, *pair.children)
         | 
| 162 | 
            -
                              })
         | 
| 163 | 
            -
                          else
         | 
| 164 | 
            -
                            s(:for, s(:lvasgn, :$_), modname,
         | 
| 165 | 
            -
                            s(:send, target, :[]=,
         | 
| 166 | 
            -
                            s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
         | 
| 167 | 
            -
                          end
         | 
| 168 | 
            -
                          }, s(:return, target))), :[])
         | 
| 169 | 
            -
                      end
         | 
| 139 | 
            +
                      process S(:assign, target, *args)
         | 
| 170 140 |  | 
| 171 141 | 
             
                    elsif method == :delete and args.length == 1
         | 
| 172 142 | 
             
                      if not target
         | 
| @@ -531,6 +501,34 @@ module Ruby2JS | |
| 531 501 | 
             
                    elsif method == :block_given? and target == nil and args.length == 0
         | 
| 532 502 | 
             
                      process process s(:lvar, "_implicitBlockYield")
         | 
| 533 503 |  | 
| 504 | 
            +
                    elsif method == :abs and args.length == 0
         | 
| 505 | 
            +
                      process S(:send, s(:const, nil, :Math), :abs, target)
         | 
| 506 | 
            +
             | 
| 507 | 
            +
                    elsif method == :ceil and args.length == 0
         | 
| 508 | 
            +
                      process S(:send, s(:const, nil, :Math), :ceil, target)
         | 
| 509 | 
            +
             | 
| 510 | 
            +
                    elsif method == :floor and args.length == 0
         | 
| 511 | 
            +
                      process S(:send, s(:const, nil, :Math), :floor, target)
         | 
| 512 | 
            +
             | 
| 513 | 
            +
                    elsif method == :sum and args.length == 0
         | 
| 514 | 
            +
                      process S(:send, target, :reduce, s(:block, s(:send, nil, :proc),
         | 
| 515 | 
            +
                        s(:args, s(:arg, :a), s(:arg, :b)),
         | 
| 516 | 
            +
                        s(:send, s(:lvar, :a), :+, s(:lvar, :b))), s(:int, 0))
         | 
| 517 | 
            +
             | 
| 518 | 
            +
                    elsif method == :method_defined? and args.length >= 1
         | 
| 519 | 
            +
                      if args[1] == s(:false)
         | 
| 520 | 
            +
                        process S(:send, s(:attr, target, :prototype), :hasOwnProperty, args[0])
         | 
| 521 | 
            +
                      elsif args.length == 1 or args[1] == s(:true)
         | 
| 522 | 
            +
                        process S(:in?, args[0], s(:attr, target, :prototype))
         | 
| 523 | 
            +
                      else
         | 
| 524 | 
            +
                        process S(:if, args[1], s(:in?, args[0], s(:attr, target, :prototype)),
         | 
| 525 | 
            +
                          s(:send, s(:attr, target, :prototype), :hasOwnProperty, args[0]))
         | 
| 526 | 
            +
                      end
         | 
| 527 | 
            +
             | 
| 528 | 
            +
                    elsif method == :alias_method and args.length == 2
         | 
| 529 | 
            +
                      process S(:send, s(:attr, target, :prototype), :[]=, args[0],
         | 
| 530 | 
            +
                        s(:attr, s(:attr, target, :prototype), args[1].children[0]))
         | 
| 531 | 
            +
             | 
| 534 532 | 
             
                    else
         | 
| 535 533 | 
             
                      super
         | 
| 536 534 | 
             
                    end
         | 
| @@ -717,6 +715,10 @@ module Ruby2JS | |
| 717 715 | 
             
                        s(:return, s(:lvar, node.children[1].children[0].children[0])))),
         | 
| 718 716 | 
             
                        :[], call.children[0]])
         | 
| 719 717 |  | 
| 718 | 
            +
                    elsif method == :define_method and call.children.length == 3
         | 
| 719 | 
            +
                      process node.updated(:send, [s(:attr, call.children[0], :prototype), :[]=,
         | 
| 720 | 
            +
                        call.children[2], s(:deff, nil, *node.children[1..-1])])
         | 
| 721 | 
            +
             | 
| 720 722 | 
             
                    else
         | 
| 721 723 | 
             
                      super
         | 
| 722 724 | 
             
                    end
         | 
| @@ -726,6 +728,12 @@ module Ruby2JS | |
| 726 728 | 
             
                    name, inheritance, *body = node.children
         | 
| 727 729 | 
             
                    body.compact!
         | 
| 728 730 |  | 
| 731 | 
            +
                    body.each_with_index do |node, i|
         | 
| 732 | 
            +
                      if node.type == :send and node.children[0..1] == [nil, :alias_method]
         | 
| 733 | 
            +
                        body[i] = node.updated(:send, [name, *node.children[1..-1]])
         | 
| 734 | 
            +
                      end
         | 
| 735 | 
            +
                    end
         | 
| 736 | 
            +
             | 
| 729 737 | 
             
                    if inheritance == s(:const, nil, :Exception)
         | 
| 730 738 | 
             
                      unless
         | 
| 731 739 | 
             
                        body.any? {|statement| statement.type == :def and
         | 
| @@ -741,7 +749,8 @@ module Ruby2JS | |
| 741 749 | 
             
                      body = [s(:begin, *body)] if body.length > 1
         | 
| 742 750 | 
             
                      S(:class, name, s(:const, nil, :Error), *body)
         | 
| 743 751 | 
             
                    else
         | 
| 744 | 
            -
                       | 
| 752 | 
            +
                      body = [s(:begin, *body)] if body.length > 1
         | 
| 753 | 
            +
                      super S(:class, name, inheritance, *body)
         | 
| 745 754 | 
             
                    end
         | 
| 746 755 | 
             
                  end
         | 
| 747 756 | 
             
                end
         |