From 48d4847e340ba2a809cac855c2273a6cc814a5ab Mon Sep 17 00:00:00 2001 From: Rene Saarsoo Date: Wed, 31 Jul 2013 12:43:05 +0300 Subject: [PATCH] Auto-detect @readonly from Object.defineProperty. --- lib/jsduck/js/method.rb | 2 +- lib/jsduck/js/node.rb | 8 ++++-- lib/jsduck/js/property.rb | 13 ++++----- lib/jsduck/tag/property.rb | 1 + spec/aggregator_readonly_spec.rb | 47 ++++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/lib/jsduck/js/method.rb b/lib/jsduck/js/method.rb index 4c7a93d5..60bd9b54 100644 --- a/lib/jsduck/js/method.rb +++ b/lib/jsduck/js/method.rb @@ -38,7 +38,7 @@ module JsDuck make(ast["key"].key_value, ast["value"]) # Object.defineProperty(obj, "prop", {value: function() {} }) - elsif exp && (value = exp.value_of_define_property) && detect(value) + elsif exp && (value = exp.object_descriptor("value")) && detect(value) name = exp["arguments"][1].to_value make(name, value) diff --git a/lib/jsduck/js/node.rb b/lib/jsduck/js/node.rb index 8adf9886..8e4da8ed 100644 --- a/lib/jsduck/js/node.rb +++ b/lib/jsduck/js/node.rb @@ -120,15 +120,17 @@ module JsDuck end end - # Returns the value field from Object.defineProperty call + # Returns value of a given field from Object.defineProperty call # descriptor object. - def value_of_define_property + def object_descriptor(descriptor_key) return unless define_property? descriptor = child("arguments")[2] descriptor.each_property do |key, value, prop| - return value if key == "value" + return value if key == descriptor_key end + + return nil end # Returns line number in parsed source where the Node resides. diff --git a/lib/jsduck/js/property.rb b/lib/jsduck/js/property.rb index 0a0aa0a7..b089fa07 100644 --- a/lib/jsduck/js/property.rb +++ b/lib/jsduck/js/property.rb @@ -41,7 +41,9 @@ module JsDuck # Object.defineProperty(obj, "prop", {value: x}) elsif exp && exp.define_property? name = exp["arguments"][1].to_value - make(name, exp.value_of_define_property) + writable = exp.object_descriptor("writable") + readonly = writable ? !writable.to_value : true + make(name, exp.object_descriptor("value"), readonly) else nil @@ -49,12 +51,13 @@ module JsDuck end # Produces a doc-hash for a property. - def make(name=nil, ast=nil) + def make(name=nil, ast=nil, readonly=nil) return { :tagname => :property, :name => name, :type => ast && ast.value_type, :default => ast && default(ast), + :readonly => readonly, } end @@ -64,12 +67,6 @@ module JsDuck ast.to_value != nil ? ast.to_s : nil end - def value_from_descriptor(descriptor) - descriptor.each_property do |key, value, prop| - return value if key == "value" - end - end - end end end diff --git a/lib/jsduck/tag/property.rb b/lib/jsduck/tag/property.rb index 49da1fee..50aec75c 100644 --- a/lib/jsduck/tag/property.rb +++ b/lib/jsduck/tag/property.rb @@ -49,6 +49,7 @@ module JsDuck::Tag h = super(code) h[:type] = code[:type] h[:default] = code[:default] + h[:readonly] = code[:readonly] h end diff --git a/spec/aggregator_readonly_spec.rb b/spec/aggregator_readonly_spec.rb index 98e974e2..7d5e7785 100644 --- a/spec/aggregator_readonly_spec.rb +++ b/spec/aggregator_readonly_spec.rb @@ -19,4 +19,51 @@ describe JsDuck::Aggregator do end end + describe "Object.defineProperty with writable:true" do + let(:doc) do + parse_member(<<-EOS) + /** */ + Object.defineProperty(this, 'myCfg', { + value: 5, + writable: true + }); + EOS + end + + it "doesn't get readonly attribute" do + doc[:readonly].should_not == true + end + end + + describe "Object.defineProperty with writable:false" do + let(:doc) do + parse_member(<<-EOS) + /** */ + Object.defineProperty(this, 'myCfg', { + value: 5, + writable: false + }); + EOS + end + + it "gets readonly attribute" do + doc[:readonly].should == true + end + end + + describe "Object.defineProperty without writable:" do + let(:doc) do + parse_member(<<-EOS) + /** */ + Object.defineProperty(this, 'myCfg', { + value: 5 + }); + EOS + end + + it "gets readonly attribute" do + doc[:readonly].should == true + end + end + end -- GitLab