sorbet-runtime 0.5.5439 → 0.5.5449

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15b884405afe5ef1a9261206433553142c10166302d6bcc80e9ffed82343ac4c
4
- data.tar.gz: 2c5a550e1d9b9363cacefc36ce53fa86a3b36bde40f6f018e8bfad4632130a5b
3
+ metadata.gz: 86d060de12c48696ab8a6c9647bb57c006d71c23cd8e1256796b3057a436c050
4
+ data.tar.gz: 16a69f327d8477a9f8c0ea2320a226037489ad58fa0dab940a863819365c6ad5
5
5
  SHA512:
6
- metadata.gz: '0038a4dd9590fd6c8cdd30c41eea8767f2ad6c30e779979e8d4b880132c8d352343d0a46ef1ef1852edcadc157b28b09e498d356721d518734817e0759958aa1'
7
- data.tar.gz: c6e0dad262a7105db18b126d8fc01168ec3a3a7c5f6982f1753368561d77540b40384f7cfaed50e38e94767ff136a306c22d377b0c6db6ee965cd3d44f14a793
6
+ metadata.gz: eee05964b0496ec92f20dd35f425c375b7e5f20a856ef84a450383a5f164e62a76d0c94cda65074624b9730c6975563e3e9946525acccc532530d8fbce93540a
7
+ data.tar.gz: 0eed76a0fa31537f0362bc779b8787d59457c3c882d53432412b03a20015d77dbccb89556235a412d91a966fe45f8866e313dc9b352b6f53c52a7de38ae0ddc9
@@ -148,7 +148,24 @@ module T::Props
148
148
  assert_equal(s(:op_asgn, s(:lvasgn, :found), :-, s(:int, 1)), found_else_body)
149
149
 
150
150
  validate_deserialize_handle_nil(handle_nil)
151
- validate_lack_of_side_effects(else_body, whitelisted_methods_for_deserialize)
151
+
152
+ if else_body.type == :kwbegin
153
+ rescue_expression, = else_body.children
154
+ assert_equal(:rescue, rescue_expression.type)
155
+
156
+ try, rescue_body = rescue_expression.children
157
+ validate_lack_of_side_effects(try, whitelisted_methods_for_deserialize)
158
+
159
+ assert_equal(:resbody, rescue_body.type)
160
+ exceptions, assignment, handler = rescue_body.children
161
+ assert_equal(:array, exceptions.type)
162
+ exceptions.children.each {|c| assert_equal(:const, c.type)}
163
+ assert_equal(:lvasgn, assignment.type)
164
+ assert_equal([:e], assignment.children)
165
+ validate_lack_of_side_effects(handler, whitelisted_methods_for_deserialize)
166
+ else
167
+ validate_lack_of_side_effects(else_body, whitelisted_methods_for_deserialize)
168
+ end
152
169
  end
153
170
 
154
171
  private_class_method def self.validate_deserialize_handle_nil(node)
@@ -244,7 +261,7 @@ module T::Props
244
261
  private_class_method def self.whitelisted_methods_for_deserialize
245
262
  @whitelisted_methods_for_deserialize ||= {
246
263
  :lvar => %i{dup map transform_values transform_keys each_with_object nil? []=},
247
- :const => %i{deserialize from_hash deep_clone_object},
264
+ :const => %i{deserialize from_hash deep_clone_object soft_assert_handler},
248
265
  }
249
266
  end
250
267
  end
@@ -43,11 +43,33 @@ module T::Props
43
43
  ivar_name = rules.fetch(:accessor_key).to_s
44
44
  raise unless ivar_name.start_with?('@') && T::Props::Decorator::SAFE_NAME.match?(ivar_name[1..-1])
45
45
 
46
- transformed_val = SerdeTransform.generate(
46
+ transformation = SerdeTransform.generate(
47
47
  T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object)),
48
48
  SerdeTransform::Mode::DESERIALIZE,
49
49
  'val'
50
- ) || 'val'
50
+ )
51
+ if transformation
52
+ # Rescuing exactly NoMethodError is intended as a temporary hack
53
+ # to preserve the semantics from before codegen. More generally
54
+ # we are inconsistent about typechecking on deser and need to decide
55
+ # our strategy here.
56
+ transformed_val = <<~RUBY
57
+ begin
58
+ #{transformation}
59
+ rescue NoMethodError => e
60
+ T::Configuration.soft_assert_handler(
61
+ 'Deserialization error (probably unexpected stored type)',
62
+ klass: self.class,
63
+ prop: #{prop.inspect},
64
+ value: val,
65
+ error: e.message
66
+ )
67
+ val
68
+ end
69
+ RUBY
70
+ else
71
+ transformed_val = 'val'
72
+ end
51
73
 
52
74
  nil_handler = generate_nil_handler(
53
75
  prop: prop,
@@ -69,6 +69,16 @@ module T::Props
69
69
  handle_serializable_subtype(varname, raw, mode)
70
70
  elsif raw.singleton_class < T::Props::CustomType
71
71
  handle_custom_type(varname, T.unsafe(raw), mode)
72
+ elsif T::Configuration.scalar_types.include?(raw.name)
73
+ # It's a bit of a hack that this is separate from NO_TRANSFORM_TYPES
74
+ # and doesn't check inheritance (like `T::Props::CustomType.scalar_type?`
75
+ # does), but it covers the main use case (pay-server's custom `Boolean`
76
+ # module) without either requiring `T::Configuration.scalar_types` to
77
+ # accept modules instead of strings (which produces load-order issues
78
+ # and subtle behavior changes) or eating the performance cost of doing
79
+ # an inheritance check by manually crawling a class hierarchy and doing
80
+ # string comparisons.
81
+ nil
72
82
  else
73
83
  "T::Props::Utils.deep_clone_object(#{varname})"
74
84
  end
@@ -82,7 +92,12 @@ module T::Props
82
92
  "#{varname}.nil? ? nil : #{inner}"
83
93
  end
84
94
  else
85
- "T::Props::Utils.deep_clone_object(#{varname})"
95
+ # Handle, e.g., T::Boolean
96
+ if type.types.all? {|t| generate(t, mode, varname).nil?}
97
+ nil
98
+ else
99
+ "T::Props::Utils.deep_clone_object(#{varname})"
100
+ end
86
101
  end
87
102
  when T::Types::Enum
88
103
  generate(T::Utils.lift_enum(type), mode, varname)
@@ -16,7 +16,21 @@ module T::Props::Serializable
16
16
  # values.
17
17
  # @return [Hash] A serialization of this object.
18
18
  def serialize(strict=true)
19
- h = __t_props_generated_serialize(strict)
19
+ begin
20
+ h = __t_props_generated_serialize(strict)
21
+ rescue => e
22
+ msg = self.class.decorator.message_with_generated_source_context(
23
+ e,
24
+ :__t_props_generated_serialize,
25
+ :generate_serialize_source
26
+ )
27
+ if msg
28
+ raise T::Props::InvalidValueError.new(msg)
29
+ else
30
+ raise
31
+ end
32
+ end
33
+
20
34
  h.merge!(@_extra_props) if @_extra_props
21
35
  h
22
36
  end
@@ -39,7 +53,21 @@ module T::Props::Serializable
39
53
  # props on this instance.
40
54
  # @return [void]
41
55
  def deserialize(hash, strict=false)
42
- hash_keys_matching_props = __t_props_generated_deserialize(hash)
56
+ begin
57
+ hash_keys_matching_props = __t_props_generated_deserialize(hash)
58
+ rescue => e
59
+ msg = self.class.decorator.message_with_generated_source_context(
60
+ e,
61
+ :__t_props_generated_deserialize,
62
+ :generate_deserialize_source
63
+ )
64
+ if msg
65
+ raise T::Props::InvalidValueError.new(msg)
66
+ else
67
+ raise
68
+ end
69
+ end
70
+
43
71
  if hash.size > hash_keys_matching_props
44
72
  serialized_forms = self.class.decorator.prop_by_serialized_forms
45
73
  extra = hash.reject {|k, _| serialized_forms.key?(k)}
@@ -181,6 +209,24 @@ module T::Props::Serializable::DecoratorMethods
181
209
  )
182
210
  end
183
211
 
212
+ def message_with_generated_source_context(error, generated_method, generate_source_method)
213
+ line_label = error.backtrace.find {|l| l.end_with?("in `#{generated_method}'")}
214
+ return unless line_label
215
+
216
+ line_num = line_label.split(':')[1]&.to_i
217
+ return unless line_num
218
+
219
+ source_lines = self.send(generate_source_method).split("\n")
220
+ previous_blank = source_lines[0...line_num].rindex(&:empty?) || 0
221
+ next_blank = line_num + (source_lines[line_num..-1].find_index(&:empty?) || 0)
222
+ context = " " + source_lines[(previous_blank + 1)...(next_blank)].join("\n ")
223
+ <<~MSG
224
+ Error in #{decorated_class.name}##{generated_method}: #{error.message}
225
+ at line #{line_num-previous_blank-1} in:
226
+ #{context}
227
+ MSG
228
+ end
229
+
184
230
  def raise_nil_deserialize_error(hkey)
185
231
  msg = "Tried to deserialize a required prop from a nil value. It's "\
186
232
  "possible that a nil value exists in the database, so you should "\
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5439
4
+ version: 0.5.5449
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-14 00:00:00.000000000 Z
11
+ date: 2020-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest