Publicado por naruse el 2022-12-25
Traducción de vtamara
Nos complace anunciar la publicación de Ruby 3.2.0. Ruby 3.2 añade muchas características y mejoras en desempeño.
Soporte para WebAssembly basado en WASI
Este es un porte inicial del soporte para WebAssembly basado en WASI. Esto permite que un binario de CRuby esté disponible en un navegador Web, en un ambiente sin servidor Edge y en otros tipos de empotrados de WebAssembly/WASI. Actualmente este porte pasa los juegos de pruebas básicas y de bootstrap que no usan la API de Threads.
Trasfondo
WebAssembly (Wasm) inicialmente se introdujo para ejecutar programas de manera segura y rápida en navegadores web. Pero buena parte de su objetivo –ejecutar programar eficientemente y con seguridad– es anhelado hace tiempo no sólo para el web sino para aplicaciones en general.
WASI (The WebAssembly System Interface) fue diseñado para ese caso de uso. Dado que una aplicación necesita comunicarse con el sistema operativo pero WebAssembly corre en una máquina virtual sin interfaz al sistema operativo, WASI estandariza dicha interfaz.
El soporte para WebAssembly/WASI en ruby pretende aprovechar estos proyectos. Habilita a los desarrolladores de ruby para escribir aplicaciones que corran en esas plataformas prometidas.
Caso de uso
Este soporte promueve que los desarrolladores utilicen CRuby en un ambiente WebAssembly. Un caso de uso de ejemplo es el soporte CRuby del espacio de entrenamiento TryRuby. Ahora usted puede probar CRuby original en su navegador web.
Puntos técnicos
Hoy en día WASI y WebAssembly carecen de algunas características para implementar Fibras, excepciones y el Recolector de Basura porque aún está evolucionado y también por razones de seguridad. Así que CRuby llena ese vació mediante Asyncify, que es una técnica de transformación binaria para controlar la ejecución en el espacio del usuario.
Además, construimos un Sistema Virtual de Archivos (VFS) sobre WASI que permite empaquetar con facilidad aplicación Ruby en un sólo archivo .wasm. Esto hace un poco más fácil la distribución de aplicaciones.
Enlaces relacionados
YJIT listo para producción
- YJIT ya no es experimental
- Se ha probado con cargas de producción por más de un año y a demostrado ser estable.
- YJIT ahora soporta tanto CPUs x86-64 como arm64/aarch64 en Linux, MacOS,
BSD y otras plataformas UNIX.
- Esta versión trae soporte para procesadores Mac M1/M2, AWS Graviton, Raspberry Pi 4 y más.
- La compilación de YJIT ahora requiere Rust 1.58.0+. [Característica #18481]
- Para asegurar que CRuby se compila con YJIT, por favor instale
rustc >= 1.58.0 antes de ejecutar el script
./configure
- Por favor comuníquese con el equipo de YJIT en caso de que tenga algún inconveniente.
- Para asegurar que CRuby se compila con YJIT, por favor instale
rustc >= 1.58.0 antes de ejecutar el script
- La versión 3.2 es más veloz que la 3.1, y tiene alrededor de 1/3 de
sobrecarga de memoria.
- En general YJIT es 41% más rápido (media geométrica) que el intérprete de Ruby en yjit-bench.
- La memoria física para el código JIT se localiza tardiamente. A diferencia
de Ruby 3.1, el RSS de un proceso Ruby se minimiza porque las páginas
de memoria virtual localizadas con
--yjit-exec-mem-size
no se mapearán a páginas de memoria física sino hasta que en efecto sean utilizadas por el código JIT. - Se introduce código al Recolector de Basura que libera todas las páginas
cuando el consumo de memoria del código JIT alcanza
--yjit-exec-mem-size
. - RubyVM::YJIT.runtime_stats retorna métricas del código del Recolector de
Basura además de las llaves existentes
inline_code_size
youtlined_code_size
:code_gc_count
,live_page_count
,freed_page_count
, yfreed_code_size
.
- La mayoría de las estadísticas producidas por
RubyVM::YJIT.runtime_stats
ahora están disponibles en las versiones publicadas.- Sencillamente ejecute ruby con
--yjit-stats
para calcular estadísticas stats (esto incurre en alguna sobrecarga en el tiempo de ejecución).
- Sencillamente ejecute ruby con
- YJIT ahora está optimizado para aprovechar Formas de Objetos (Object Shapes). [Característica #18776]
- Aprovecha la invalidación de constantes a una escala más fina para invalidar menos código cuando se definen nuevas constantes. [Característica #18589]
- El valor predeterminado de
--yjit-exec-mem-size
se ha cambiado a 64 (MiB). - El valor predeterminado de
--yjit-call-threshold
se ha cambiado a 30.
Mejora en Regexp contra Denegación de Servicio por Expresión Regular (ReDoS)
Es conocido que la correspondencia de expresiones regulares puede tomar un tiempo inesperadamente largo. Si su código intenta hacer corresponder una expresión regular ineficiente con un entrada no confiable, un atacante puede explotarlo y producir efectivamente una Denegación de Servicio (también llamada Denegación de Servicio por Expresión Regular o ReDoS).
Hemos introducido dos mejoras que mitigan significativamente un ReDoS.
Algoritmo de correspondencia mejorado
Desde Ruby 3.2, el algoritmo de correspondencia de expresiones regulares ha sido mejorado significativamente empleando técnicas de memorización.
# Esta correspondencia tarda 10 segundos. en Ruby 3.1, y 0.003 seg. en Ruby 3.2
/^a*b?a*$/ =~ "a" * 50000 + "x"
El algoritmo de correspondencia mejorado permite que la mayoría de correspondencia de expresiones regulares (cerca del 90% en nuestros experimentos) se complete en tiempo lineal.
(Para usuarios de la versión preview: esta optimización puede consumir memoria proporcional a la longitud de la entrada por cada correspondencia. Esperamos que no se presenten problemas prácticos porque la localización de memoria para esto usualmente se hace de manera tardía, y una correspondencia de Regexp normal debería consumir a lo sumo 10 veces la memoria de la entrada. Si se le agota la memoria al hacer correspondencia de expresiones regulares en aplicaciones del mundo real, por favor repórtelo.)
La propuesta original es https://bugs.ruby-lang.org/issues/19104
Temporizador de Regexp
La optimización anterior no puede aplicarse a algunos tipos de expresiones regulares, como las que incluyen características avanzadas (e.g., referencias-anteriores –back-references– y mirar-alrededor –look-arond–), o con un número inmenso y fijo de repeticiones. Como medida alternativa, también se introduce un temporizador para expresiones regulares.
Regexp.timeout = 1.0
/^a*b?a*()\1$/ =~ "a" * 50000 + "x"
#=> Regexp::TimeoutError is raised in one second
Tenga en cuenta que Regexp.timeout
es una configuración global. Si quiere
emplear configuraciones del temporizadores diferentes para algunas
expresiones regulares especiales, puede usar la palabra clave timeout
de Regexp.new
.
Regexp.timeout = 1.0
# Esta regexp no tiene tiempo límite
long_time_re = Regexp.new('^a*b?a*()\1$', timeout: Float::INFINITY)
long_time_re =~ "a" * 50000 + "x" # nunca se interrumpe
La propuesta original es https://bugs.ruby-lang.org/issues/17837
Otras características nuevas y notables
SyntaxSuggest
-
La característica de
syntax_suggest
(antes llamadadead_end
) se ha integrado en Ruby. Le ayuda a encontrar la posición de errores tales comoend
s falantes o superfluos, para permitirle continuar su camino más rápido, como en el siguiente ejemplo:Unmatched `end', missing keyword (`do', `def`, `if`, etc.) ? 1 class Perro > 2 defladra > 3 end 4 end
ErrorHighlight
- Ahora puede resaltar errores en los argumentos relevantes para
errores
TypeError
yArgumentError
test.rb:2:in `+': nil can't be coerced into Integer (TypeError)
sum = ary[0] + ary[1]
^^^^^^
Lenguaje
-
Los argumentos anónimos para el resto y con palabra clave para el resto ahora pueden ser pasados como argumentos, en lugar de sólo ser usados en parámetros de métodos. [Característica #18351]
def foo(*) bar(*) end def baz(**) quux(**) end
-
Un proc que acepte un solo argumento posicional y palabras clave ya no hará splat automáticamente. [Falla #18633]
proc{|a, **k| a}.call([1, 2]) # Ruby 3.1 and before # => 1 # Ruby 3.2 and after # => [1, 2]
-
El orden de evaluación de la asignación de constantes para constantes establecidas en objetos explícitos se ha hecho consistente con el orden de evaluación de la asignación de atributos. Por ejemplo con este código:
foo::BAR = baz
foo
ahora es llamado antes quebaz
. De forma similar, para asignaciones múltiples a constantes, se usa un orden de evaluación de izquierda a derecha. Por ejemplo con el siguiente código:foo1::BAR1, foo2::BAR2 = baz1, baz2
Ahora se usa el siguiente orden de evaluación:
foo1
foo2
baz1
baz2
-
El patrón Find ya no es experimental. [Característica #18585]
-
Los métodos que reciben un parámetro para el resto (como
*args
) y que quieren delegar argumentos de palabra clave comofoo(*args)
ahora deben marcarse conruby2_keywords
(si es que aún hace falta). En otras palabras, todos los métodos que quieren delegar argumentos de palabra clave por medio de*args
ahora deben marcarse conruby2_keywords
, sin excepción. Esto hará más fácil la transición a otras formas de delegación una vez una librería pueda requerir Ruby 3+. Antes, la opciónruby2_keywords
se mantenía si el método receptor tomaba*args
, pero esto era una falla y una inconsistencia. Una buena técnica para encontrar dónde puede faltarruby2_keywords
es ejecutar la suite de pruebas, y donde falle buscar el último método que debe recibir argumentos de palabra clave , usarputs nil, caller, nil
allí. Después revisar que cada método/bloque en la cadena de llamados que delegue palabras clave esté marcado correctamente comoruby2_keywords
. [Falla #18625] [Falla #16466]def target(**kw) end # Accidentalmente funcionaba sin ruby2_keywords en Ruby 2.7-3.1, # necesita ruby2_keywords en 3.2+. # Así como (*args, **kwargs) o (...) se necesitarían tanto en #foo # como #bar cuando deje de usar ruby2_keywords. ruby2_keywords def bar(*args) target(*args) end ruby2_keywords def foo(*args) bar(*args) end foo(k: 1)
Mejoras en desempeño
MJIT
- El compilador MJIT se ha vuelto a implementar en Ruby como
ruby_vm/mjit/compiler
. - El compilador MJIT se ejecuta en un proceso bifurcado en lugar de
hacerlo en un hilo (thread) nativo llamado trabajador MJIT
[Característica #18968]
- Como resultado de esto, ya no soporta Microsoft Visual Studio (MSWIN).
- MinGW ya no es soportado. [Característica #18824]
- Renombrar
--mjit-min-calls
por--mjit-call-threshold
. - Se cambió el valor predeterminado para
--mjit-max-cache
de 10000 a 100.
PubGrub
-
Bundler 2.4 ahora usa el resolvedor PubGrub en lugar de Molinillo.
- PubGrub es la siguiente generación de algoritmos de resolución usado
por el manejador de paquetes
pub
para el lenguaje de programación Dart. - Puede obtener resultados de resolución diferentes tras este cambio. Por favor reporte tales casos como Incidentes de RubyGems/Bundler
- PubGrub es la siguiente generación de algoritmos de resolución usado
por el manejador de paquetes
-
RubyGems seguirá usando el resolvedor Molinillo en Ruby 3.2. Planeamos remplazarlo por PubGrub en el futuro.
Otros cambios notables desde 3.1
- Data
-
Nueva clase central para representar un objeto con valor inmutable. La clase es similar a Struct y comparte parcialmente la implementación, pero tiene una API más limpia y estricta [Característica #16122]
Medicion = Data.define(:cantidad, :unidad) distancia = Medicion.new(100, 'km') #=> #<data Medicion cantidad=100, unidad="km"> peso = Medicion.new(cantidad: 50, unidad: 'kg') #=> #<data Medicion cantidad=50, unidad="kg"> peso.with(cantidad: 40) #=> #<data Medicion cantidad=40, unidad="kg"> peso.cantidad #=> 50 peso.cantidad = 40 #=> NoMethodError: undefined method `cantidad='
-
- Hash
Hash#shift
ahora siempre retornanil
si el diccionario está vacío, en lugar de retornar el valor predeterminado o llamar el proc predeterminado. [Falla #16908]
- MatchData
- Se ha añadido
MatchData#byteoffset
. [Característica #13110]
- Se ha añadido
- Módulos
- Se ha añadido
Module.used_refinements
. [Característica #14332] - Se ha añadido
Module#refinements
. [Característica #12737] - Se ha añadido
Module#const_added
. [Característica #17881]
- Se ha añadido
- Proc
Proc#dup
retorna una instancia de subclase. [Falla #17545]Proc#parameters
ahora acepta la palabra clavelambda
. [Característica #15357]
- Refinamiento
- Se ha añadido
Refinement#refined_class
. [Característica #12737]
- Se ha añadido
- RubyVM::AbstractSyntaxTree
- Se agrega la opción
error_tolerant
aparse
,parse_file
yof
. [Característica #19013] Con esta opción- Se suprime
SyntaxError
- Se retorna un AST con entradas inválidas
end
se complementa cuando el reconocedor llega al final de la entrada peroend
es insuficiente.end
se trata como una palabra reservada con base en la indentación.
# Sin la opción error_tolerant raiz = RubyVM::AbstractSyntaxTree.parse(<<~RUBY) def m a = 10 if end RUBY # => <internal:ast>:33:in `parse': syntax error, unexpected `end' (SyntaxError) # Con la opción error_tolerant raiz = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true) def m a = 10 if end RUBY p root # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-4:3> # `end` se trata como palabra reservada con base en la indentación raiz = RubyVM::AbstractSyntaxTree.parse(<<~RUBY, error_tolerant: true) module Z class Foo foo. end def bar end end RUBY p raiz.children[-1].children[-1].children[-1].children[-2..-1] # => [#<RubyVM::AbstractSyntaxTree::Node:CLASS@2:2-4:5>, #<RubyVM::AbstractSyntaxTree::Node:DEFN@6:2-7:5>]
- Se suprime
-
Se agrega la opción
keep_tokens
aparse
,parse_file
yof
. [Característica #19070]root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2", keep_tokens: true) root.tokens # => [[0, :tIDENTIFIER, "x", [1, 0, 1, 1]], [1, :tSP, " ", [1, 1, 1, 2]], ...] root.tokens.map{_1[2]}.join # => "x = 1 + 2"
- Se agrega la opción
- Conjuntos
Set
ahora está disponible como una clase incorporada que no exigerequire "set"
. [Característica #16989] Ahora se llama de manera automática al usar la constanteSet
o con una llamada aEnumerable#to_set
.
- Cadenas
- Se han añadido
String#byteindex
yString#byterindex
. [Característica #13110] - Se actualizó Unicode a la versión 15.0.0 y Emoji a la version 15.0. [[Característica #18039]] (también aplica para Regexp)
- Se ha añadido
String#bytesplice
. [Característica #18598]
- Se han añadido
Struct
-
Una clase
Struct
también puede inicializarse con argumentos de palabra clave sinkeyword_init: true
enStruct.new
[Característica #16806]Publicacion = Struct.new(:id, :nombre) Publicacion.new(1, "Hola") #=> #<struct Publicacion id=1, nombre="hola"> # Desde Ruby 3.2, el siguiente código también opera sin keyword_init: true. Publicacion.new(id: 1, nombre: "hola") #=> #<struct Publicacion id=1, nombre="hello">
Asuntos de compatibilidad
-
Nota: Excluyendo arreglos de fallas.
Constantes eliminadas
Las siguientes constantes en desuso han sido eliminadas.
Fixnum
yBignum
[Característica #12005]Random::DEFAULT
[Característica #17351]Struct::Group
Struct::Passwd
Métodos eliminados
Los siguientes métodos en desuso han sido eliminados.
Dir.exists?
[Característica #17391]File.exists?
[Característica #17391]Kernel#=~
[Característica #15231]Kernel#taint
,Kernel#untaint
,Kernel#tainted?
[Característica #16131]Kernel#trust
,Kernel#untrust
,Kernel#untrusted?
[Característica #16131]
Asuntos de compatibilidad en Stdlib
Ya no se incluyen fuentes de terceros
-
Ya no incluimos código fuente de terceros como
libyaml
ylibffi
.-
La fuente de
libyaml
fue eliminada depsych
. Puede tener que instalarlibyaml-dev
en plataformas Ubuntu/Debian. El nombre del paquete difiere en cada plataforma. -
El código fuente incluido de
libffi
también fue eliminado defiddle
-
Psych
ya no incluye las fuentes de libyaml. Los usuarios necesitan instalar la librería libyaml por su cuenta con el sistema de paquetes. [Característica #18571]-
Psych y fiddle soportaban compilación estática con versiones específicas de las fuentes de libyaml y libffi. Puede compilar psych con libyaml-0.2.5 así:
$ ./configure --with-libyaml-source-dir=/path/to/libyaml-0.2.5
Y puede compilar fiddle con libffi-3.4.4 así:
$ ./configure --with-libffi-source-dir=/path/to/libffi-3.4.4
[[Feature #18571]]
Actualización al API en C
Funciones actualizadas del API en C
Se actualizaron las siguientes funciones del API.
- Generador de números seudo aleatorios (PRNG)
rb_random_interface_t
actualizado y con versiones. Las librerías de extensión que usan esta interfaz y construidas para versiones antiguas. También la funcióninit_int32
debe ser definida.
Funciones eliminadas del API en C
Los siguientes elementos del APIs han sido eliminados.
- variable
rb_cData
. - funciones “taintedness” y “trustedness”. [Característica #16131]
Actualizaciones a la librería estándar
-
Bundler
- Añadido soporte para –ext=rust para empaquetar gemas simples con extensiones Rust. [GH-rubygems-6149]
- La clonación de repositorios git es más rápida [GH-rubygems-4475]
-
RubyGems
- Agrega soporte mswin para el constructor cargo. [GH-rubygems-6167]
-
ERB
- Se implementa
ERB::Util.html_escape
más rápido queCGI.escapeHTML
.- Ya no localiza un objeto String cuando no se requiere escapar caracteres.
- Evita llamar métodos
#to_s
cuando un argumento ya es String. - Se agrega
ERB::Escape.html_escape
como alias deERB::Util.html_escape
, que no ha tenido un parchado-monkey de Rails.
- Se implementa
-
IRB
- Se han añadido ordenes de integración con debug.gem:
debug
,break
,catch
,next
,delete
,step
,continue
,finish
,backtrace
,info
- Funcionan incluso si no tiene
gem "debug"
en su Gemfile. - Ver también: What’s new in Ruby 3.2’s IRB?
- Funcionan incluso si no tiene
- Se han añadido más ordenes como de Pry y características.
- Se añadieron
edit
yshow_cmds
(comohelp
en Pry). ls
recibe la opción-g
o-G
para filtrar la salida.show_source
es un alias de$
y acepta entradas sin comillas.whereami
es un alias de@
.
- Se añadieron
- Se han añadido ordenes de integración con debug.gem:
-
Las siguientes gemas predeterminadas han sido actualizadas
- RubyGems 3.4.1
- abbrev 0.1.1
- benchmark 0.2.1
- bigdecimal 3.1.3
- bundler 2.4.1
- cgi 0.3.6
- csv 3.2.6
- date 3.3.3
- delegate 0.3.0
- did_you_mean 1.6.3
- digest 3.1.1
- drb 2.1.1
- english 0.7.2
- erb 4.0.2
- error_highlight 0.5.1
- etc 1.4.2
- fcntl 1.0.2
- fiddle 1.1.1
- fileutils 1.7.0
- forwardable 1.3.3
- getoptlong 0.2.0
- io-console 0.6.0
- io-nonblock 0.2.0
- io-wait 0.3.0
- ipaddr 1.2.5
- irb 1.6.2
- json 2.6.3
- logger 1.5.3
- mutex_m 0.1.2
- net-http 0.3.2
- net-protocol 0.2.1
- nkf 0.1.2
- open-uri 0.3.0
- open3 0.1.2
- openssl 3.1.0
- optparse 0.3.1
- ostruct 0.5.5
- pathname 0.2.1
- pp 0.4.0
- pstore 0.1.2
- psych 5.0.1
- racc 1.6.2
- rdoc 6.5.0
- readline-ext 0.1.5
- reline 0.3.2
- resolv 0.2.2
- resolv-replace 0.1.1
- securerandom 0.2.2
- set 1.0.3
- stringio 3.0.4
- strscan 3.0.5
- syntax_suggest 1.0.2
- syslog 0.1.1
- tempfile 0.1.3
- time 0.2.1
- timeout 0.3.1
- tmpdir 0.1.3
- tsort 0.1.1
- un 0.2.1
- uri 0.12.0
- weakref 0.1.2
- win32ole 1.8.9
- yaml 0.2.1
- zlib 3.0.0
-
Las siguientes gemas incluidas han sido actualizadas
- minitest 5.16.3
- power_assert 2.0.3
- test-unit 3.5.7
- net-ftp 0.2.0
- net-imap 0.3.3
- net-pop 0.1.2
- net-smtp 0.3.3
- rbs 2.8.2
- typeprof 0.21.3
- debug 1.7.1
Ver en la publicación de GitHub GitHub Releases of logger o en la bitácora de cambios los detalles de las gemas predeterminadas e incluidas.
Ver más detalles en NEWS o en la bitácora de cambios.
Con estos cambios, 3048 archivos cambiados, 218253 inserciones(+), 131067 eliminaciones(-) desde Ruby 3.1.0!
¡Feliz navidad, felices fiestas y disfrute programar con Ruby 3.2!
Descargas
-
https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz
SIZE: 20440715 SHA1: fb4ab2ceba8bf6a5b9bc7bf7cac945cc94f94c2b SHA256: daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272 SHA512: 94203051d20475b95a66660016721a0457d7ea57656a9f16cdd4264d8aa6c4cd8ea2fab659082611bfbd7b00ebbcf0391e883e2ebf384e4fab91869e0a877d35
-
https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.xz
SIZE: 15058364 SHA1: bcdae07183d66fd902cb7bf995545a472d2fefea SHA256: d2f4577306e6dd932259693233141e5c3ec13622c95b75996541b8d5b68b28b4 SHA512: 733ecc6709470ee16916deeece9af1c76220ae95d17b2681116aff7f381d99bc3124b1b11b1c2336b2b29e468e91b90f158d5ae5fca810c6cf32a0b6234ae08e
-
https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.zip
SIZE: 24583271 SHA1: 581ec7b9289c2a85abf4f41c93993ecaa5cf43a5 SHA256: cca9ddbc958431ff77f61948cb67afa569f01f99c9389d2bbedfa92986c9ef09 SHA512: b7d2753825cc0667e8bb391fc7ec59a53c3db5fa314e38eee74b6511890b585ac7515baa2ddac09e2c6b6c42b9221c82e040af5b39c73e980fbd3b1bc622c99d
Lo que es Ruby
Ruby fue desarrollado inicialmente por Matz (Yukihiro Matsumoto) en 1993, y ahora es desarrollado como Código Abierto. Corre en múltiples plataformas y se usa en todo el mundo especialmente para desarrollo web.