Skip to content

Instantly share code, notes, and snippets.

@headius
Created January 27, 2022 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save headius/2e3928e8a96c1a86cd887e37da78b844 to your computer and use it in GitHub Desktop.
Save headius/2e3928e8a96c1a86cd887e37da78b844 to your computer and use it in GitHub Desktop.
diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb
index 0b9d0648bb..5a7cd5e984 100644
--- a/ext/bigdecimal/lib/bigdecimal/math.rb
+++ b/ext/bigdecimal/lib/bigdecimal/math.rb
@@ -227,6 +227,19 @@ def PI(prec)
#
def E(prec)
raise ArgumentError, "Zero or negative precision for E" if prec <= 0
- BigMath.exp(1, prec)
+ n = prec + BigDecimal.double_fig
+ one = BigDecimal("1")
+ y = one
+ d = y
+ z = one
+ i = 0
+ while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
+ m = BigDecimal.double_fig if m < BigDecimal.double_fig
+ i += 1
+ z *= i
+ d = one.div(z,m)
+ y += d
+ end
+ y
end
end
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
index 4512989310..2d49cd3fd7 100644
--- a/ext/fiddle/lib/fiddle.rb
+++ b/ext/fiddle/lib/fiddle.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-
-require 'fiddle.so'
+require 'fiddle.so' unless RUBY_ENGINE == 'jruby'
+require 'fiddle/jruby' if RUBY_ENGINE == 'jruby'
require 'fiddle/closure'
require 'fiddle/function'
require 'fiddle/version'
@@ -10,36 +10,66 @@ module Fiddle
# Returns the last win32 +Error+ of the current executing +Thread+ or nil
# if none
def self.win32_last_error
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
+ if RUBY_ENGINE == 'jruby'
+ errno = FFI.errno
+ errno == 0 ? nil : errno
+ else
+ Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
+ end
end
# Sets the last win32 +Error+ of the current executing +Thread+ to +error+
def self.win32_last_error= error
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
+ if RUBY_ENGINE == 'jruby'
+ errno = FFI.errno
+ errno == 0 ? nil : errno
+ else
+ Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
+ end
end
# Returns the last win32 socket +Error+ of the current executing
# +Thread+ or nil if none
def self.win32_last_socket_error
- Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
+ if RUBY_ENGINE == 'jruby'
+ errno = FFI.errno
+ errno == 0 ? nil : errno
+ else
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
+ end
end
# Sets the last win32 socket +Error+ of the current executing
# +Thread+ to +error+
def self.win32_last_socket_error= error
- Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
+ if RUBY_ENGINE == 'jruby'
+ errno = FFI.errno
+ errno == 0 ? nil : errno
+ else
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
+ end
end
end
# Returns the last +Error+ of the current executing +Thread+ or nil if none
def self.last_error
- Thread.current[:__FIDDLE_LAST_ERROR__]
+ if RUBY_ENGINE == 'jruby'
+ errno = FFI.errno
+ errno == 0 ? nil : errno
+ errno
+ else
+ Thread.current[:__FIDDLE_LAST_ERROR__]
+ end
end
# Sets the last +Error+ of the current executing +Thread+ to +error+
def self.last_error= error
- Thread.current[:__DL2_LAST_ERROR__] = error
- Thread.current[:__FIDDLE_LAST_ERROR__] = error
+ if RUBY_ENGINE == 'jruby'
+ FFI.errno = error || 0
+ else
+ Thread.current[:__DL2_LAST_ERROR__] = error
+ Thread.current[:__FIDDLE_LAST_ERROR__] = error
+ end
end
# call-seq: dlopen(library) => Fiddle::Handle
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index 3799d589d5..e4725dc49d 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -10,7 +10,8 @@
# For documentation, see class Pathname.
#
-require 'pathname.so'
+# Load built-in pathname library
+JRuby::Util.load_ext("org.jruby.ext.pathname.PathnameLibrary")
class Pathname
diff --git a/ext/ripper/lib/ripper/core.rb b/ext/ripper/lib/ripper/core.rb
index fa075da5b9..968766b12d 100644
--- a/ext/ripper/lib/ripper/core.rb
+++ b/ext/ripper/lib/ripper/core.rb
@@ -9,7 +9,12 @@
# For details of Ruby License, see ruby/COPYING.
#
-require 'ripper.so'
+if RUBY_ENGINE == 'jruby'
+ # Load built-in ripper library
+ JRuby::Util.load_ext("org.jruby.ext.ripper.RipperLibrary")
+else
+ require 'ripper.so'
+end
class Ripper
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index d756a32a5a..88f03d393e 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-require 'socket.so'
+# Load built-in socket library
+JRuby::Util.load_ext("org.jruby.ext.socket.SocketLibrary")
+
require 'io/wait'
class Addrinfo
@@ -194,7 +196,7 @@ def bind
# creates a listening socket bound to self.
def listen(backlog=Socket::SOMAXCONN)
- sock = Socket.new(self.pfamily, self.socktype, self.protocol)
+ sock = ServerSocket.new(self.pfamily, self.socktype, self.protocol)
begin
sock.ipv6only! if self.ipv6?
sock.setsockopt(:SOCKET, :REUSEADDR, 1)
@@ -300,9 +302,9 @@ def connect_address
# # use 3-element array.
# ancdata = [:SOCKET, :RIGHTS, [io.fileno].pack("i!")]
# sock.sendmsg("\0", 0, nil, ancdata)
- def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls)
- __sendmsg(mesg, flags, dest_sockaddr, controls)
- end
+ #def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls)
+ # __sendmsg(mesg, flags, dest_sockaddr, controls)
+ #end
# call-seq:
# basicsocket.sendmsg_nonblock(mesg, flags=0, dest_sockaddr=nil, *controls, opts={}) => numbytes_sent
@@ -316,10 +318,10 @@ def sendmsg(mesg, flags = 0, dest_sockaddr = nil, *controls)
# By specifying a keyword argument _exception_ to +false+, you can indicate
# that sendmsg_nonblock should not raise an IO::WaitWritable exception, but
# return the symbol +:wait_writable+ instead.
- def sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls,
- exception: true)
- __sendmsg_nonblock(mesg, flags, dest_sockaddr, controls, exception)
- end
+ #def sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls,
+ # exception: true)
+ # __sendmsg_nonblock(mesg, flags, dest_sockaddr, controls, exception)
+ #end
# call-seq:
# basicsocket.recv_nonblock(maxlen [, flags [, buf [, options ]]]) => mesg
@@ -368,9 +370,9 @@ def sendmsg_nonblock(mesg, flags = 0, dest_sockaddr = nil, *controls,
#
# === See
# * Socket#recvfrom
- def recv_nonblock(len, flag = 0, str = nil, exception: true)
- __recv_nonblock(len, flag, str, exception)
- end
+ #def recv_nonblock(len, flag = 0, str = nil, exception: true)
+ # __recv_nonblock(len, flag, str, exception)
+ #end
# call-seq:
# basicsocket.recvmsg(maxmesglen=nil, flags=0, maxcontrollen=nil, opts={}) => [mesg, sender_addrinfo, rflags, *controls]
@@ -423,9 +425,9 @@ def recv_nonblock(len, flag = 0, str = nil, exception: true)
# return ancdata.unix_rights[0]
# end
# }
- def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false)
- __recvmsg(dlen, flags, clen, scm_rights)
- end
+ #def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false)
+ # __recvmsg(dlen, flags, clen, scm_rights)
+ #end
# call-seq:
# basicsocket.recvmsg_nonblock(maxdatalen=nil, flags=0, maxcontrollen=nil, opts={}) => [data, sender_addrinfo, rflags, *controls]
@@ -439,23 +441,23 @@ def recvmsg(dlen = nil, flags = 0, clen = nil, scm_rights: false)
# By specifying a keyword argument _exception_ to +false+, you can indicate
# that recvmsg_nonblock should not raise an IO::WaitReadable exception, but
# return the symbol +:wait_readable+ instead.
- def recvmsg_nonblock(dlen = nil, flags = 0, clen = nil,
- scm_rights: false, exception: true)
- __recvmsg_nonblock(dlen, flags, clen, scm_rights, exception)
- end
+ #def recvmsg_nonblock(dlen = nil, flags = 0, clen = nil,
+ # scm_rights: false, exception: true)
+ # __recvmsg_nonblock(dlen, flags, clen, scm_rights, exception)
+ #end
# Linux-specific optimizations to avoid fcntl for IO#read_nonblock
# and IO#write_nonblock using MSG_DONTWAIT
# Do other platforms support MSG_DONTWAIT reliably?
- if RUBY_PLATFORM =~ /linux/ && Socket.const_defined?(:MSG_DONTWAIT)
- def read_nonblock(len, str = nil, exception: true) # :nodoc:
- __read_nonblock(len, str, exception)
- end
-
- def write_nonblock(buf, exception: true) # :nodoc:
- __write_nonblock(buf, exception)
- end
- end
+ #if RUBY_PLATFORM =~ /linux/ && Socket.const_defined?(:MSG_DONTWAIT)
+ # def read_nonblock(len, str = nil, exception: true) # :nodoc:
+ # __read_nonblock(len, str, exception)
+ # end
+ #
+ # def write_nonblock(buf, exception: true) # :nodoc:
+ # __write_nonblock(buf, exception)
+ # end
+ #end
end
class Socket < BasicSocket
@@ -466,6 +468,9 @@ def ipv6only!
end
end
+ # JRuby does not do this dance to get around keyword arguments.
+ unless RUBY_ENGINE == 'jruby'
+
# call-seq:
# socket.recvfrom_nonblock(maxlen[, flags[, outbuf[, opts]]]) => [mesg, sender_addrinfo]
#
@@ -532,9 +537,9 @@ def ipv6only!
#
# === See
# * Socket#recvfrom
- def recvfrom_nonblock(len, flag = 0, str = nil, exception: true)
- __recvfrom_nonblock(len, flag, str, exception)
- end
+ #def recvfrom_nonblock(len, flag = 0, str = nil, exception: true)
+ # __recvfrom_nonblock(len, flag, str, exception)
+ #end
# call-seq:
# socket.accept_nonblock([options]) => [client_socket, client_addrinfo]
@@ -589,9 +594,11 @@ def recvfrom_nonblock(len, flag = 0, str = nil, exception: true)
#
# === See
# * Socket#accept
- def accept_nonblock(exception: true)
- __accept_nonblock(exception)
- end
+ #def accept_nonblock(exception: true)
+ # __accept_nonblock(exception)
+ #end
+
+ end # unless RUBY_ENGINE == 'jruby'
# :call-seq:
# Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... }
@@ -673,7 +680,7 @@ def self.ip_sockets_port0(ai_list, reuseaddr)
port = nil
ai_list.each {|ai|
begin
- s = Socket.new(ai.pfamily, ai.socktype, ai.protocol)
+ s = ServerSocket.new(ai.pfamily, ai.socktype, ai.protocol)
rescue SystemCallError
next
end
@@ -1210,9 +1217,9 @@ def self.unix_server_loop(path, &b) # :yield: socket, client_addrinfo
#
# === See
# # Socket#connect
- def connect_nonblock(addr, exception: true)
- __connect_nonblock(addr, exception)
- end
+ #def connect_nonblock(addr, exception: true)
+ # __connect_nonblock(addr, exception)
+ #end
end
class UDPSocket < IPSocket
@@ -1268,9 +1275,9 @@ class UDPSocket < IPSocket
#
# === See
# * Socket#recvfrom
- def recvfrom_nonblock(len, flag = 0, outbuf = nil, exception: true)
- __recvfrom_nonblock(len, flag, outbuf, exception)
- end
+ #def recvfrom_nonblock(len, flag = 0, outbuf = nil, exception: true)
+ # __recvfrom_nonblock(len, flag, outbuf, exception)
+ #end
end
class TCPServer < TCPSocket
@@ -1310,9 +1317,9 @@ class TCPServer < TCPSocket
# === See
# * TCPServer#accept
# * Socket#accept
- def accept_nonblock(exception: true)
- __accept_nonblock(exception)
- end
+ #def accept_nonblock(exception: true)
+ # __accept_nonblock(exception)
+ #end
end
class UNIXServer < UNIXSocket
@@ -1351,7 +1358,7 @@ class UNIXServer < UNIXSocket
# === See
# * UNIXServer#accept
# * Socket#accept
- def accept_nonblock(exception: true)
- __accept_nonblock(exception)
- end
+ #def accept_nonblock(exception: true)
+ # __accept_nonblock(exception)
+ #end
end if defined?(UNIXSocket)
diff --git a/ext/win32/lib/win32/resolv.rb b/ext/win32/lib/win32/resolv.rb
index d06658f0aa..b96a4bdfaf 100644
--- a/ext/win32/lib/win32/resolv.rb
+++ b/ext/win32/lib/win32/resolv.rb
@@ -37,9 +37,81 @@ def self.get_resolv_info
end
end
-begin
- require 'win32/resolv.so'
-rescue LoadError
+
+# JRuby specific use FFI instead of loading native .so
+module Win32
+ module Internal
+ NO_ERROR, ERROR_BUFFER_OVERFLOW = 0, 111
+
+ require 'ffi'
+
+ class IP_ADDRESS_STRING < FFI::Struct
+ layout :string, [:uint8, 16]
+ end
+
+ class IP_ADDR_STRING < FFI::Struct
+ layout :next, IP_ADDR_STRING.ptr,
+ :ip_address, IP_ADDRESS_STRING,
+ :ip_mask_string, IP_ADDRESS_STRING,
+ :context, :int
+ end
+
+ class FIXED_INFO < FFI::Struct
+ layout :host_name, [:uint8, 128 + 4],
+ :domain_name, [:uint8, 128 + 4],
+ :current_dns_server, IP_ADDR_STRING.ptr,
+ :dns_server_list, IP_ADDR_STRING,
+ :node_type, :uint,
+ :scope_id, [:uint8, 256 + 4],
+ :enable_routine, :uint,
+ :enable_proxy, :uint,
+ :enable_dns, :uint
+ end
+
+ class IntPtr < FFI::Struct
+ layout :value, :int
+ end
+
+ module Iphlpapi
+ extend FFI::Library
+ ffi_lib 'Iphlpapi'
+ ffi_convention :stdcall
+
+ attach_function :get_network_params, :GetNetworkParams, [:pointer, IntPtr], :int
+ end
+ end
+end
+
+module Win32
+ module Resolv
+ def self.get_dns_server_list
+ size = Win32::Internal::IntPtr.new
+ ret = Win32::Internal::Iphlpapi.get_network_params nil, size
+
+ # We get buffer overflow because first arg to get_network_params is nil.
+ if ret != Win32::Internal::NO_ERROR && ret != Win32::Internal::ERROR_BUFFER_OVERFLOW
+ raise Win32::Resolv::Error
+ end
+
+ fixed_info = FFI::MemoryPointer.new size[:value]
+ ret = Win32::Internal::Iphlpapi.get_network_params fixed_info, size
+
+ raise Win32::Resolv::Error if ret != Win32::Internal::NO_ERROR
+
+ fixed_info = Win32::Internal::FIXED_INFO.new fixed_info
+
+ addr = fixed_info[:dns_server_list]
+ addresses = []
+
+ while !addr.null? do # test condition on machines with no DNS entries at all.
+ addresses << addr[:ip_address][:string].to_s
+ break if addr[:next].null?
+ addr = addr[:next]
+ end
+
+ addresses
+ end
+ end
end
module Win32
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 552f818e5d..25cc6e370b 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -651,6 +651,10 @@ class << HTTP
# is required to use the proxy, and p_no_proxy hosts which do not
# use the proxy.
#
+ # In JRuby, this will default to the JSE proxy settings provided in the
+ # 'http.proxyHost' and 'http.proxyPort' Java system properties, if they
+ # are set, falling back on environment variables otherwise.
+ #
def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
http = super address, port
@@ -1032,10 +1036,12 @@ def connect
end
end
@ssl_context.set_params(ssl_parameters)
- @ssl_context.session_cache_mode =
- OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
- OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
- @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
+ # NOTE: session_cache_mode = has no effect on (current) JRuby-OpenSSL
+ # @ssl_context.session_cache_mode =
+ # OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
+ # OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
+ # SSLSocket#session= does nothing with JRuby-OpenSSL
+ # @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
D "starting SSL for #{conn_addr}:#{conn_port}..."
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
s.sync_close = true
@@ -1046,7 +1052,7 @@ def connect
s.session = @ssl_session
end
ssl_socket_connect(s, @open_timeout)
- if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname
+ if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) # && @ssl_context.verify_hostname
s.post_connection_check(@address)
end
D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
@@ -1103,6 +1109,11 @@ def do_finish
#
# This class is obsolete. You may pass these same parameters directly to
# Net::HTTP.new. See Net::HTTP.new for details of the arguments.
+ #
+ # In JRuby, this will default to the JSE proxy settings provided in the
+ # 'http.proxyHost' and 'http.proxyPort' Java system properties, if they
+ # are set, falling back on environment variables otherwise.
+ #
def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil)
return self unless p_addr
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
index 3b67164039..cc0b60790b 100644
--- a/lib/tmpdir.rb
+++ b/lib/tmpdir.rb
@@ -7,7 +7,7 @@
require 'fileutils'
begin
- require 'etc.so'
+ require 'etc'
rescue LoadError # rescue LoadError for miniruby
end
@@ -87,9 +87,9 @@ def self.tmpdir
#
def self.mktmpdir(prefix_suffix=nil, *rest, **options)
base = nil
- path = Tmpname.create(prefix_suffix || "d", *rest, **options) {|path, _, _, d|
+ path = Tmpname.create(prefix_suffix || "d", *rest, **options) {|_path, _, _, d|
base = d
- mkdir(path, 0700)
+ mkdir(_path, 0700)
}
if block_given?
begin
@@ -140,7 +140,10 @@ def create(basename, tmpdir=nil, max_try: nil, **opts)
t = Time.now.strftime("%Y%m%d")
path = "#{prefix}#{t}-#{$$}-#{RANDOM.next}"\
"#{n ? %[-#{n}] : ''}#{suffix||''}"
- path = File.join(tmpdir, path)
+ # We use the second form here because chdir + ./ files won't open right (http://bugs.jruby.org/3698)
+ # path = File.join(tmpdir, path)
+ path = File.expand_path(path, tmpdir)
+
yield(path, n, opts, origdir)
rescue Errno::EEXIST
n ||= 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment