Skip to content

[Ruby] optional field's presence checker method has_...? is broken on JRuby and has cosmetic issue on MRI #18807

@ntkme

Description

@ntkme

What version of protobuf and what language are you using?
Version: 4.28.2
Language: Ruby

What operating system (Linux, Windows, ...) and version?

All operating systems.

What runtime / compiler are you using (e.g., python version or gcc version)

Ruby 3.3.5 / JRuby 9.4.8.0

What did you do?

Protobuf definition: https://github.com/sass/sass/blob/eba0a58b46788b893983c2886c1be3b9c2d260e1/spec/embedded_sass.proto#L807-L834

Test code:

require_relative 'embedded_sass_pb'

value = Sass::EmbeddedProtocol::Value::Color.new(
  space: 'rgb',
  channel1: 0, # this is an optional field
  channel2: 0, # this is an optional field
  channel3: 0, # this is an optional field
  alpha: nil # this is an optional field
)

# Note, the JRuby bug only occurs on a deserialized object. `.new` created objects have no issue. 
value = Sass::EmbeddedProtocol::Value::Color.decode(value.to_proto)

puts "  value.has_channel1? = #{value.has_channel1?}" # <- should return true
puts "  value.has_alpha?    = #{value.has_alpha?}" # <- should return false
puts "==="
puts value.to_s # <- note that the behavior changes on JRuby before and after this call
puts "==="
puts "  value.has_channel1? = #{value.has_channel1?}"  # <- should return true
puts "  value.has_alpha?    = #{value.has_alpha?}" # <- should return false

What did you expect to see

  value.has_channel1? = true
  value.has_alpha?    = false
===
<Sass::EmbeddedProtocol::Value::Color: space: "rgb", channel1: 0.0, channel2: 0.0, channel3: 0.0>
===
  value.has_channel1? = true
  value.has_alpha?    = false

What did you see instead?

MRI

.has_...? returns 0 instead of true. Note: 0 in ruby is considered as truthy, so this is just a cosmetic issue in MRI.

  value.has_channel1? = 0
  value.has_alpha?    = false
===
<Sass::EmbeddedProtocol::Value::Color: space: "rgb", channel1: 0.0, channel2: 0.0, channel3: 0.0>
===
  value.has_channel1? = 0
  value.has_alpha?    = false

JRuby

.has_...? always return false, until .to_s is called on the object. Somehow calling .to_s changes behavior of .has_...?, that after the call .has_...? returns the expected value.

  value.has_channel1? = false
  value.has_alpha?    = false
===
<Sass::EmbeddedProtocol::Value::Color: space: "rgb", channel1: 0.0, channel2: 0.0, channel3: 0.0>
===
  value.has_channel1? = true
  value.has_alpha?    = false

Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs).

Anything else we should know about your project / environment
sass-contrib/sass-embedded-host-ruby#246

Metadata

Metadata

Assignees

Labels

jrubyIssues unique to the JRuby interpreter

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions