Phát hành Ruby 3.2.0 Preview 3

Đăng bởi naruse vào 11 Nov 2022

Chúng tôi vui mừng thông báo phát hành Ruby 3.2.0-preview3. Ruby 3.2 bổ sung nhiều tính năng và cải thiện hiệu suất.

Hỗ trợ WebAssembly dựa trên WASI

Đây là bản port ban đầu của hỗ trợ WebAssembly dựa trên WASI. Bản port này cho phép tệp nhị phân CRuby có thể sử dụng trên trình duyệt Web, môi trường Serverless Edge và các trình nhúng WebAssembly/WASI khác. Hiện tại bản port này vượt qua các bộ test cơ bản và bootstrap mà không sử dụng Thread API.

Bối cảnh

WebAssembly (Wasm) ban đầu được giới thiệu để chạy chương trình một cách an toàn và nhanh chóng trên trình duyệt web. Nhưng mục tiêu của nó - chạy chương trình hiệu quả với bảo mật trên nhiều môi trường khác nhau - đã được mong đợi từ lâu không chỉ cho web mà còn cho các ứng dụng nói chung.

WASI (The WebAssembly System Interface) được thiết kế cho các trường hợp sử dụng như vậy. Mặc dù các ứng dụng này cần giao tiếp với hệ điều hành, WebAssembly chạy trên một máy ảo không có giao diện hệ thống. WASI chuẩn hóa điều đó.

Hỗ trợ WebAssembly/WASI trong Ruby nhằm tận dụng các dự án này. Nó cho phép các nhà phát triển Ruby viết ứng dụng chạy trên nền tảng đầy hứa hẹn đó.

Trường hợp sử dụng

Hỗ trợ này khuyến khích các nhà phát triển có thể sử dụng CRuby trong môi trường WebAssembly. Một ví dụ trường hợp sử dụng là hỗ trợ CRuby của TryRuby playground. Bây giờ bạn có thể thử CRuby gốc ngay trong trình duyệt web của mình.

Các điểm kỹ thuật

WASI và WebAssembly hiện tại vẫn thiếu một số tính năng để triển khai Fiber, exception và GC vì nó vẫn đang phát triển và cũng vì lý do bảo mật. Vì vậy CRuby lấp đầy khoảng trống bằng cách sử dụng Asyncify, một kỹ thuật chuyển đổi nhị phân để điều khiển thực thi trong userland.

Ngoài ra, chúng tôi đã xây dựng VFS trên WASI để có thể dễ dàng đóng gói ứng dụng Ruby thành một tệp .wasm duy nhất. Điều này giúp việc phân phối ứng dụng Ruby dễ dàng hơn một chút.

Liên kết liên quan

Cải thiện Regexp chống ReDoS

Được biết rằng việc khớp Regexp có thể mất thời gian dài bất ngờ. Nếu mã của bạn cố gắng khớp một Regexp có thể không hiệu quả với đầu vào không tin cậy, kẻ tấn công có thể khai thác nó để tấn công từ chối dịch vụ hiệu quả (gọi là Regular expression DoS, hoặc ReDoS).

Chúng tôi đã giới thiệu hai cải tiến giúp giảm thiểu đáng kể ReDoS.

Cải thiện thuật toán khớp Regexp

Kể từ Ruby 3.2, thuật toán khớp của Regexp đã được cải thiện đáng kể bằng kỹ thuật ghi nhớ (memoization).

# This matching takes 10 sec. in Ruby 3.1, and does 0.003 sec. in Ruby 3.2

/^a*b?a*$/ =~ "a" * 50000 + "x"

Thuật toán khớp cải tiến cho phép hầu hết các phép khớp Regexp (khoảng 90% trong các thí nghiệm của chúng tôi) được hoàn thành trong thời gian tuyến tính.

(Cho người dùng preview: tối ưu hóa này có thể tiêu thụ bộ nhớ tỷ lệ thuận với độ dài đầu vào cho mỗi lần khớp. Chúng tôi dự kiến không có vấn đề thực tế nào phát sinh vì việc cấp phát bộ nhớ này thường bị trì hoãn, và một phép khớp Regexp bình thường nên tiêu thụ tối đa 10 lần bộ nhớ so với độ dài đầu vào. Nếu bạn hết bộ nhớ khi khớp Regexp trong ứng dụng thực tế, vui lòng báo cáo.)

Đề xuất ban đầu là https://bugs.ruby-lang.org/issues/19104

Thời gian chờ Regexp

Tối ưu hóa ở trên không thể áp dụng cho một số loại biểu thức chính quy, chẳng hạn như những biểu thức bao gồm các tính năng nâng cao (ví dụ: tham chiếu ngược hoặc look-around), hoặc với số lần lặp cố định lớn. Như một biện pháp dự phòng, tính năng thời gian chờ cho khớp Regexp cũng được giới thiệu.

Regexp.timeout = 1.0

/^a*b?a*()\1$/ =~ "a" * 50000 + "x"
#=> Regexp::TimeoutError is raised in one second

Lưu ý rằng Regexp.timeout là cấu hình toàn cục. Nếu bạn muốn sử dụng các cài đặt thời gian chờ khác nhau cho một số Regexp đặc biệt, bạn có thể sử dụng từ khóa timeout cho Regexp.new.

Regexp.timeout = 1.0

# This regexp has no timeout
long_time_re = Regexp.new('^a*b?a*()\1$', timeout: Float::INFINITY)

long_time_re =~ "a" * 50000 + "x" # never interrupted

Đề xuất ban đầu là https://bugs.ruby-lang.org/issues/17837

Các tính năng mới đáng chú ý khác

Không còn đi kèm mã nguồn bên thứ ba

  • Chúng tôi không còn đi kèm mã nguồn bên thứ ba như libyaml, libffi.

    • Mã nguồn libyaml đã được xóa khỏi psych. Bạn có thể cần cài đặt libyaml-dev trên nền tảng Ubuntu/Debian. Tên gói khác nhau trên mỗi nền tảng.

    • Mã nguồn libffi đi kèm cũng đã được xóa khỏi fiddle

Ngôn ngữ

  • Các tham số rest và keyword rest ẩn danh giờ đây có thể được truyền làm đối số, thay vì chỉ được sử dụng trong tham số phương thức. [Feature #18351]

      def foo(*)
        bar(*)
      end
      def baz(**)
        quux(**)
      end
    
  • Một proc nhận một tham số vị trí duy nhất và từ khóa sẽ không còn tự động tách (autosplat). [Bug #18633]

    proc{|a, **k| a}.call([1, 2])
    # Ruby 3.1 and before
    # => 1
    # Ruby 3.2 and after
    # => [1, 2]
    
  • Thứ tự đánh giá gán hằng số cho các hằng số được đặt trên đối tượng tường minh đã được làm nhất quán với thứ tự đánh giá gán thuộc tính đơn. Với mã này:

      foo::BAR = baz
    

    foo giờ được gọi trước baz. Tương tự, cho các phép gán đa hằng số, thứ tự đánh giá từ trái sang phải được sử dụng. Với mã này:

        foo1::BAR1, foo2::BAR2 = baz1, baz2
    

    Thứ tự đánh giá sau đây được sử dụng:

    1. foo1
    2. foo2
    3. baz1
    4. baz2

    [Bug #15928]

  • Find pattern không còn là tính năng thử nghiệm. [Feature #18585]

  • Các phương thức nhận tham số rest (như *args) và muốn ủy quyền tham số từ khóa qua foo(*args) giờ phải được đánh dấu bằng ruby2_keywords (nếu chưa có). Nói cách khác, tất cả các phương thức muốn ủy quyền tham số từ khóa qua *args giờ phải được đánh dấu bằng ruby2_keywords, không có ngoại lệ. Điều này sẽ giúp dễ dàng chuyển sang các cách ủy quyền khác khi thư viện có thể yêu cầu Ruby 3+. Trước đây, cờ ruby2_keywords được giữ lại nếu phương thức nhận nhận *args, nhưng đây là lỗi và không nhất quán. Một kỹ thuật tốt để tìm các ruby2_keywords có thể bị thiếu là chạy bộ test, tìm nơi test thất bại và tìm phương thức cuối phải nhận tham số từ khóa, sử dụng puts nil, caller, nil ở đó, rồi kiểm tra từng phương thức/block trên chuỗi gọi phải ủy quyền từ khóa được đánh dấu đúng bằng ruby2_keywords. [Bug #18625] [Bug #16466]

      def target(**kw)
      end
    
      # Accidentally worked without ruby2_keywords in Ruby 2.7-3.1, ruby2_keywords
      # needed in 3.2+. Just like (*args, **kwargs) or (...) would be needed on
      # both #foo and #bar when migrating away from ruby2_keywords.
      ruby2_keywords def bar(*args)
        target(*args)
      end
    
      ruby2_keywords def foo(*args)
        bar(*args)
      end
    
      foo(k: 1)
    

Cải thiện hiệu suất

YJIT

  • Hỗ trợ arm64 / aarch64 trên các nền tảng UNIX.
  • Xây dựng YJIT yêu cầu Rust 1.58.1+. [Feature #18481]

Các thay đổi đáng chú ý khác kể từ 3.1

  • Hash
    • Hash#shift now always returns nil if the hash is empty, instead of returning the default value or calling the default proc. [Bug #16908]
  • MatchData
  • Module
  • Proc
  • Refinement
  • RubyVM::AbstractSyntaxTree
    • Add error_tolerant option for parse, parse_file and of. [Feature #19013]
  • Set
    • Set is now available as a builtin class without the need for require "set". [Feature #16989] It is currently autoloaded via the Set constant or a call to Enumerable#to_set.
  • String
    • String#byteindex and String#byterindex have been added. [Feature #13110]
    • Update Unicode to Version 14.0.0 and Emoji Version 14.0. [Feature #18037] (also applies to Regexp)
    • String#bytesplice has been added. [Feature #18598]
  • Struct
    • A Struct class can also be initialized with keyword arguments without keyword_init: true on Struct.new [Feature #16806]

Vấn đề tương thích

Lưu ý: Không bao gồm các bản sửa lỗi tính năng.

Các hằng số đã bị xóa

Các hằng số không dùng nữa sau đã bị xóa.

Các phương thức đã bị xóa

Các phương thức không dùng nữa sau đã bị xóa.

Vấn đề tương thích Stdlib

  • Psych không còn đi kèm mã nguồn libyaml. Người dùng cần tự cài đặt thư viện libyaml qua hệ thống gói. [Feature #18571]

Cập nhật C API

Các C API đã cập nhật

Các API sau đã được cập nhật.

  • PRNG update rb_random_interface_t updated and versioned. Extension libraries which use this interface and built for older versions. Also init_int32 function needs to be defined.

Các C API đã bị xóa

Các API không dùng nữa sau đã bị xóa.

  • rb_cData variable.
  • “taintedness” and “trustedness” functions. [Feature #16131]

Cập nhật thư viện chuẩn

  • SyntaxSuggest

    • Tính năng syntax_suggest trước đây là dead_end đã được tích hợp vào Ruby. [Feature #18159]
  • ErrorHighlight

    • Giờ nó chỉ ra (các) đối số của TypeError và ArgumentError
test.rb:2:in `+': nil can't be coerced into Integer (TypeError)

sum = ary[0] + ary[1]
               ^^^^^^
  • Các gem mặc định sau đã được cập nhật.
    • RubyGems 3.4.0.dev
    • bigdecimal 3.1.2
    • bundler 2.4.0.dev
    • cgi 0.3.2
    • date 3.2.3
    • error_highlight 0.4.0
    • etc 1.4.0
    • io-console 0.5.11
    • io-nonblock 0.1.1
    • io-wait 0.3.0.pre
    • ipaddr 1.2.4
    • json 2.6.2
    • logger 1.5.1
    • net-http 0.2.2
    • net-protocol 0.1.3
    • ostruct 0.5.5
    • psych 5.0.0.dev
    • reline 0.3.1
    • securerandom 0.2.0
    • set 1.0.3
    • stringio 3.0.3
    • syntax_suggest 0.0.1
    • timeout 0.3.0
  • Các gem đi kèm sau đã được cập nhật.
    • minitest 5.16.3
    • net-imap 0.2.3
    • rbs 2.6.0
    • typeprof 0.21.3
    • debug 1.6.2
  • Các gem mặc định sau giờ là gem đi kèm.

Xem NEWS hoặc nhật ký commit để biết thêm chi tiết.

Với những thay đổi đó, 2719 tệp đã thay đổi, 191269 thêm(+), 120315 xóa(-) kể từ Ruby 3.1.0!

Tải về

  • https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0-preview3.tar.gz

    SIZE: 20086542
    SHA1: dafca8116d36ceaa32482ab38359768de8c3ae5e
    SHA256: c041d1488e62730d3a10dbe7cf7a3b3e4268dc867ec20ec991e7d16146640487
    SHA512: 860634d95e4b9c48f18d38146dfbdc3c389666d45454248a4ccdfc3a5d3cd0c71c73533aabf359558117de9add1472af228d8eaec989c9336b1a3a6f03f1ae88
    
  • https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0-preview3.tar.xz

    SIZE: 14799804
    SHA1: c94e2add05502cb5c39afffc995b7c8f000f7df0
    SHA256: d3f5619de544240d92a5d03aa289e71bd1103379622c523a0e80ed029a74b3bb
    SHA512: c1864e2e07c3711eaa17d0f85dfbcc6e0682b077782bb1c155315af45139ae66dc4567c73682d326975b0f472111eb0a70f949811cb54bed0b3a816ed6ac34df
    
  • https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0-preview3.zip

    SIZE: 24426893
    SHA1: 346c051c4be7ab8d0b551fd2ff8169785697db62
    SHA256: cf49aa70e7ebd8abebffd5e49cd3bd92e5b9f3782d587cc7ed88c98dd5f17069
    SHA512: 4f22b5ea91be17ef5f68cf0acb1e3a226dcc549ad71cc9b40e623220087c4065ca9bea942710f668e5c94ca0323da8d2ccd565f95a9085c1a0e38e9c0543b22f
    

Ruby là gì

Ruby được phát triển lần đầu bởi Matz (Yukihiro Matsumoto) vào năm 1993, và hiện được phát triển dưới dạng Mã nguồn Mở. Nó chạy trên nhiều nền tảng và được sử dụng trên toàn thế giới, đặc biệt cho phát triển web.

Tin mới nhất

Phát hành Ruby 4.0.0

Chúng tôi vui mừng thông báo phát hành Ruby 4.0.0. Ruby 4.0 giới thiệu “Ruby Box” và “ZJIT”, cùng nhiều cải tiến khác.

Đăng bởi naruse vào 25 Dec 2025

Diện mạo mới cho tài liệu Ruby

Tiếp theo việc thiết kế lại ruby-lang.org, chúng tôi có thêm tin vui để kỷ niệm 30 năm Ruby: docs.ruby-lang.org có diện mạo hoàn toàn...

Đăng bởi Stan Lo vào 23 Dec 2025

Thêm Tin...