rbs 4.1.0.pre.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +37 -0
  3. data/.github/workflows/bundle-update.yml +1 -1
  4. data/.github/workflows/c-check.yml +11 -6
  5. data/.github/workflows/comments.yml +2 -2
  6. data/.github/workflows/dependabot.yml +1 -1
  7. data/.github/workflows/jruby.yml +15 -3
  8. data/.github/workflows/milestone.yml +9 -1
  9. data/.github/workflows/ruby.yml +4 -4
  10. data/.github/workflows/rust.yml +10 -8
  11. data/.github/workflows/truffleruby.yml +1 -1
  12. data/.github/workflows/typecheck.yml +2 -2
  13. data/.github/workflows/wasm.yml +4 -2
  14. data/.github/workflows/windows.yml +2 -2
  15. data/.gitignore +3 -2
  16. data/CHANGELOG.md +88 -0
  17. data/Dockerfile.jruby +53 -0
  18. data/Rakefile +16 -29
  19. data/Steepfile +2 -0
  20. data/core/array.rbs +228 -165
  21. data/core/float.rbs +0 -24
  22. data/core/match_data.rbs +1 -1
  23. data/core/pathname.rbs +0 -10
  24. data/core/ractor.rbs +0 -10
  25. data/core/rubygems/errors.rbs +4 -1
  26. data/core/rubygems/requirement.rbs +0 -10
  27. data/core/rubygems/rubygems.rbs +4 -1
  28. data/core/rubygems/specification.rbs +8 -0
  29. data/core/rubygems/version.rbs +0 -160
  30. data/core/thread.rbs +3 -8
  31. data/docs/CONTRIBUTING.md +1 -1
  32. data/docs/release.md +69 -0
  33. data/ext/rbs_extension/ast_translation.c +2 -2
  34. data/ext/rbs_extension/legacy_location.c +11 -6
  35. data/lib/rbs/parser_aux.rb +4 -2
  36. data/lib/rbs/prototype/rbi.rb +193 -25
  37. data/lib/rbs/version.rb +1 -1
  38. data/lib/rbs/wasm/runtime.rb +7 -28
  39. data/lib/rbs_jars.rb +39 -0
  40. data/lib/rdoc_plugin/parser.rb +5 -0
  41. data/rbs.gemspec +16 -3
  42. data/sig/prototype/rbi.rbs +33 -4
  43. data/src/lexer.c +97 -93
  44. data/src/lexer.re +1 -1
  45. data/src/lexstate.c +6 -2
  46. data/src/util/rbs_allocator.c +13 -4
  47. data/stdlib/delegate/0/delegator.rbs +2 -1
  48. data/stdlib/digest/0/digest.rbs +10 -4
  49. data/stdlib/erb/0/erb.rbs +1 -1
  50. data/stdlib/ipaddr/0/ipaddr.rbs +0 -5
  51. data/stdlib/monitor/0/monitor.rbs +2 -2
  52. data/stdlib/openssl/0/openssl.rbs +39 -33
  53. data/stdlib/tempfile/0/manifest.yaml +3 -0
  54. data/stdlib/timeout/0/timeout.rbs +0 -5
  55. data/stdlib/uri/0/generic.rbs +0 -5
  56. data/stdlib/zlib/0/zstream.rbs +0 -1
  57. data/wasm/README.md +4 -3
  58. data/wasm/rbs_wasm.c +12 -0
  59. metadata +6 -1
data/src/lexer.re CHANGED
@@ -58,7 +58,7 @@ rbs_token_t rbs_lexer_next_token(rbs_lexer_t *lexer) {
58
58
  "%a|" [^|\x00]* "|" { return rbs_next_token(lexer, tANNOTATION); }
59
59
  "%a<" [^>\x00]* ">" { return rbs_next_token(lexer, tANNOTATION); }
60
60
 
61
- "#" (. \ [\x00])* {
61
+ "#" (. \ [\x00\uFFFD])* {
62
62
  return rbs_next_token(
63
63
  lexer,
64
64
  lexer->first_token_of_line ? tLINECOMMENT : tCOMMENT
data/src/lexstate.c CHANGED
@@ -135,9 +135,13 @@ bool rbs_next_char(rbs_lexer_t *lexer, unsigned int *codepoint, size_t *byte_len
135
135
  *byte_len = lexer->encoding->char_width((const uint8_t *) start, (ptrdiff_t) (lexer->string.end - start));
136
136
 
137
137
  if (*byte_len == 0) {
138
- // Avoid infinite loop on invalid bytes.
138
+ // Invalid byte under the active encoding. Map it to a sentinel code
139
+ // point (U+FFFD) and advance one byte so the lexer always makes
140
+ // progress. Token rules that scan until a delimiter exclude this
141
+ // sentinel, so an invalid byte surfaces as an ErrorToken instead of
142
+ // being silently swallowed.
139
143
  *byte_len = 1;
140
- *codepoint = (unsigned int) (unsigned char) *start;
144
+ *codepoint = 0xFFFD;
141
145
  } else if (*byte_len == 1) {
142
146
  *codepoint = (unsigned int) *start;
143
147
  } else {
@@ -39,15 +39,24 @@ typedef struct rbs_allocator_page {
39
39
  size_t used;
40
40
  } rbs_allocator_page_t;
41
41
 
42
+ // Normalize a raw page size to a safe value for payload_size subtraction.
43
+ // Falls back to 4096 when the raw value is <= 0 or smaller than the page
44
+ // header struct, preventing underflow in rbs_allocator_init.
45
+ // Internal API, intentionally omitted from the public header.
46
+ size_t rbs_allocator_normalize_page_size(long raw) {
47
+ if (raw <= 0) return 4096;
48
+ size_t page_size = (size_t) raw;
49
+ if (page_size <= sizeof(rbs_allocator_page_t)) return 4096;
50
+ return page_size;
51
+ }
52
+
42
53
  static size_t get_system_page_size(void) {
43
54
  #ifdef _WIN32
44
55
  SYSTEM_INFO si;
45
56
  GetSystemInfo(&si);
46
- return si.dwPageSize;
57
+ return rbs_allocator_normalize_page_size((long) si.dwPageSize);
47
58
  #else
48
- long sz = sysconf(_SC_PAGESIZE);
49
- if (sz == -1) return 4096; // Fallback to the common 4KB page size
50
- return (size_t) sz;
59
+ return rbs_allocator_normalize_page_size(sysconf(_SC_PAGESIZE));
51
60
  #endif
52
61
  }
53
62
 
@@ -94,7 +94,7 @@ class Delegator < BasicObject
94
94
  # rdoc-file=lib/delegate.rb
95
95
  # - freeze()
96
96
  # -->
97
- # :method: freeze Freeze both the object returned by `__getobj__` and self.
97
+ # Freeze both the object returned by `__getobj__` and self.
98
98
  #
99
99
  def freeze: () -> self
100
100
 
@@ -118,6 +118,7 @@ class Delegator < BasicObject
118
118
  # rdoc-file=lib/delegate.rb
119
119
  # - method_missing(m, *args, &block)
120
120
  # -->
121
+ # Handles the magic of delegation through `__getobj__`.
121
122
  #
122
123
  def method_missing: (Symbol m, *untyped args, **untyped) { (*untyped, **untyped) -> untyped } -> untyped
123
124
 
@@ -536,13 +536,19 @@ class Digest::SHA2 < Digest::Class
536
536
  #
537
537
  def update: (String) -> self
538
538
 
539
- private def finish: () -> String
540
-
541
539
  # <!--
542
- # rdoc-file=ext/digest/sha2/lib/sha2.rb
543
- # - <<(str)
540
+ # rdoc-file=ext/digest/digest.c
541
+ # - digest_obj.instance_eval { finish } -> digest_obj
544
542
  # -->
543
+ # Finishes the digest and returns the resulting hash value.
545
544
  #
545
+ # This method is overridden by each implementation subclass and often made
546
+ # private, because some of those subclasses may leave internal data
547
+ # uninitialized. Do not call this method from outside. Use #digest!() instead,
548
+ # which ensures that internal data be reset for security reasons.
549
+ #
550
+ private def finish: () -> String
551
+
546
552
  alias << update
547
553
 
548
554
  # <!--
data/stdlib/erb/0/erb.rbs CHANGED
@@ -633,7 +633,7 @@ class ERB
633
633
  # # => "The time is 2025-09-18 15:58:08 -0500."
634
634
  #
635
635
  # In a more readable format:
636
- # # puts erb.src.split('; ')
636
+ # # puts erb.src.split('; ')
637
637
  # # #coding:UTF-8
638
638
  # # _erbout = +''
639
639
  # # _erbout.<< "The time is ".freeze
@@ -98,11 +98,6 @@ class IPAddr
98
98
  #
99
99
  def ==: (untyped other) -> bool
100
100
 
101
- # <!--
102
- # rdoc-file=lib/ipaddr.rb
103
- # - ===(other)
104
- # -->
105
- #
106
101
  alias === include?
107
102
 
108
103
  # <!--
@@ -338,7 +338,7 @@ class MonitorMixin::ConditionVariable
338
338
 
339
339
  # <!--
340
340
  # rdoc-file=ext/monitor/lib/monitor.rb
341
- # - wait_until()
341
+ # - wait_until() { || ... }
342
342
  # -->
343
343
  # Calls wait repeatedly until the given block yields a truthy value.
344
344
  #
@@ -346,7 +346,7 @@ class MonitorMixin::ConditionVariable
346
346
 
347
347
  # <!--
348
348
  # rdoc-file=ext/monitor/lib/monitor.rb
349
- # - wait_while()
349
+ # - wait_while() { || ... }
350
350
  # -->
351
351
  # Calls wait repeatedly while the given block yields a truthy value.
352
352
  #
@@ -5913,10 +5913,17 @@ module OpenSSL
5913
5913
  def initialize_copy: (self) -> void
5914
5914
  end
5915
5915
 
5916
- # <!-- rdoc-file=ext/openssl/ossl_pkey_dh.c -->
5917
- # Generic exception that is raised if an operation on a DH PKey fails
5918
- # unexpectedly or in case an instantiation of an instance of DH fails due to
5919
- # non-conformant input data.
5916
+ # <!-- rdoc-file=ext/openssl/ossl_pkey.c -->
5917
+ # Raised when errors occur during PKey#sign or PKey#verify.
5918
+ #
5919
+ # Before version 4.0.0, OpenSSL::PKey::PKeyError had the following subclasses.
5920
+ # These subclasses have been removed and the constants are now defined as
5921
+ # aliases of OpenSSL::PKey::PKeyError.
5922
+ #
5923
+ # * OpenSSL::PKey::DHError
5924
+ # * OpenSSL::PKey::DSAError
5925
+ # * OpenSSL::PKey::ECError
5926
+ # * OpenSSL::PKey::RSAError
5920
5927
  #
5921
5928
  class DHError < OpenSSL::PKey::PKeyError
5922
5929
  end
@@ -6304,10 +6311,17 @@ module OpenSSL
6304
6311
  def initialize_copy: (self) -> void
6305
6312
  end
6306
6313
 
6307
- # <!-- rdoc-file=ext/openssl/ossl_pkey_dsa.c -->
6308
- # Generic exception that is raised if an operation on a DSA PKey fails
6309
- # unexpectedly or in case an instantiation of an instance of DSA fails due to
6310
- # non-conformant input data.
6314
+ # <!-- rdoc-file=ext/openssl/ossl_pkey.c -->
6315
+ # Raised when errors occur during PKey#sign or PKey#verify.
6316
+ #
6317
+ # Before version 4.0.0, OpenSSL::PKey::PKeyError had the following subclasses.
6318
+ # These subclasses have been removed and the constants are now defined as
6319
+ # aliases of OpenSSL::PKey::PKeyError.
6320
+ #
6321
+ # * OpenSSL::PKey::DHError
6322
+ # * OpenSSL::PKey::DSAError
6323
+ # * OpenSSL::PKey::ECError
6324
+ # * OpenSSL::PKey::RSAError
6311
6325
  #
6312
6326
  class DSAError < OpenSSL::PKey::PKeyError
6313
6327
  end
@@ -7011,6 +7025,18 @@ module OpenSSL
7011
7025
  end
7012
7026
  end
7013
7027
 
7028
+ # <!-- rdoc-file=ext/openssl/ossl_pkey.c -->
7029
+ # Raised when errors occur during PKey#sign or PKey#verify.
7030
+ #
7031
+ # Before version 4.0.0, OpenSSL::PKey::PKeyError had the following subclasses.
7032
+ # These subclasses have been removed and the constants are now defined as
7033
+ # aliases of OpenSSL::PKey::PKeyError.
7034
+ #
7035
+ # * OpenSSL::PKey::DHError
7036
+ # * OpenSSL::PKey::DSAError
7037
+ # * OpenSSL::PKey::ECError
7038
+ # * OpenSSL::PKey::RSAError
7039
+ #
7014
7040
  class ECError < OpenSSL::PKey::PKeyError
7015
7041
  end
7016
7042
 
@@ -9282,6 +9308,7 @@ module OpenSSL
9282
9308
  # rdoc-file=ext/openssl/ossl_ssl.c
9283
9309
  # - SSLSocket.new(io) => aSSLSocket
9284
9310
  # - SSLSocket.new(io, ctx) => aSSLSocket
9311
+ # - SSLSocket.new(io, ctx, sync_close:) => aSSLSocket
9285
9312
  # -->
9286
9313
  # Creates a new SSL socket from *io* which must be a real IO object (not an
9287
9314
  # IO-like object that responds to read/write).
@@ -9289,6 +9316,10 @@ module OpenSSL
9289
9316
  # If *ctx* is provided the SSL Sockets initial params will be taken from the
9290
9317
  # context.
9291
9318
  #
9319
+ # The optional *sync_close* keyword parameter sets the *sync_close* instance
9320
+ # variable. Setting this to `true` will cause the underlying socket to be closed
9321
+ # when the SSL/TLS connection is shut down.
9322
+ #
9292
9323
  # The OpenSSL::Buffering module provides additional IO methods.
9293
9324
  #
9294
9325
  # This method will freeze the SSLContext if one is provided; however, session
@@ -10390,11 +10421,6 @@ module OpenSSL
10390
10421
 
10391
10422
  extend OpenSSL::Marshal::ClassMethods
10392
10423
 
10393
- # <!--
10394
- # rdoc-file=ext/openssl/lib/openssl/x509.rb
10395
- # - ==(other)
10396
- # -->
10397
- #
10398
10424
  def ==: (self other) -> bool
10399
10425
 
10400
10426
  # <!--
@@ -10462,11 +10488,6 @@ module OpenSSL
10462
10488
 
10463
10489
  extend OpenSSL::Marshal::ClassMethods
10464
10490
 
10465
- # <!--
10466
- # rdoc-file=ext/openssl/lib/openssl/x509.rb
10467
- # - ==(other)
10468
- # -->
10469
- #
10470
10491
  def ==: (self other) -> bool
10471
10492
 
10472
10493
  # <!--
@@ -10982,11 +11003,6 @@ module OpenSSL
10982
11003
 
10983
11004
  extend OpenSSL::Marshal::ClassMethods
10984
11005
 
10985
- # <!--
10986
- # rdoc-file=ext/openssl/lib/openssl/x509.rb
10987
- # - ==(other)
10988
- # -->
10989
- #
10990
11006
  def ==: (self other) -> bool
10991
11007
 
10992
11008
  # <!--
@@ -11610,11 +11626,6 @@ module OpenSSL
11610
11626
 
11611
11627
  extend OpenSSL::Marshal::ClassMethods
11612
11628
 
11613
- # <!--
11614
- # rdoc-file=ext/openssl/lib/openssl/x509.rb
11615
- # - ==(other)
11616
- # -->
11617
- #
11618
11629
  def ==: (untyped other) -> bool
11619
11630
 
11620
11631
  # <!--
@@ -11755,11 +11766,6 @@ module OpenSSL
11755
11766
  end
11756
11767
 
11757
11768
  class Revoked
11758
- # <!--
11759
- # rdoc-file=ext/openssl/lib/openssl/x509.rb
11760
- # - ==(other)
11761
- # -->
11762
- #
11763
11769
  def ==: (untyped other) -> bool
11764
11770
 
11765
11771
  # <!--
@@ -0,0 +1,3 @@
1
+ dependencies:
2
+ - name: delegate
3
+ - name: tmpdir
@@ -109,11 +109,6 @@ module Timeout
109
109
  # If you want the timeout to only happen on blocking operations one can use
110
110
  # :on_blocking instead of :immediate. However, that means if the block uses no
111
111
  # blocking operations after `sec` seconds, the block will not be interrupted.
112
- # ----
113
- # <!--
114
- # rdoc-file=lib/timeout.rb
115
- # - timeout(*args, &block)
116
- # -->
117
112
  #
118
113
  def self?.timeout: [T] (Numeric? sec, ?singleton(Exception) klass, ?String message) { (Numeric sec) -> T } -> T
119
114
  end
@@ -909,11 +909,6 @@ module URI
909
909
  #
910
910
  def merge: (URI::Generic | string oth) -> URI::Generic
911
911
 
912
- # <!--
913
- # rdoc-file=lib/uri/generic.rb
914
- # - +(oth)
915
- # -->
916
- #
917
912
  alias + merge
918
913
 
919
914
  # :stopdoc:
@@ -153,7 +153,6 @@ module Zlib
153
153
  # rdoc-file=ext/zlib/zlib.c
154
154
  # - flush_next_in -> input
155
155
  # -->
156
- # Flushes input buffer and returns all data in that buffer.
157
156
  #
158
157
  def flush_next_in: () -> String
159
158
 
data/wasm/README.md CHANGED
@@ -19,9 +19,10 @@ The build needs the [WASI SDK](https://github.com/WebAssembly/wasi-sdk/releases)
19
19
 
20
20
  ```console
21
21
  $ export WASI_SDK_PATH=/path/to/wasi-sdk
22
- $ rake wasm:build # compile rbs_parser.wasm
23
- $ rake wasm:check # also smoke-test it (needs wasmtime)
24
- $ rake wasm:jruby_setup # assemble lib/rbs/wasm/ for JRuby (wasm + Chicory jars)
22
+ $ rake wasm:build # compile rbs_parser.wasm
23
+ $ rake wasm:check # also smoke-test it (needs wasmtime)
24
+ $ rake wasm:jruby_setup # copy rbs_parser.wasm into lib/rbs/wasm/ for JRuby
25
+ $ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 (run on JRuby)
25
26
  ```
26
27
 
27
28
  The compiled `rbs_parser.wasm` is a build artifact and is not checked in.
data/wasm/rbs_wasm.c CHANGED
@@ -399,7 +399,19 @@ __attribute__((export_name("rbs_wasm_lex"))) int rbs_wasm_lex(const char *source
399
399
  *
400
400
  * @return 1 if the sample parsed successfully, 0 otherwise.
401
401
  */
402
+ // Internal: defined in rbs_allocator.c, not declared in the public header.
403
+ extern size_t rbs_allocator_normalize_page_size(long raw);
404
+
402
405
  __attribute__((export_name("rbs_wasm_selftest"))) int rbs_wasm_selftest(void) {
406
+ // Regression test: normalize_page_size must return a safe value
407
+ // (>= sizeof(rbs_allocator_page_t)) for inputs that would underflow
408
+ // payload_size. On WASI in a Rust cdylib, sysconf(_SC_PAGESIZE)
409
+ // returns 0; the normalization must catch that.
410
+ if (rbs_allocator_normalize_page_size(-1) != 4096) return 0;
411
+ if (rbs_allocator_normalize_page_size(0) != 4096) return 0;
412
+ if (rbs_allocator_normalize_page_size(1) != 4096) return 0;
413
+ if (rbs_allocator_normalize_page_size(65536) != 65536) return 0;
414
+
403
415
  static const char source[] =
404
416
  "class User\n"
405
417
  " attr_reader name: String\n"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbs
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0.pre.2
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
@@ -63,6 +63,7 @@ extra_rdoc_files: []
63
63
  files:
64
64
  - ".clang-format"
65
65
  - ".clangd"
66
+ - ".dockerignore"
66
67
  - ".github/dependabot.yml"
67
68
  - ".github/workflows/bundle-update.yml"
68
69
  - ".github/workflows/c-check.yml"
@@ -81,6 +82,7 @@ files:
81
82
  - BSDL
82
83
  - CHANGELOG.md
83
84
  - COPYING
85
+ - Dockerfile.jruby
84
86
  - README.md
85
87
  - Rakefile
86
88
  - Steepfile
@@ -184,6 +186,7 @@ files:
184
186
  - docs/gem.md
185
187
  - docs/inline.md
186
188
  - docs/rbs_by_example.md
189
+ - docs/release.md
187
190
  - docs/repo.md
188
191
  - docs/rust.md
189
192
  - docs/sigs.md
@@ -326,6 +329,7 @@ files:
326
329
  - lib/rbs/wasm/runtime.rb
327
330
  - lib/rbs/wasm/serialization_schema.rb
328
331
  - lib/rbs/writer.rb
332
+ - lib/rbs_jars.rb
329
333
  - lib/rdoc/discover.rb
330
334
  - lib/rdoc_plugin/parser.rb
331
335
  - rbs.gemspec
@@ -579,6 +583,7 @@ files:
579
583
  - stdlib/socket/0/unix_socket.rbs
580
584
  - stdlib/stringio/0/stringio.rbs
581
585
  - stdlib/strscan/0/string_scanner.rbs
586
+ - stdlib/tempfile/0/manifest.yaml
582
587
  - stdlib/tempfile/0/tempfile.rbs
583
588
  - stdlib/time/0/time.rbs
584
589
  - stdlib/timeout/0/timeout.rbs