@@ -553,7 +553,18 @@ def add_object(obj)
553
553
end
554
554
555
555
def add_symlink ( obj )
556
- sz = @symlinks . size
556
+ sz = @symbols . size
557
+ @symbols [ sz ] = obj
558
+ @symlinks [ obj . __id__ ] = sz
559
+ end
560
+
561
+ def reserve_symlink
562
+ sz = @symbols . size
563
+ @symbols [ sz ] = nil
564
+ sz
565
+ end
566
+
567
+ def assign_reserved_symlink ( sz , obj )
557
568
@symbols [ sz ] = obj
558
569
@symlinks [ obj . __id__ ] = sz
559
570
end
@@ -848,7 +859,6 @@ def construct_regexp
848
859
849
860
def construct_struct
850
861
name = get_symbol
851
- store_unique_object name
852
862
853
863
klass = const_lookup name , Class
854
864
members = klass . members
@@ -859,8 +869,7 @@ def construct_struct
859
869
construct_integer . times do |i |
860
870
slot = get_symbol
861
871
unless members [ i ] . intern == slot
862
- raise TypeError , 'struct %s is not compatible (%p for %p)' %
863
- [ klass , slot , members [ i ] ]
872
+ raise TypeError , "struct #{ klass } is not compatible (#{ slot . inspect } for #{ members [ i ] . inspect } )"
864
873
end
865
874
866
875
Primitive . object_hidden_var_set obj , slot , construct
@@ -872,6 +881,12 @@ def construct_struct
872
881
def construct_symbol ( ivar_index )
873
882
data = get_byte_sequence
874
883
884
+ # We must use the next @symbols index for the Symbol being constructed.
885
+ # However, constructing a Symbol might require to construct the :E or :encoding symbols,
886
+ # and those must have a larger index (if they are serialized for the first time),
887
+ # to be binary-compatible with CRuby and pass specs. So we reserve the index and assign it later.
888
+ idx = reserve_symlink
889
+
875
890
# A Symbol has no instance variables (it's frozen),
876
891
# but we need to know the encoding before building the Symbol
877
892
if ivar_index and @has_ivar [ ivar_index ]
@@ -881,7 +896,7 @@ def construct_symbol(ivar_index)
881
896
end
882
897
883
898
obj = data . to_sym
884
- store_unique_object obj
899
+ assign_reserved_symlink idx , obj
885
900
886
901
obj
887
902
end
@@ -910,7 +925,6 @@ def construct_user_defined(ivar_index)
910
925
911
926
def construct_user_marshal
912
927
name = get_symbol
913
- store_unique_object name
914
928
915
929
klass = const_lookup name , Class
916
930
obj = klass . allocate
@@ -976,7 +990,7 @@ def serialize(obj)
976
990
raise ArgumentError , 'exceed depth limit' if @depth == 0
977
991
978
992
# How much depth we have left.
979
- @depth -= 1 ;
993
+ @depth -= 1
980
994
981
995
if link = find_link ( obj )
982
996
str = Truffle ::Type . binary_string ( "@#{ serialize_integer ( link ) } " )
@@ -1249,7 +1263,10 @@ def initialize(stream, depth, prc)
1249
1263
if @stream
1250
1264
@byte_array = stream . bytes
1251
1265
end
1266
+ end
1252
1267
1268
+ def inspect
1269
+ "#<Marshal::StringState #{ @stream [ @consumed ..-1 ] . inspect } >"
1253
1270
end
1254
1271
1255
1272
def consume ( bytes )
0 commit comments