Commit d3644215 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Don't crash when getters and setters in JavaScript.

Make the RKellyAdapter correctly adapt the getters/setters into
properties of "get" and "set" kind.
parent 389a76de
Loading
Loading
Loading
Loading
+39 −23
Original line number Diff line number Diff line
@@ -216,32 +216,24 @@ module JsDuck
        when RKelly::Nodes::PropertyNode == node.class
          make(node, {
            "type" => "Property",
            "key" =>
              if node.name.is_a?(Numeric)
                {
                  "type" => "Literal",
                  "value" => node.name,
                  "raw" => node.name.to_s,
                  "range" => offset_range(node, :name),
                }
              elsif node.name =~ /['"]/
                {
                  "type" => "Literal",
                  "value" => string_value(node.name),
                  "raw" => node.name,
                  "range" => offset_range(node, :name),
                }
              else
                {
                  "type" => "Identifier",
                  "name" => node.name,
                  "range" => offset_range(node, :name),
                }
              end,
            "key" => property_key(node),
            "value" => adapt_node(node.value),
            "kind" => "init",
          })

        when RKelly::Nodes::GetterPropertyNode == node.class
          make(node, {
            "type" => "Property",
            "key" => property_key(node),
            "value" => adapt_node(node.value),
            "kind" => "get",
          })
        when RKelly::Nodes::SetterPropertyNode == node.class
          make(node, {
            "type" => "Property",
            "key" => property_key(node),
            "value" => adapt_node(node.value),
            "kind" => "set",
          })
        # Statements
        when RKelly::Nodes::ExpressionStatementNode == node.class
          make(node, {
@@ -458,6 +450,30 @@ module JsDuck
        }
      end

      def property_key(node)
        if node.name.is_a?(Numeric)
          {
            "type" => "Literal",
            "value" => node.name,
            "raw" => node.name.to_s,
            "range" => offset_range(node, :name),
          }
        elsif node.name =~ /['"]/
          {
            "type" => "Literal",
            "value" => string_value(node.name),
            "raw" => node.name,
            "range" => offset_range(node, :name),
          }
        else
          {
            "type" => "Identifier",
            "name" => node.name,
            "range" => offset_range(node, :name),
          }
        end
      end

      # Evaluates the actual value of a JavaScript string.
      # Importantly we avoid using Ruby's eval().
      def string_value(string)
+27 −1
Original line number Diff line number Diff line
@@ -93,9 +93,35 @@ describe JsDuck::Js::RKellyAdapter do
    end
  end

  def adapt_property(string)
    adapt(string)["expression"]["properties"][0]
  end

  describe "string properties" do
    it "don't use Ruby's eval()" do
      adapt('({"foo#$%": 5})')["expression"]["properties"][0]["key"]["value"].should == 'foo#$%'
      adapt_property('({"foo#$%": 5})')["key"]["value"].should == 'foo#$%'
    end
  end

  describe "getter property" do
    let(:property) { adapt_property('({get foo() { return this.x; } })') }

    it "gets parsed into get-kind" do
      property["kind"].should == 'get'
    end
    it "gets a function as its value" do
      property["value"]["type"].should == 'FunctionExpression'
    end
  end

  describe "setter property" do
    let(:property) { adapt_property('({set foo(x) { this.x = x; } })') }

    it "gets parsed into set-kind" do
      property["kind"].should == 'set'
    end
    it "gets a function as its value" do
      property["value"]["type"].should == 'FunctionExpression'
    end
  end