Skip to content

Commit 242e99e

Browse files
kddnewtonmatzbot
authored andcommitted
[ruby/prism] Mark extension as Ractor-safe
ruby/prism@10e5431b38
1 parent 08b3a45 commit 242e99e

File tree

4 files changed

+76
-4
lines changed

4 files changed

+76
-4
lines changed

lib/prism/ffi.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
require "rbconfig"
88
require "ffi"
99

10+
# We want to eagerly load this file if there are Ractors so that it does not get
11+
# autoloaded from within a non-main Ractor.
12+
require "prism/serialize" if defined?(Ractor)
13+
1014
module Prism
1115
module LibRubyParser # :nodoc:
1216
extend FFI::Library
@@ -159,6 +163,9 @@ def self.with
159163
class PrismString # :nodoc:
160164
SIZEOF = LibRubyParser.pm_string_sizeof
161165

166+
PLATFORM_EXPECTS_UTF8 =
167+
RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i)
168+
162169
attr_reader :pointer, :length
163170

164171
def initialize(pointer, length, from_string)
@@ -193,8 +200,7 @@ def self.with_file(filepath)
193200
# On Windows and Mac, it's expected that filepaths will be encoded in
194201
# UTF-8. If they are not, we need to convert them to UTF-8 before
195202
# passing them into pm_string_mapped_init.
196-
if RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i) &&
197-
(encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8
203+
if PLATFORM_EXPECTS_UTF8 && (encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8
198204
filepath = filepath.encode(Encoding::UTF_8)
199205
end
200206

@@ -223,7 +229,7 @@ def self.with_file(filepath)
223229
private_constant :LibRubyParser
224230

225231
# The version constant is set by reading the result of calling pm_version.
226-
VERSION = LibRubyParser.pm_version.read_string
232+
VERSION = LibRubyParser.pm_version.read_string.freeze
227233

228234
class << self
229235
# Mirror the Prism.dump API by using the serialization API.

prism/extension.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,11 @@ Init_prism(void) {
13311331
);
13321332
}
13331333

1334+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
1335+
// Mark this extension as Ractor-safe.
1336+
rb_ext_ractor_safe(true);
1337+
#endif
1338+
13341339
// Grab up references to all of the constants that we're going to need to
13351340
// reference throughout this extension.
13361341
rb_cPrism = rb_define_module("Prism");

prism/templates/lib/prism/serialize.rb.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ module Prism
592592
<%- tokens.each do |token| -%>
593593
<%= token.name.to_sym.inspect %>,
594594
<%- end -%>
595-
]
595+
].freeze
596596

597597
private_constant :MAJOR_VERSION, :MINOR_VERSION, :PATCH_VERSION
598598
private_constant :ConstantPool, :FastStringIO, :Loader, :TOKEN_TYPES

test/prism/ractor_test.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# frozen_string_literal: true
2+
3+
return unless defined?(Ractor)
4+
5+
require_relative "test_helper"
6+
7+
module Prism
8+
class RactorTest < TestCase
9+
def test_version
10+
refute_nil(with_ractor { Prism::VERSION })
11+
end
12+
13+
def test_parse_file
14+
assert_kind_of(Prism::Result, with_ractor(__FILE__) { |filepath| Prism.parse_file(filepath) })
15+
end
16+
17+
def test_lex_file
18+
assert_kind_of(Prism::Result, with_ractor(__FILE__) { |filepath| Prism.lex_file(filepath) })
19+
end
20+
21+
def test_parse_file_comments
22+
assert_kind_of(Array, with_ractor(__FILE__) { |filepath| Prism.parse_file_comments(filepath) })
23+
end
24+
25+
def test_parse_lex_file
26+
assert_kind_of(Prism::Result, with_ractor(__FILE__) { |filepath| Prism.parse_lex_file(filepath) })
27+
end
28+
29+
def test_parse_success
30+
assert(with_ractor("1 + 1") { |source| Prism.parse_success?(source) })
31+
end
32+
33+
def test_parse_failure
34+
assert(with_ractor("1 +") { |source| Prism.parse_failure?(source) })
35+
end
36+
37+
def test_string_query_local
38+
assert(with_ractor("foo") { |source| StringQuery.local?(source) })
39+
end
40+
41+
def test_string_query_constant
42+
assert(with_ractor("FOO") { |source| StringQuery.constant?(source) })
43+
end
44+
45+
def test_string_query_method_name
46+
assert(with_ractor("foo?") { |source| StringQuery.method_name?(source) })
47+
end
48+
49+
if !ENV["PRISM_BUILD_MINIMAL"]
50+
def test_dump_file
51+
assert_kind_of(String, with_ractor(__FILE__) { |filepath| Prism.dump_file(filepath) })
52+
end
53+
end
54+
55+
private
56+
57+
def with_ractor(*arguments, &block)
58+
ignore_warnings { Ractor.new(*arguments, &block) }.take
59+
end
60+
end
61+
end

0 commit comments

Comments
 (0)