[ruby/prism] Mark Prism as ractor-safe
https://github.com/ruby/prism/commit/c02429765b
This commit is contained in:
parent
050ffab82b
commit
641f15b1c6
@ -7,6 +7,10 @@
|
||||
require "rbconfig"
|
||||
require "ffi"
|
||||
|
||||
# We want to eagerly load this file if there are Ractors so that it does not get
|
||||
# autoloaded from within a non-main Ractor.
|
||||
require "prism/serialize" if defined?(Ractor)
|
||||
|
||||
module Prism
|
||||
module LibRubyParser # :nodoc:
|
||||
extend FFI::Library
|
||||
@ -159,6 +163,9 @@ module Prism
|
||||
class PrismString # :nodoc:
|
||||
SIZEOF = LibRubyParser.pm_string_sizeof
|
||||
|
||||
PLATFORM_EXPECTS_UTF8 =
|
||||
RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i)
|
||||
|
||||
attr_reader :pointer, :length
|
||||
|
||||
def initialize(pointer, length, from_string)
|
||||
@ -193,8 +200,7 @@ module Prism
|
||||
# On Windows and Mac, it's expected that filepaths will be encoded in
|
||||
# UTF-8. If they are not, we need to convert them to UTF-8 before
|
||||
# passing them into pm_string_mapped_init.
|
||||
if RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i) &&
|
||||
(encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8
|
||||
if PLATFORM_EXPECTS_UTF8 && (encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8
|
||||
filepath = filepath.encode(Encoding::UTF_8)
|
||||
end
|
||||
|
||||
@ -223,7 +229,7 @@ module Prism
|
||||
private_constant :LibRubyParser
|
||||
|
||||
# The version constant is set by reading the result of calling pm_version.
|
||||
VERSION = LibRubyParser.pm_version.read_string
|
||||
VERSION = LibRubyParser.pm_version.read_string.freeze
|
||||
|
||||
class << self
|
||||
# Mirror the Prism.dump API by using the serialization API.
|
||||
|
@ -1331,6 +1331,11 @@ Init_prism(void) {
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
||||
// Mark this extension as Ractor-safe.
|
||||
rb_ext_ractor_safe(true);
|
||||
#endif
|
||||
|
||||
// Grab up references to all of the constants that we're going to need to
|
||||
// reference throughout this extension.
|
||||
rb_cPrism = rb_define_module("Prism");
|
||||
|
@ -592,7 +592,7 @@ module Prism
|
||||
<%- tokens.each do |token| -%>
|
||||
<%= token.name.to_sym.inspect %>,
|
||||
<%- end -%>
|
||||
]
|
||||
].freeze
|
||||
|
||||
private_constant :MAJOR_VERSION, :MINOR_VERSION, :PATCH_VERSION
|
||||
private_constant :ConstantPool, :FastStringIO, :Loader, :TOKEN_TYPES
|
||||
|
77
test/prism/ractor_test.rb
Normal file
77
test/prism/ractor_test.rb
Normal file
@ -0,0 +1,77 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
return unless defined?(Ractor)
|
||||
|
||||
require_relative "test_helper"
|
||||
|
||||
return if Prism::TestCase.windows?
|
||||
|
||||
module Prism
|
||||
class RactorTest < TestCase
|
||||
def test_version
|
||||
assert_match(/\A\d+\.\d+\.\d+\z/, with_ractor { Prism::VERSION })
|
||||
end
|
||||
|
||||
def test_parse_file
|
||||
assert_equal("Prism::ParseResult", with_ractor(__FILE__) { |filepath| Prism.parse_file(filepath).class })
|
||||
end
|
||||
|
||||
def test_lex_file
|
||||
assert_equal("Prism::LexResult", with_ractor(__FILE__) { |filepath| Prism.lex_file(filepath).class })
|
||||
end
|
||||
|
||||
def test_parse_file_comments
|
||||
assert_equal("Array", with_ractor(__FILE__) { |filepath| Prism.parse_file_comments(filepath).class })
|
||||
end
|
||||
|
||||
def test_parse_lex_file
|
||||
assert_equal("Prism::ParseLexResult", with_ractor(__FILE__) { |filepath| Prism.parse_lex_file(filepath).class })
|
||||
end
|
||||
|
||||
def test_parse_success
|
||||
assert_equal("true", with_ractor("1 + 1") { |source| Prism.parse_success?(source) })
|
||||
end
|
||||
|
||||
def test_parse_failure
|
||||
assert_equal("true", with_ractor("1 +") { |source| Prism.parse_failure?(source) })
|
||||
end
|
||||
|
||||
def test_string_query_local
|
||||
assert_equal("true", with_ractor("foo") { |source| StringQuery.local?(source) })
|
||||
end
|
||||
|
||||
def test_string_query_constant
|
||||
assert_equal("true", with_ractor("FOO") { |source| StringQuery.constant?(source) })
|
||||
end
|
||||
|
||||
def test_string_query_method_name
|
||||
assert_equal("true", with_ractor("foo?") { |source| StringQuery.method_name?(source) })
|
||||
end
|
||||
|
||||
if !ENV["PRISM_BUILD_MINIMAL"]
|
||||
def test_dump_file
|
||||
result = with_ractor(__FILE__) { |filepath| Prism.dump_file(filepath) }
|
||||
assert_operator(result, :start_with?, "PRISM")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Note that this must be done in a subprocess, otherwise it can mess up
|
||||
# CRuby's test suite.
|
||||
def with_ractor(*arguments, &block)
|
||||
reader, writer = IO.pipe
|
||||
|
||||
pid = fork do
|
||||
reader.close
|
||||
writer.puts(ignore_warnings { Ractor.new(*arguments, &block) }.take)
|
||||
end
|
||||
|
||||
writer.close
|
||||
result = reader.gets.chomp
|
||||
|
||||
Process.wait(pid)
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
@ -339,7 +339,7 @@ module Prism
|
||||
assert_warning("tap { redo; foo }", "statement not reached")
|
||||
end
|
||||
|
||||
if RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince/i)
|
||||
if windows?
|
||||
def test_shebang_ending_with_carriage_return
|
||||
refute_warning("#!ruby\r\np(123)\n", compare: false)
|
||||
end
|
||||
|
@ -212,6 +212,11 @@ module Prism
|
||||
yield Encoding::EUC_TW, codepoints_euc_tw
|
||||
end
|
||||
|
||||
# True if the current platform is Windows.
|
||||
def self.windows?
|
||||
RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince/i)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
if RUBY_ENGINE == "ruby" && RubyVM::InstructionSequence.compile("").to_a[4][:parser] != :prism
|
||||
|
Loading…
x
Reference in New Issue
Block a user