diff --git a/lib/jsduck/js/method.rb b/lib/jsduck/js/method.rb index 4c7a93d5338433d62d384250f88278d0b768836f..60bd9b5486b187a21adf6af97dfd4d777ae84df1 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 8adf9886bd35d42b37369a9d9fd1d544dfc408ee..8e4da8edcf32fd1238d8e7bc46afbcd1552dade3 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 0a0aa0a731773d26193f6fcb698184102d0d7172..b089fa072dbe8450912754ca924ece367f514581 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 49da1fee1bde832afc6aa7b8c42e89a9fe37793b..50aec75c32ddc6caf89c9dde2b7b45a8c208d5f4 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 98e974e278708a317e0202a82fc294a320d30074..7d5e7785774c0222b583beaf87accd603ea6c707 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