diff --git a/lib/ruby2js.rb b/lib/ruby2js.rb index 70f8f06..0401abb 100644 --- a/lib/ruby2js.rb +++ b/lib/ruby2js.rb @@ -224,7 +224,7 @@ def self.convert(source, options={}) file,line = source.source_location source = IO.read(file) ast, comments = parse(source) - comments = Parser::Source::Comment.associate(ast, comments) if ast + comments = Parser::Source::Comment.associate_by_identity(ast, comments) if ast ast = find_block( ast, line ) options[:file] ||= file elsif Parser::AST::Node === source @@ -232,7 +232,7 @@ def self.convert(source, options={}) source = ast.loc.expression.source_buffer.source else ast, comments = parse( source, options[:file] ) - comments = ast ? Parser::Source::Comment.associate(ast, comments) : {} + comments = ast ? Parser::Source::Comment.associate_by_identity(ast, comments) : {} end # check if magic comment is present diff --git a/lib/ruby2js/converter.rb b/lib/ruby2js/converter.rb index e7d5e89..2f65665 100644 --- a/lib/ruby2js/converter.rb +++ b/lib/ruby2js/converter.rb @@ -203,6 +203,21 @@ def comments(ast) end end + def get_comments(ast) + result = [] + + if Parser::AST::Node === ast + ast.children.each do |child| + comment = @comments[child] + result << comment.map {|c| c.text }.first if comment&.size > 0 + more = get_comments(child) + result += more if more.size > 0 + end + end + + return result + end + def parse(ast, state=:expression) oldstate, @state = @state, state oldast, @ast = @ast, ast @@ -210,6 +225,11 @@ def parse(ast, state=:expression) handler = @handlers[ast.type] + if state == :statement + @comment = get_comments(ast).first&.strip + @pragma = @comment =~ /#\s+Pragma:\s*([^\s]+)/i ? $1.downcase : nil + end + unless handler raise Error.new("unknown AST type #{ ast.type }", ast) end diff --git a/lib/ruby2js/converter/logical.rb b/lib/ruby2js/converter/logical.rb index dcf3677..5e48899 100644 --- a/lib/ruby2js/converter/logical.rb +++ b/lib/ruby2js/converter/logical.rb @@ -15,6 +15,12 @@ class Converter handle :and, :or do |left, right| type = @ast.type + default_or = ' || ' + + if es2020 + # Override '||' and use '??' + default_or = ' ?? ' if @pragma == '??' + end if es2020 and type == :and node = rewrite(left, right) @@ -36,7 +42,7 @@ class Converter rgroup = true if right.type == :begin put '(' if lgroup; parse left; put ')' if lgroup - put (type==:and ? ' && ' : ((@or == :nullish and es2020) ? ' ?? ' : ' || ')) + put (type==:and ? ' && ' : ((@or == :nullish and es2020) ? ' ?? ' : default_or)) put '(' if rgroup; parse right; put ')' if rgroup end diff --git a/lib/ruby2js/converter/opasgn.rb b/lib/ruby2js/converter/opasgn.rb index 21057a6..cb158df 100644 --- a/lib/ruby2js/converter/opasgn.rb +++ b/lib/ruby2js/converter/opasgn.rb @@ -54,8 +54,15 @@ class Converter vtype = :ivar if asgn.type == :ivasgn vtype = :cvar if asgn.type == :cvasgn - if es2021 - op = type == :and ? '&&' : (@or == :nullish ? '??' : '||') + if es2020 + default_or = '||' + + if @pragma == '??' + # Override '||' and use '??' + default_or = '??' + end + + op = type == :and ? '&&' : (@or == :nullish ? '??' : default_or) parse s(:op_asgn, asgn, op, value); elsif vtype parse s(asgn.type, asgn.children.first, s(type, diff --git a/lib/ruby2js/converter/super.rb b/lib/ruby2js/converter/super.rb index b827963..5037916 100644 --- a/lib/ruby2js/converter/super.rb +++ b/lib/ruby2js/converter/super.rb @@ -24,23 +24,29 @@ class Converter end if es2015 + add_args = true + if @class_method parse @class_parent put '.' put method.children[0] + add_args = method.is_method? elsif method.children[0] == :constructor put 'super' else put 'super.' put method.children[0] + add_args = method.is_method? end - put '(' - cleaned_args = args.map do |arg| # FIX: #212 - arg.type == :optarg ? s(:arg, arg.children[0]) : arg + if add_args + put '(' + cleaned_args = args.map do |arg| # FIX: #212 + arg.type == :optarg ? s(:arg, arg.children[0]) : arg + end + parse s(:args, *cleaned_args) + put ')' end - parse s(:args, *cleaned_args) - put ')' else parse @class_parent