@@ -115,6 +115,26 @@ def test_regexp_linear_time_no_leak_without_keyword
115115 assert_equal [ 1 , 2 ] , [ v . a , v . k ]
116116 end
117117
118+ # ── Regexp#initialize keyword handling ───────────────────────────
119+
120+ def test_regexp_initialize_with_timeout_keyword
121+ # 2-arg form: Regexp.new(source, timeout: val)
122+ re = Regexp . new ( "abc" , timeout : 1.0 )
123+ assert_match re , "abc"
124+
125+ v = KwargsReceiver . new ( 1 , k : 2 )
126+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
127+ end
128+
129+ def test_regexp_initialize_3arg_with_timeout_keyword
130+ # 3-arg form: Regexp.new(source, flags, timeout: val)
131+ re = Regexp . new ( "abc" , Regexp ::IGNORECASE , timeout : 1.0 )
132+ assert_match re , "ABC"
133+
134+ v = KwargsReceiver . new ( 1 , k : 2 )
135+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
136+ end
137+
118138 # ── ARGF keyword handling ──────────────────────────────────────────
119139
120140 def test_argf_readlines_chomp_keyword
@@ -213,6 +233,160 @@ def test_to_enum_without_keywords_does_not_leak
213233 assert_equal [ 1 , 2 ] , [ v . a , v . k ]
214234 end
215235
236+ # ── Data class keyword handling ────────────────────────────────────
237+
238+ def test_data_new_with_keywords
239+ d = Data . define ( :x , :y )
240+ instance = d . new ( x : 1 , y : 2 )
241+ assert_equal 1 , instance . x
242+ assert_equal 2 , instance . y
243+
244+ v = KwargsReceiver . new ( 1 , k : 2 )
245+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
246+ end
247+
248+ def test_data_new_single_member_with_keyword
249+ d = Data . define ( :x )
250+ instance = d . new ( x : 42 )
251+ assert_equal 42 , instance . x
252+
253+ v = KwargsReceiver . new ( 1 , k : 2 )
254+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
255+ end
256+
257+ def test_data_with_keyword
258+ d = Data . define ( :x , :y )
259+ original = d . new ( x : 1 , y : 2 )
260+ updated = original . with ( x : 10 )
261+ assert_equal 10 , updated . x
262+ assert_equal 2 , updated . y
263+
264+ v = KwargsReceiver . new ( 1 , k : 2 )
265+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
266+ end
267+
268+ # ── Dir.glob / Dir[] keyword handling ──────────────────────────────
269+
270+ def test_dir_glob_with_sort_keyword
271+ entries = Dir . glob ( "*" , sort : true )
272+ assert_kind_of Array , entries
273+
274+ v = KwargsReceiver . new ( 1 , k : 2 )
275+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
276+ end
277+
278+ def test_dir_aref_does_not_leak
279+ Dir [ "*" ]
280+
281+ v = KwargsReceiver . new ( 1 , k : 2 )
282+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
283+ end
284+
285+ # ── Proc#parameters keyword handling ───────────────────────────────
286+
287+ def test_proc_parameters_with_lambda_keyword
288+ pr = Proc . new { |a , k :| }
289+ params = pr . parameters ( lambda : true )
290+ assert_equal [ [ :req , :a ] , [ :keyreq , :k ] ] , params
291+
292+ v = KwargsReceiver . new ( 1 , k : 2 )
293+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
294+ end
295+
296+ def test_proc_parameters_without_keyword
297+ pr = Proc . new { |a , k :| }
298+ params = pr . parameters
299+ assert_include params , [ :opt , :a ]
300+ assert_include params , [ :keyreq , :k ]
301+
302+ v = KwargsReceiver . new ( 1 , k : 2 )
303+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
304+ end
305+
306+ # ── Warning.warn keyword handling ──────────────────────────────────
307+
308+ def test_warning_warn_with_category_keyword
309+ # Warning.warn 2-arg form accepts category: keyword
310+ assert_nothing_raised do
311+ Warning . warn ( "test callinfo message\n " , category : :deprecated )
312+ end
313+
314+ v = KwargsReceiver . new ( 1 , k : 2 )
315+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
316+ end
317+
318+ # ── IO.foreach keyword handling ────────────────────────────────────
319+
320+ def test_io_foreach_chomp_keyword
321+ tmpfile = Tempfile . new ( 'test_call_info_foreach' )
322+ tmpfile . write ( "hello\n world\n " )
323+ tmpfile . close
324+
325+ lines = [ ]
326+ IO . foreach ( tmpfile . path , chomp : true ) { |l | lines << l }
327+ assert_equal [ "hello" , "world" ] , lines
328+
329+ v = KwargsReceiver . new ( 1 , k : 2 )
330+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
331+ ensure
332+ tmpfile . unlink if tmpfile
333+ end
334+
335+ # ── File#initialize keyword handling ────────────────────────────────
336+
337+ def test_file_open_with_mode_keyword
338+ tmpfile = Tempfile . new ( 'test_call_info_file' )
339+ tmpfile . write ( "file content" )
340+ tmpfile . close
341+
342+ f = File . open ( tmpfile . path , mode : "r" )
343+ assert_equal "file content" , f . read
344+ f . close
345+
346+ v = KwargsReceiver . new ( 1 , k : 2 )
347+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
348+ ensure
349+ tmpfile . unlink if tmpfile
350+ end
351+
352+ def test_file_open_with_fd_and_mode_keyword
353+ tmpfile = Tempfile . new ( 'test_call_info_file_fd' )
354+ tmpfile . write ( "fd content" )
355+ tmpfile . close
356+
357+ # Open via path first, then reopen via fd to exercise the fd delegation path
358+ original = File . open ( tmpfile . path , "r" )
359+ fd_file = IO . new ( original . fileno , mode : "r" , autoclose : false )
360+ assert_equal "fd content" , fd_file . read
361+ fd_file . close
362+ original . close
363+
364+ v = KwargsReceiver . new ( 1 , k : 2 )
365+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
366+ ensure
367+ tmpfile . unlink if tmpfile
368+ end
369+
370+ # ── NoMatchingPatternKeyError keyword handling ─────────────────────
371+
372+ def test_no_matching_pattern_key_error_with_keywords
373+ err = NoMatchingPatternKeyError . new ( "test" , matchee : { a : 1 } , key : :b )
374+ assert_equal "test" , err . message
375+ assert_equal ( { a : 1 } , err . matchee )
376+ assert_equal :b , err . key
377+
378+ v = KwargsReceiver . new ( 1 , k : 2 )
379+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
380+ end
381+
382+ def test_no_matching_pattern_key_error_without_keywords
383+ err = NoMatchingPatternKeyError . new ( "test" )
384+ assert_equal "test" , err . message
385+
386+ v = KwargsReceiver . new ( 1 , k : 2 )
387+ assert_equal [ 1 , 2 ] , [ v . a , v . k ]
388+ end
389+
216390 # ── General: keywords after non-keyword calls ──────────────────────
217391
218392 def test_keywords_work_after_various_calls
0 commit comments