@@ -33,31 +33,45 @@ def self.frozen_validated_illegal_calls(illegal_calls)
3333 end . freeze
3434 end
3535
36- # Illegal calls are Hash[String, Hash[Symbol, Bool]]
36+ # Illegal calls are Hash[String, :all | Hash[Symbol, Bool]]
3737 def initialize ( illegal_calls )
3838 @tracepoint = TracePoint . new ( :call , :c_call ) do |tp |
3939 cls = tp . defined_class
4040 next unless cls . is_a? ( Module )
4141
42- # We need this to be quick so we don't do extra validations to satisfy type checker
43- # steep:ignore:start
44- if cls . singleton_class?
45- cls = cls . attached_object
46- next unless cls . is_a? ( Module )
47- end
48- vals = illegal_calls [ cls . name ]
49- if vals == :all || vals &.[]( tp . callee_id )
42+ # Extract the class name from the defined class. This is more difficult than it seems because you have to
43+ # resolve the attached object of the singleton class. But in older Ruby (at least <= 3.1), the singleton
44+ # class of things like `Date` does not have `attached_object` so you have to fall back in these rare cases
45+ # to parsing the string output. Reaching the string parsing component is rare, so this should not have
46+ # significant performance impact.
47+ cls_name = if cls . singleton_class?
48+ if cls . respond_to? ( :attached_object )
49+ cls = cls . attached_object # steep:ignore
50+ next unless cls . is_a? ( Module )
51+
52+ cls . name . to_s
53+ else
54+ cls . to_s . delete_prefix ( '#<Class:' ) . delete_suffix ( '>' )
55+ end
56+ else
57+ cls . name . to_s
58+ end
59+
60+ # Check if the call is considered illegal
61+ vals = illegal_calls [ cls_name ]
62+ if vals == :all || vals &.[]( tp . callee_id ) # steep:ignore
5063 raise Workflow ::NondeterminismError ,
51- "Cannot access #{ cls . name } #{ tp . callee_id } from inside a " \
64+ "Cannot access #{ cls_name } #{ tp . callee_id } from inside a " \
5265 'workflow. If this is known to be safe, the code can be run in ' \
5366 'a Temporalio::Workflow::Unsafe.illegal_call_tracing_disabled block.'
5467 end
55- # steep:ignore:end
5668 end
5769 end
5870
5971 def enable ( &)
60- @tracepoint . enable ( &)
72+ # Setting current thread explicitly because it wasn't until Ruby 3.2 that this
73+ # was done automatically, ref https://github.com/ruby/ruby/pull/5359
74+ @tracepoint . enable ( target_thread : Thread . current , &)
6175 end
6276
6377 def disable ( &)
0 commit comments