sorbet-runtime 0.5.5439 → 0.5.5449
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86d060de12c48696ab8a6c9647bb57c006d71c23cd8e1256796b3057a436c050
|
4
|
+
data.tar.gz: 16a69f327d8477a9f8c0ea2320a226037489ad58fa0dab940a863819365c6ad5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
-
)
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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-
|
11
|
+
date: 2020-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|