Commit graph

20692 commits

Author SHA1 Message Date
Jean Boussier
e626da82ea Don't pin named structs defined in Ruby
[Bug #20311]

`rb_define_class_under` assumes it's called from C and that the
reference might be held in a C global variable, so it adds the
class to the VM root.

In the case of `Struct.new('Name')` it's wasteful and make
the struct immortal.
2024-03-01 08:23:38 +01:00
Nobuyoshi Nakada
5d76fe6b2a [ruby/optparse] Invoke pager for --help
77dccce37c
2024-03-01 07:10:08 +00:00
Nobuyoshi Nakada
452d51ffe1
Use File.open and File.write instead of Kernel#open 2024-03-01 13:11:29 +09:00
Kasumi Hanazuki
2508a79699 [ruby/resolv] Implement CAA resource record
This patch implements handling of CAA resource records defined by [RFC8659].

- There are no known deployment of CAA records outside of IN (Internet),
  but the RFC does not state that CAA records are class-specific.
  Thus `CAA` class is defined as a class-independent RRType.
- `CAA` class stores `flags` field (a 1-octet bitset) as an Integer.
  In this way it's easier to ensure the encoded RR is in the valid wire format.

[RFC8659]: https://datatracker.ietf.org/doc/html/rfc8659

cfc4de75e3

Co-authored-by: aeris <aeris@imirhil.fr>
2024-02-29 20:55:26 +00:00
Kevin Newton
1c0c490aa0 [ruby/prism] Warn on integers in flip-flops
500099e896
2024-02-29 17:32:37 +00:00
Kevin Newton
50e999c56d [ruby/prism] Command line options as a bitset
369ffbd57e
2024-02-29 12:05:19 -05:00
Kevin Newton
cd8d1018bb [ruby/prism] Resync RBI and test it in CI
4ef4032774
2024-02-29 16:29:16 +00:00
Koichi ITO
f8dd2342bf [ruby/prism] Fix an incorrect parsing for Prism::Translation::Parser
This PR fixes an incorrect parsing for `Prism::Translation::Parser`
when one-line pattern mathing with Ruby 2.7 runtime.

## Expected

Parsing should be done based on the specified Ruby parsing version,
independent of the Ruby runtime version. When parsing for Ruby 3.3,
it should return `:match_pattern_p` node:

```console
$ ruby -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("foo in bar")'
ruby 3.0.6p216 (2023-03-30 revision 23a532679b) [x86_64-darwin19]
s(:match_pattern_p,
s(:send, nil, :foo),
  s(:match_var, :bar))
```

## Actual

When parsing with Ruby 2.7 runtime, `match_pattern` node is returned,
even though it is expected to parse for Ruby 3.3:

```console
$ ruby -rprism -rprism/translation/parser33 -ve 'p Prism::Translation::Parser33.parse("foo in bar")'
ruby 2.7.8p225 (2023-03-30 revision 1f4d455848) [x86_64-darwin19]
s(:match_pattern,
s(:send, nil, :foo),
  s(:match_var, :bar))
```

The cause was the use of `RUBY_VERSION` for condition logic,
which made it dependent on runtime Ruby version.
`Prism::Translation::Parser` supports parsing for Ruby 3.3+.
Therefore, the condition for parsing Ruby 2.7, which is not supported, is being removed.

## Background

Found due to incompatibility with RuboCop's `Layout/SpaceAroundKeyword` and `Style/TernaryParentheses` cops.

e752e251d2
2024-02-29 16:06:40 +00:00
Nobuyoshi Nakada
eb6eb1d4e8
Fix crash report path test on Windows 2024-02-28 17:53:02 +09:00
Nobuyoshi Nakada
8316cb213c
Fix to use assert_crash_report results 2024-02-28 16:09:07 +09:00
Hiroshi SHIBATA
05387b590b Update regex patterns with rbinstall.rb 2024-02-28 13:30:16 +09:00
Hiroshi SHIBATA
47b46fd98c
Use dummy command for IO.popen 2024-02-28 11:14:48 +09:00
Hiroshi SHIBATA
95e55e9ae4
Also ignore git ls-files command with IO.popen style for tmpdir.gemspec and tempfile.gemspec 2024-02-28 11:08:49 +09:00
Kevin Newton
fc36882713 [ruby/prism] Ensure symbol nodes not in interpolated symbol
e1a9a1d478
2024-02-27 16:05:02 +00:00
Shugo Maeda
d50f9ca2dd [Bug #20302] Multiple refinements cannot be applied to the same module
In the following code, the iclass tree of refinements in cref should be <iclass of Kernel@M2> -> <iclass of Kernel@M1> -> Kernel.

However, the iclass tree was broken because of code for included modules of refinements in rb_using_refinement().
Refinement#include is now removed, so this commit removes such unnecessary code.

```ruby
module M1
  refine(Kernel) do
    def f1 = :f1
  end
end

module M2
  refine(Kernel) do
    def f2 = :f2
  end
end

class Foo
  using M1
  using M2

  def test
    p f2 #=> :f2

    p f1 # expected => :f1
         # actual => undefined local variable or method 'f1' for an instance of Foo
  end
end

Foo.new.test
```
2024-02-27 14:51:04 +09:00
Fable Phippen
7b56353d97 Add a failing test for https://bugs.ruby-lang.org/issues/20305.
This bug demonstrates the issue I reported. It passes on commit
114e71d062
but does not pass on commit (the immediate child of the above commit)
1d2d25dcad
2024-02-27 13:58:03 +09:00
Kevin Newton
3ca8b4aee0 [ruby/prism] Support -p, -n, -a, and -l command line options
959eb506ca
2024-02-27 04:22:39 +00:00
Josef Šimánek
bfb2dc8acf [rubygems/rubygems] Warn on empty or open required_ruby_version specification attribute.
e4bb33747a
2024-02-27 12:33:45 +09:00
Kenta Murata
54a5b82944
Handle zero-like imaginary part as zero in to_r (#9581)
Fixes [Bug #5179]
2024-02-27 09:37:03 +09:00
Hiroshi SHIBATA
d2da774f87 [rubygems/rubygems] Rename wrapper files for vendored libraries with 'vendored_' prefix
cfc908c8c1
2024-02-26 22:04:04 +00:00
dependabot[bot]
f54122368c [rubygems/rubygems] Bump rb-sys
Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.88 to 0.9.89.
- [Release notes](https://github.com/oxidize-rb/rb-sys/releases)
- [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.88...v0.9.89)

---
updated-dependencies:
- dependency-name: rb-sys
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

75e5ec62be
2024-02-26 17:12:30 +00:00
dependabot[bot]
9c5a91e320 [rubygems/rubygems] Bump rb-sys
Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.88 to 0.9.89.
- [Release notes](https://github.com/oxidize-rb/rb-sys/releases)
- [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.88...v0.9.89)

---
updated-dependencies:
- dependency-name: rb-sys
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

94e6907098
2024-02-26 17:12:10 +00:00
Kevin Newton
1a57fee7af [ruby/prism] Fix multi write with modifier rescue
8ea7a3270f
2024-02-26 13:58:57 +00:00
Aaron Patterson
164e464b04 [ruby/strscan] Add a method for peeking and reading bytes as
integers
(https://github.com/ruby/strscan/pull/89)

This commit adds `scan_byte` and `peek_byte`. `scan_byte` will scan the
current byte, return it as an integer, and advance the cursor.
`peek_byte` will return the current byte as an integer without advancing
the cursor.

Currently `StringScanner#get_byte` returns a string, but I want to get
the current byte without allocating a string. I think this will help
with writing high performance lexers.

---------

873aba2e5d

Co-authored-by: Sutou Kouhei <kou@clear-code.com>
2024-02-26 15:54:54 +09:00
Nobuyoshi Nakada
7176c186d0 [rubygems/rubygems] Fix Fiddle::Handle leaks
Windows disallows to unlink opened files.

e0b63754bf
2024-02-26 15:27:38 +09:00
Nobuyoshi Nakada
7dd4b30b77 [rubygems/rubygems] The temporary directory must been removed
On Windows, open files cannot be removed and `FileUtils.rm_rf` just
silently fails.  This means also handle leaks, not only temporary file
leaks.

80a9c3ec08
2024-02-26 15:27:37 +09:00
Nobuyoshi Nakada
65f40967d5 [rubygems/rubygems] Get rid of too long paths
This is a fix-up of #7483.

Test method names in Rubygems are often very long, and the path under
the temporary directory generated from them can easily exceed system
limits.

Even without including the method name in the path name, by saving the
method and path name pair, it is possible to find the method from the
remaining path name.

de55064a3d
2024-02-26 15:27:37 +09:00
Hiroshi SHIBATA
91ec1fc4e7
Revert "Revert rubygems tempdir check"
This reverts commit 6aa5067ab9.
2024-02-26 15:27:26 +09:00
Nobuyoshi Nakada
d4e24021d3
Revise 9ec342e07d 2024-02-26 13:12:05 +09:00
Nobuyoshi Nakada
a0f7de814a
[Bug #20296] Fix the default assertion message 2024-02-26 12:29:23 +09:00
Misaki Shioi
9ec342e07d
Introduction of Happy Eyeballs Version 2 (RFC8305) in Socket.tcp (#9374)
* Introduction of Happy Eyeballs Version 2 (RFC8305) in Socket.tcp

This is an implementation of Happy Eyeballs version 2 (RFC 8305) in Socket.tcp.

[Background]
Currently, `Socket.tcp` synchronously resolves names and makes connection attempts with `Addrinfo::foreach.`
This implementation has the following two problems.

1. In name resolution, the program stops until the DNS server responds to all DNS queries.
2. In a connection attempt, while an IP address is trying to connect to the destination host and is taking time, the program stops, and other resolved IP addresses cannot try to connect.

[Proposal]
"Happy Eyeballs" ([RFC 8305](https://datatracker.ietf.org/doc/html/rfc8305)) is an algorithm to solve this kind of problem. It avoids delays to the user whenever possible and also uses IPv6 preferentially.

I implemented it into `Socket.tcp` by using `Addrinfo.getaddrinfo` in each thread spawned per address family to resolve the hostname asynchronously, and using `Socket::connect_nonblock` to try to connect with multiple addrinfo in parallel.

[Outcome]

This change eliminates a fatal defect in the following cases.

Case 1. One of the A or AAAA DNS queries does not return

---
require 'socket'

class Addrinfo
  class << self
    # Current Socket.tcp depends on foreach
    def foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, timeout: nil, &block)
      getaddrinfo(nodename, service, Socket::AF_INET6, socktype, protocol, flags, timeout: timeout)
        .concat(getaddrinfo(nodename, service, Socket::AF_INET, socktype, protocol, flags, timeout: timeout))
        .each(&block)
    end

    def getaddrinfo(_, _, family, *_)
      case family
      when Socket::AF_INET6 then sleep
      when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", 4567)]
      end
    end
  end
end

Socket.tcp("localhost", 4567)
---

Because the current `Socket.tcp` cannot resolve IPv6 names, the program stops in this case. It cannot start to connect with IPv4 address.
Though `Socket.tcp` with HEv2 can promptly start a connection attempt with IPv4 address in this case.

 Case 2. Server does not promptly return ack for syn of either IPv4 / IPv6 address family

---
require 'socket'

fork do
  socket = Socket.new(Socket::AF_INET6, :STREAM)
  socket.setsockopt(:SOCKET, :REUSEADDR, true)
  socket.bind(Socket.pack_sockaddr_in(4567, '::1'))
  sleep
  socket.listen(1)
  connection, _ = socket.accept
  connection.close
  socket.close
end

fork do
  socket = Socket.new(Socket::AF_INET, :STREAM)
  socket.setsockopt(:SOCKET, :REUSEADDR, true)
  socket.bind(Socket.pack_sockaddr_in(4567, '127.0.0.1'))
  socket.listen(1)
  connection, _ = socket.accept
  connection.close
  socket.close
end

Socket.tcp("localhost", 4567)
---

The current `Socket.tcp` tries to connect serially, so when its first name resolves an IPv6 address and initiates a connection to an IPv6 server, this server does not return an ACK, and the program stops.
Though `Socket.tcp` with HEv2 starts to connect sequentially and in parallel so a connection can be established promptly at the socket that attempted to connect to the IPv4 server.

In exchange, the performance of `Socket.tcp` with HEv2 will be degraded.

---
100.times { Socket.tcp("www.ruby-lang.org", 80) }
---

This is due to the addition of the creation of IO objects, Thread objects, etc., and calls to `IO::select` in the implementation.

* Avoid NameError of Socket::EAI_ADDRFAMILY in MinGW

* Support Windows with SO_CONNECT_TIME

* Improve performance

I have additionally implemented the following patterns:

- If the host is single-stack, name resolution is performed in the main thread. This reduces the cost of creating threads.
- If an IP address is specified, name resolution is performed in the main thread. This also reduces the cost of creating threads.
- If only one IP address is resolved, connect is executed in blocking mode. This reduces the cost of calling IO::select.

Also, I have added a fast_fallback option for users who wish not to use HE.
Here are the results of each performance test.

```ruby
require 'socket'
require 'benchmark'

HOSTNAME = "www.ruby-lang.org"
PORT = 80

ai = Addrinfo.tcp(HOSTNAME, PORT)

Benchmark.bmbm do |x|
  x.report("Domain name") do
    30.times { Socket.tcp(HOSTNAME, PORT).close }
  end

  x.report("IP Address") do
    30.times { Socket.tcp(ai.ip_address, PORT).close }
  end

  x.report("fast_fallback: false") do
    30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close }
  end
end
```

```
                           user     system      total        real
Domain name            0.015567   0.032511   0.048078 (  0.325284)
IP Address             0.004458   0.014219   0.018677 (  0.284361)
fast_fallback: false   0.005869   0.021511   0.027380 (  0.321891)
````

And this is the measurement result when executed in a single stack environment.

```
                           user     system      total        real
Domain name            0.007062   0.019276   0.026338 (  1.905775)
IP Address             0.004527   0.012176   0.016703 (  3.051192)
fast_fallback: false   0.005546   0.019426   0.024972 (  1.775798)
```

The following is the result of the run on Ruby 3.3.0.

(on Dual stack environment)

```
                 user     system      total        real
Ruby 3.3.0   0.007271   0.027410   0.034681 (  0.472510)
```

(on Single stack environment)

```
                 user     system      total        real
Ruby 3.3.0  0.005353   0.018898   0.024251 (  1.774535)
```

* Do not cache `Socket.ip_address_list`

As mentioned in the comment at https://github.com/ruby/ruby/pull/9374#discussion_r1482269186, caching Socket.ip_address_list does not follow changes in network configuration.
But if we stop caching, it becomes necessary to check every time `Socket.tcp` is called whether it's a single stack or not, which could further degrade performance in the case of a dual stack.
From this, I've changed the approach so that when a domain name is passed, it doesn't check whether it's a single stack or not and resolves names in parallel each time.

The performance measurement results are as follows.

require 'socket'
require 'benchmark'

HOSTNAME = "www.ruby-lang.org"
PORT = 80

ai = Addrinfo.tcp(HOSTNAME, PORT)

Benchmark.bmbm do |x|
  x.report("Domain name") do
    30.times { Socket.tcp(HOSTNAME, PORT).close }
  end

  x.report("IP Address") do
    30.times { Socket.tcp(ai.ip_address, PORT).close }
  end

  x.report("fast_fallback: false") do
    30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close }
  end
end

                           user     system      total        real
Domain name            0.004085   0.011873   0.015958 (  0.330097)
IP Address             0.000993   0.004400   0.005393 (  0.257286)
fast_fallback: false   0.001348   0.008266   0.009614 (  0.298626)

* Wait forever if fallback addresses are unresolved, unless resolv_timeout

Changed from waiting only 3 seconds for name resolution when there is no fallback address available, to waiting as long as there is no resolv_timeout.
This is in accordance with the current `Socket.tcp` specification.

* Use exact pattern to match IPv6 address format for specify address family
2024-02-26 12:14:11 +09:00
Nobuyoshi Nakada
f23d502805 [Bug #20296] Refine the test 2024-02-26 11:56:38 +09:00
Nobuyoshi Nakada
dc146babf4 [Bug #20296] Clear errinfo when exception: false 2024-02-26 11:56:38 +09:00
Kevin Newton
96907f9495 [ruby/prism] Convert pm_integer_t to strings
fa9a30ad91
2024-02-23 21:54:01 +00:00
eileencodes
50ace992c7 [Bug #20234] Fix segv when parsing begin statement in method definition
In a method definition, the `begin` may not have an `nd_body`. When that
happens we get a null expr back from `last_expr_node` which causes a
segv for the following examples:

```ruby
def (begin;end).foo; end
def (begin;else;end).foo; end
def (begin;ensure;else;end).foo; end
```

In addition, I've added tests for other cases that weren't causing a
segv but appeared untested.`

Fixes https://bugs.ruby-lang.org/issues/20234
2024-02-23 10:59:10 -08:00
Kevin Newton
02b531a813 [ruby/prism] Factor in sign to integer comparison
377666a5df
2024-02-23 13:25:31 -05:00
Kevin Newton
a38cc177d2 [ruby/prism] Duplicated when clauses
865b0d5fbe
2024-02-23 13:25:31 -05:00
Kevin Newton
d1ce989829 [ruby/prism] Duplicated hash keys
3e10c46c14
2024-02-23 13:25:31 -05:00
Nobuyoshi Nakada
41c0fb6991 [ruby/optparse] Add exact: keyword argument
07e83673a8
2024-02-23 21:16:59 +09:00
Kevin Newton
5e0589cf52 [ruby/prism] Parse float values
9137226a52
2024-02-22 22:42:44 -05:00
Kevin Newton
3b3def5db7 [ruby/prism] Regenerate snapshots using integer values 2024-02-22 22:42:44 -05:00
Kevin Newton
af0a6ea1d5 [ruby/prism] Add an IntegerField for parsing integer values
120d8c0479
2024-02-22 22:42:44 -05:00
Kevin Newton
ff6ebba9de [ruby/prism] Parse numeric values
a6a552411c
2024-02-22 22:42:44 -05:00
yui-knk
3ca6da24e3 [Bug #20295] Fix SEGV when parsing invalid regexp 2024-02-23 11:12:08 +09:00
Takashi Kokubun
bccf4b30fa
Skip under_gc_compact_stress on s390x (#10073) 2024-02-22 14:34:19 -08:00
Nobuyoshi Nakada
e04146129e
[Bug #20292] Truncate embedded string to new capacity 2024-02-22 22:46:18 +09:00
Nobuyoshi Nakada
133d774382
Cover all warning category options 2024-02-22 19:45:38 +09:00
Martin Emde
9f8f32bf9f [ruby/zlib] In Zlib::GzipReader#eof? check if we're actually at eof
Only consider it eof if we read ahead and something fills the buf.
If not, we may only have empty blocks and the footer.

Fixes https://github.com/ruby/zlib/pull/56

437bea8003
2024-02-22 06:42:06 +00:00
Kevin Newton
90c5393f9f [ruby/prism] Support ItParametersNode
So that compilers know they need to add to add an anonymous
variable to the local table.

7f1aadd057
2024-02-21 17:55:11 -05:00
Alan Wu
0be09967fe
YJIT: Grab stack operands after SP change in String#byteslice (#10060)
Previously, `StackOperand`s caching `sp_offset` was held across a
jit_prepare_call_with_gc(), which invalidates the offsets. With the
right register allocation state, the canary overlapped with the old
address of the receiver and YJIT clobbered the receiver writing the
canary.
2024-02-21 14:42:23 -08:00