sorbet-runtime 0.5.8993 → 0.5.9103
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 +4 -4
- data/lib/sorbet-runtime.rb +3 -0
- data/lib/types/_types.rb +0 -2
- data/lib/types/configuration.rb +14 -4
- data/lib/types/enum.rb +1 -6
- data/lib/types/private/casts.rb +0 -8
- data/lib/types/private/compiler.rb +24 -0
- data/lib/types/private/methods/_methods.rb +6 -2
- data/lib/types/private/methods/decl_builder.rb +5 -5
- data/lib/types/private/methods/modes.rb +18 -6
- data/lib/types/private/methods/signature_validation.rb +1 -2
- data/lib/types/private/runtime_levels.rb +7 -1
- data/lib/types/props/_props.rb +15 -5
- data/lib/types/props/decorator.rb +9 -3
- data/lib/types/props/generated_code_validation.rb +1 -1
- data/lib/types/props/optional.rb +3 -3
- data/lib/types/props/private/serializer_generator.rb +0 -1
- data/lib/types/props/serializable.rb +15 -12
- data/lib/types/types/fixed_hash.rb +16 -10
- data/lib/types/types/self_type.rb +3 -3
- data/lib/types/types/simple.rb +10 -2
- data/lib/types/utils.rb +8 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dd50aa97fa3835f75f05ddad407ced4062053e791cb9c246a4ac617cb6e4eeb5
|
|
4
|
+
data.tar.gz: dd7a5031c72ae5ce3a09324d2b110c343e1409e350c12b1a8bf8a1bf21763c90
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa6efdc3b42d1b42322af825df44bf33c625cc24b2d93f5474887218f686604e8603db6c19afae00c29c6e32e1e1ecceb52a07de68471ec9cf18aea01ab98ef4
|
|
7
|
+
data.tar.gz: a16780c9665e17e0666d2e2b04a5b60a04a7b02863f111d3a068e2b5c7b32b72334b246b00e76ddfa98d1a64fd78c79fa1467e03d19d80203c0bc5ccacf28b6c
|
data/lib/sorbet-runtime.rb
CHANGED
data/lib/types/_types.rb
CHANGED
|
@@ -78,10 +78,8 @@ module T
|
|
|
78
78
|
T::Types::ClassOf.new(klass)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
|
|
82
81
|
## END OF THE METHODS TO PASS TO `sig`.
|
|
83
82
|
|
|
84
|
-
|
|
85
83
|
# Constructs a type alias. Used to create a short name for a larger type. In Ruby this returns a
|
|
86
84
|
# wrapper that contains a proc that is evaluated to get the underlying type. This syntax however
|
|
87
85
|
# is needed for support by the static checker. Example usage:
|
data/lib/types/configuration.rb
CHANGED
|
@@ -112,7 +112,7 @@ module T::Configuration
|
|
|
112
112
|
# statically, so that methods don't have to guard themselves from being
|
|
113
113
|
# called incorrectly by untyped code.
|
|
114
114
|
#
|
|
115
|
-
# @param [:never, :tests, :always] default_checked_level
|
|
115
|
+
# @param [:never, :compiled, :tests, :always] default_checked_level
|
|
116
116
|
def self.default_checked_level=(default_checked_level)
|
|
117
117
|
T::Private::RuntimeLevels.default_checked_level = default_checked_level
|
|
118
118
|
end
|
|
@@ -429,10 +429,10 @@ module T::Configuration
|
|
|
429
429
|
MODULE_NAME = Module.instance_method(:name)
|
|
430
430
|
private_constant :MODULE_NAME
|
|
431
431
|
|
|
432
|
-
if T::Configuration::AT_LEAST_RUBY_2_7
|
|
433
|
-
|
|
432
|
+
@default_module_name_mangler = if T::Configuration::AT_LEAST_RUBY_2_7
|
|
433
|
+
->(type) {MODULE_NAME.bind_call(type)}
|
|
434
434
|
else
|
|
435
|
-
|
|
435
|
+
->(type) {MODULE_NAME.bind(type).call}
|
|
436
436
|
end
|
|
437
437
|
|
|
438
438
|
@module_name_mangler = nil
|
|
@@ -523,6 +523,16 @@ module T::Configuration
|
|
|
523
523
|
@legacy_t_enum_migration_mode || false
|
|
524
524
|
end
|
|
525
525
|
|
|
526
|
+
@prop_freeze_handler = ->(instance, prop_name) {}
|
|
527
|
+
|
|
528
|
+
def self.prop_freeze_handler=(handler)
|
|
529
|
+
@prop_freeze_handler = handler
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def self.prop_freeze_handler
|
|
533
|
+
@prop_freeze_handler
|
|
534
|
+
end
|
|
535
|
+
|
|
526
536
|
# @param [Array] sealed_violation_whitelist An array of Regexp to validate
|
|
527
537
|
# whether inheriting /including a sealed module outside the defining module
|
|
528
538
|
# should be allowed. Useful to whitelist benign violations, like shim files
|
data/lib/types/enum.rb
CHANGED
|
@@ -134,10 +134,8 @@ class T::Enum
|
|
|
134
134
|
self.from_serialized(mongo_value)
|
|
135
135
|
end
|
|
136
136
|
|
|
137
|
-
|
|
138
137
|
## Enum instance methods ##
|
|
139
138
|
|
|
140
|
-
|
|
141
139
|
sig {returns(T.self_type)}
|
|
142
140
|
def dup
|
|
143
141
|
self
|
|
@@ -180,7 +178,6 @@ class T::Enum
|
|
|
180
178
|
end
|
|
181
179
|
end
|
|
182
180
|
|
|
183
|
-
|
|
184
181
|
# NB: Do not call this method. This exists to allow for a safe migration path in places where enum
|
|
185
182
|
# values are compared directly against string values.
|
|
186
183
|
#
|
|
@@ -246,10 +243,8 @@ class T::Enum
|
|
|
246
243
|
)
|
|
247
244
|
end
|
|
248
245
|
|
|
249
|
-
|
|
250
246
|
## Private implementation ##
|
|
251
247
|
|
|
252
|
-
|
|
253
248
|
sig {params(serialized_val: SerializedVal).void}
|
|
254
249
|
def initialize(serialized_val=nil)
|
|
255
250
|
raise 'T::Enum is abstract' if self.class == T::Enum
|
|
@@ -366,6 +361,6 @@ class T::Enum
|
|
|
366
361
|
|
|
367
362
|
sig {params(args: String).returns(T.attached_class)}
|
|
368
363
|
def self._load(args)
|
|
369
|
-
deserialize(Marshal.load(args))
|
|
364
|
+
deserialize(Marshal.load(args)) # rubocop:disable Security/MarshalLoad
|
|
370
365
|
end
|
|
371
366
|
end
|
data/lib/types/private/casts.rb
CHANGED
|
@@ -2,14 +2,6 @@
|
|
|
2
2
|
# typed: false
|
|
3
3
|
|
|
4
4
|
module T::Private
|
|
5
|
-
# Dynamically confirm that `value` is recursively a valid value of
|
|
6
|
-
# type `type`, including recursively through collections. Note that
|
|
7
|
-
# in some cases this runtime check can be very expensive, especially
|
|
8
|
-
# with large collections of objects.
|
|
9
|
-
def self.check_type_recursive!(value, type)
|
|
10
|
-
T::Private::Casts.cast_recursive(value, type, cast_method: "T.check_type_recursive!")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
5
|
module Casts
|
|
14
6
|
def self.cast(value, type, cast_method:)
|
|
15
7
|
begin
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: true
|
|
3
|
+
|
|
4
|
+
module T::Private
|
|
5
|
+
module Compiler
|
|
6
|
+
# If this code ever runs, the caller is running interpreted (or the
|
|
7
|
+
# compiler didn't see the call to `running_compiled?` statically.)
|
|
8
|
+
#
|
|
9
|
+
# The Sorbet Compiler replaces calls to this method unconditionally (no
|
|
10
|
+
# runtime guards) to return `true` when compiling a file.
|
|
11
|
+
def self.running_compiled?
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Returns `nil` because the compiler isn't running.
|
|
16
|
+
#
|
|
17
|
+
# The Sorbet Compiler replaces calls to this method unconditionally (no
|
|
18
|
+
# runtime guards) to return a String showing the Sorbet Compiler's version
|
|
19
|
+
# string.
|
|
20
|
+
def self.compiler_version
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -20,7 +20,7 @@ module T::Private::Methods
|
|
|
20
20
|
# twice is permitted). we could do this with two tables, but it seems slightly
|
|
21
21
|
# cleaner with a single table.
|
|
22
22
|
# Effectively T::Hash[Module, T.nilable(Set))]
|
|
23
|
-
@modules_with_final = Hash.new {
|
|
23
|
+
@modules_with_final = Hash.new {|hash, key| hash[key] = nil}
|
|
24
24
|
# this stores the old [included, extended] hooks for Module and inherited hook for Class that we override when
|
|
25
25
|
# enabling final checks for when those hooks are called. the 'hooks' here don't have anything to do with the 'hooks'
|
|
26
26
|
# in installed_hooks.
|
|
@@ -158,7 +158,7 @@ module T::Private::Methods
|
|
|
158
158
|
|
|
159
159
|
definition_file, definition_line = T::Private::Methods.signature_for_method(ancestor.instance_method(method_name)).method.source_location
|
|
160
160
|
is_redefined = target == ancestor
|
|
161
|
-
caller_loc = caller_locations&.find {|l| !l.to_s.match?(%r{sorbet-runtime[^/]*/lib/})
|
|
161
|
+
caller_loc = caller_locations&.find {|l| !l.to_s.match?(%r{sorbet-runtime[^/]*/lib/})}
|
|
162
162
|
extra_info = "\n"
|
|
163
163
|
if caller_loc
|
|
164
164
|
extra_info = (is_redefined ? "Redefined" : "Overridden") + " here: #{caller_loc.path}:#{caller_loc.lineno}\n"
|
|
@@ -456,6 +456,10 @@ module T::Private::Methods
|
|
|
456
456
|
end
|
|
457
457
|
end
|
|
458
458
|
|
|
459
|
+
def self.all_checked_tests_sigs
|
|
460
|
+
@signatures_by_method.values.select {|sig| sig.check_level == :tests}
|
|
461
|
+
end
|
|
462
|
+
|
|
459
463
|
# the module target is adding the methods from the module source to itself. we need to check that for all instance
|
|
460
464
|
# methods M on source, M is not defined on any of target's ancestors.
|
|
461
465
|
def self._hook_impl(target, singleton_class, source)
|
|
@@ -88,8 +88,8 @@ module T::Private::Methods
|
|
|
88
88
|
if !decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
89
89
|
raise BuilderError.new("You can't call .checked multiple times in a signature.")
|
|
90
90
|
end
|
|
91
|
-
if level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
92
|
-
raise BuilderError.new("You can't use .checked(
|
|
91
|
+
if (level == :never || level == :compiled) && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
92
|
+
raise BuilderError.new("You can't use .checked(:#{level}) with .on_failure because .on_failure will have no effect.")
|
|
93
93
|
end
|
|
94
94
|
if !T::Private::RuntimeLevels::LEVELS.include?(level)
|
|
95
95
|
raise BuilderError.new("Invalid `checked` level '#{level}'. Use one of: #{T::Private::RuntimeLevels::LEVELS}.")
|
|
@@ -106,8 +106,8 @@ module T::Private::Methods
|
|
|
106
106
|
if !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
107
107
|
raise BuilderError.new("You can't call .on_failure multiple times in a signature.")
|
|
108
108
|
end
|
|
109
|
-
if decl.checked == :never
|
|
110
|
-
raise BuilderError.new("You can't use .on_failure with .checked(
|
|
109
|
+
if decl.checked == :never || decl.checked == :compiled
|
|
110
|
+
raise BuilderError.new("You can't use .on_failure with .checked(:#{decl.checked}) because .on_failure will have no effect.")
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
decl.on_failure = args
|
|
@@ -209,7 +209,7 @@ module T::Private::Methods
|
|
|
209
209
|
end
|
|
210
210
|
if decl.checked.equal?(ARG_NOT_PROVIDED)
|
|
211
211
|
default_checked_level = T::Private::RuntimeLevels.default_checked_level
|
|
212
|
-
if default_checked_level == :never && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
212
|
+
if (default_checked_level == :never || default_checked_level == :compiled) && !decl.on_failure.equal?(ARG_NOT_PROVIDED)
|
|
213
213
|
raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.")
|
|
214
214
|
end
|
|
215
215
|
decl.checked = default_checked_level
|
|
@@ -2,12 +2,24 @@
|
|
|
2
2
|
# typed: true
|
|
3
3
|
|
|
4
4
|
module T::Private::Methods::Modes
|
|
5
|
-
def self.standard
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def self.
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
def self.standard
|
|
6
|
+
'standard'
|
|
7
|
+
end
|
|
8
|
+
def self.abstract
|
|
9
|
+
'abstract'
|
|
10
|
+
end
|
|
11
|
+
def self.overridable
|
|
12
|
+
'overridable'
|
|
13
|
+
end
|
|
14
|
+
def self.override
|
|
15
|
+
'override'
|
|
16
|
+
end
|
|
17
|
+
def self.overridable_override
|
|
18
|
+
'overridable_override'
|
|
19
|
+
end
|
|
20
|
+
def self.untyped
|
|
21
|
+
'untyped'
|
|
22
|
+
end
|
|
11
23
|
MODES = [self.standard, self.abstract, self.overridable, self.override, self.overridable_override, self.untyped].freeze
|
|
12
24
|
|
|
13
25
|
OVERRIDABLE_MODES = [self.override, self.overridable, self.overridable_override, self.untyped, self.abstract].freeze
|
|
@@ -154,7 +154,6 @@ module T::Private::Methods::SignatureValidation
|
|
|
154
154
|
"#{base_override_loc_str(signature, super_signature)}"
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
-
|
|
158
157
|
# O(nm), but n and m are tiny here
|
|
159
158
|
extra_req_kwargs = signature.req_kwarg_names - super_signature.req_kwarg_names
|
|
160
159
|
if !extra_req_kwargs.empty?
|
|
@@ -174,7 +173,7 @@ module T::Private::Methods::SignatureValidation
|
|
|
174
173
|
return if signature.override_allow_incompatible
|
|
175
174
|
return if super_signature.mode == Modes.untyped
|
|
176
175
|
return unless [signature, super_signature].all? do |sig|
|
|
177
|
-
sig.check_level == :always || (sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?)
|
|
176
|
+
sig.check_level == :always || sig.check_level == :compiled || (sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?)
|
|
178
177
|
end
|
|
179
178
|
mode_noun = super_signature.mode == Modes.abstract ? 'implementation' : 'override'
|
|
180
179
|
|
|
@@ -12,6 +12,9 @@ module T::Private::RuntimeLevels
|
|
|
12
12
|
# Don't even validate in tests, b/c too expensive,
|
|
13
13
|
# or b/c we fully trust the static typing
|
|
14
14
|
:never,
|
|
15
|
+
# Validate the sig when the file is using the Sorbet Compiler.
|
|
16
|
+
# Behaves like :never when interpreted.
|
|
17
|
+
:compiled,
|
|
15
18
|
].freeze
|
|
16
19
|
|
|
17
20
|
@check_tests = false
|
|
@@ -31,8 +34,11 @@ module T::Private::RuntimeLevels
|
|
|
31
34
|
|
|
32
35
|
def self.enable_checking_in_tests
|
|
33
36
|
if !@check_tests && @wrapped_tests_with_validation
|
|
37
|
+
all_checked_tests_sigs = T::Private::Methods.all_checked_tests_sigs
|
|
38
|
+
locations = all_checked_tests_sigs.map {|sig| sig.method.source_location.join(':')}.join("\n- ")
|
|
34
39
|
raise "Toggle `:tests`-level runtime type checking earlier. " \
|
|
35
|
-
"There are already some methods wrapped with `sig.checked(:tests)
|
|
40
|
+
"There are already some methods wrapped with `sig.checked(:tests)`:\n" \
|
|
41
|
+
"- #{locations}"
|
|
36
42
|
end
|
|
37
43
|
|
|
38
44
|
_toggle_checking_tests(true)
|
data/lib/types/props/_props.rb
CHANGED
|
@@ -20,13 +20,23 @@ module T::Props
|
|
|
20
20
|
extend T::Sig
|
|
21
21
|
extend T::Helpers
|
|
22
22
|
|
|
23
|
-
def props
|
|
24
|
-
|
|
23
|
+
def props
|
|
24
|
+
decorator.props
|
|
25
|
+
end
|
|
26
|
+
def plugins
|
|
27
|
+
@plugins ||= []
|
|
28
|
+
end
|
|
25
29
|
|
|
26
|
-
def decorator_class
|
|
30
|
+
def decorator_class
|
|
31
|
+
Decorator
|
|
32
|
+
end
|
|
27
33
|
|
|
28
|
-
def decorator
|
|
29
|
-
|
|
34
|
+
def decorator
|
|
35
|
+
@decorator ||= decorator_class.new(self)
|
|
36
|
+
end
|
|
37
|
+
def reload_decorator!
|
|
38
|
+
@decorator = decorator_class.new(self)
|
|
39
|
+
end
|
|
30
40
|
|
|
31
41
|
# @!method self.prop(name, type, opts={})
|
|
32
42
|
#
|
|
@@ -34,11 +34,15 @@ class T::Props::Decorator
|
|
|
34
34
|
attr_reader :props
|
|
35
35
|
|
|
36
36
|
sig {returns(T::Array[Symbol])}
|
|
37
|
-
def all_props
|
|
37
|
+
def all_props
|
|
38
|
+
props.keys
|
|
39
|
+
end
|
|
38
40
|
|
|
39
41
|
# checked(:never) - O(prop accesses)
|
|
40
42
|
sig {params(prop: T.any(Symbol, String)).returns(Rules).checked(:never)}
|
|
41
|
-
def prop_rules(prop)
|
|
43
|
+
def prop_rules(prop)
|
|
44
|
+
props[prop.to_sym] || raise("No such prop: #{prop.inspect}")
|
|
45
|
+
end
|
|
42
46
|
|
|
43
47
|
# checked(:never) - Rules hash is expensive to check
|
|
44
48
|
sig {params(prop: Symbol, rules: Rules).void.checked(:never)}
|
|
@@ -78,7 +82,9 @@ class T::Props::Decorator
|
|
|
78
82
|
|
|
79
83
|
# checked(:never) - O(prop accesses)
|
|
80
84
|
sig {returns(T.all(Module, T::Props::ClassMethods)).checked(:never)}
|
|
81
|
-
def decorated_class
|
|
85
|
+
def decorated_class
|
|
86
|
+
@class
|
|
87
|
+
end
|
|
82
88
|
|
|
83
89
|
# Accessors
|
|
84
90
|
|
|
@@ -157,7 +157,7 @@ module T::Props
|
|
|
157
157
|
validate_lack_of_side_effects(try, whitelisted_methods_for_deserialize)
|
|
158
158
|
|
|
159
159
|
assert_equal(:resbody, rescue_body.type)
|
|
160
|
-
exceptions, assignment, handler =
|
|
160
|
+
exceptions, assignment, handler = rescue_body.children
|
|
161
161
|
assert_equal(:array, exceptions.type)
|
|
162
162
|
exceptions.children.each {|c| assert_equal(:const, c.type)}
|
|
163
163
|
assert_equal(:lvasgn, assignment.type)
|
data/lib/types/props/optional.rb
CHANGED
|
@@ -5,10 +5,8 @@ module T::Props::Optional
|
|
|
5
5
|
include T::Props::Plugin
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
##############################################
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
# NB: This must stay in the same file where T::Props::Optional is defined due to
|
|
13
11
|
# T::Props::Decorator#apply_plugin; see https://git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717
|
|
14
12
|
module T::Props::Optional::DecoratorMethods
|
|
@@ -27,7 +25,9 @@ module T::Props::Optional::DecoratorMethods
|
|
|
27
25
|
super || VALID_RULE_KEYS[key]
|
|
28
26
|
end
|
|
29
27
|
|
|
30
|
-
def prop_optional?(prop)
|
|
28
|
+
def prop_optional?(prop)
|
|
29
|
+
prop_rules(prop)[:fully_optional]
|
|
30
|
+
end
|
|
31
31
|
|
|
32
32
|
def compute_derived_rules(rules)
|
|
33
33
|
rules[:fully_optional] = !T::Props::Utils.need_nil_write_check?(rules)
|
|
@@ -15,7 +15,7 @@ module T::Props::Serializable
|
|
|
15
15
|
# exception if this object has mandatory props with missing
|
|
16
16
|
# values.
|
|
17
17
|
# @return [Hash] A serialization of this object.
|
|
18
|
-
def serialize(strict=true)
|
|
18
|
+
def serialize(strict=true)
|
|
19
19
|
begin
|
|
20
20
|
h = __t_props_generated_serialize(strict)
|
|
21
21
|
rescue => e
|
|
@@ -56,7 +56,7 @@ module T::Props::Serializable
|
|
|
56
56
|
# the hash contains keys that do not correspond to any known
|
|
57
57
|
# props on this instance.
|
|
58
58
|
# @return [void]
|
|
59
|
-
def deserialize(hash, strict=false)
|
|
59
|
+
def deserialize(hash, strict=false)
|
|
60
60
|
begin
|
|
61
61
|
hash_keys_matching_props = __t_props_generated_deserialize(hash)
|
|
62
62
|
rescue => e
|
|
@@ -171,7 +171,6 @@ module T::Props::Serializable
|
|
|
171
171
|
end
|
|
172
172
|
end
|
|
173
173
|
|
|
174
|
-
|
|
175
174
|
##############################################
|
|
176
175
|
|
|
177
176
|
# NB: This must stay in the same file where T::Props::Serializable is defined due to
|
|
@@ -190,10 +189,14 @@ module T::Props::Serializable::DecoratorMethods
|
|
|
190
189
|
@class.props.select {|_, v| T::Props::Utils.required_prop?(v)}.keys
|
|
191
190
|
end
|
|
192
191
|
|
|
193
|
-
def prop_dont_store?(prop)
|
|
194
|
-
|
|
192
|
+
def prop_dont_store?(prop)
|
|
193
|
+
prop_rules(prop)[:dont_store]
|
|
194
|
+
end
|
|
195
|
+
def prop_by_serialized_forms
|
|
196
|
+
@class.prop_by_serialized_forms
|
|
197
|
+
end
|
|
195
198
|
|
|
196
|
-
def from_hash(hash, strict=false)
|
|
199
|
+
def from_hash(hash, strict=false)
|
|
197
200
|
raise ArgumentError.new("#{hash.inspect} provided to from_hash") if !(hash && hash.is_a?(Hash))
|
|
198
201
|
|
|
199
202
|
i = @class.allocate
|
|
@@ -260,7 +263,7 @@ module T::Props::Serializable::DecoratorMethods
|
|
|
260
263
|
context = " #{source_lines[(previous_blank + 1)...next_blank].join("\n ")}"
|
|
261
264
|
<<~MSG
|
|
262
265
|
Error in #{decorated_class.name}##{generated_method}: #{error.message}
|
|
263
|
-
at line #{line_num-previous_blank-1} in:
|
|
266
|
+
at line #{line_num - previous_blank - 1} in:
|
|
264
267
|
#{context}
|
|
265
268
|
MSG
|
|
266
269
|
end
|
|
@@ -300,7 +303,7 @@ module T::Props::Serializable::DecoratorMethods
|
|
|
300
303
|
end
|
|
301
304
|
|
|
302
305
|
if !rules[:raise_on_nil_write].nil? && rules[:raise_on_nil_write] != true
|
|
303
|
-
|
|
306
|
+
raise ArgumentError.new("The value of `raise_on_nil_write` if specified must be `true` (given: #{rules[:raise_on_nil_write]}).")
|
|
304
307
|
end
|
|
305
308
|
|
|
306
309
|
result
|
|
@@ -334,21 +337,21 @@ module T::Props::Serializable::DecoratorMethods
|
|
|
334
337
|
end
|
|
335
338
|
end
|
|
336
339
|
|
|
337
|
-
|
|
338
340
|
##############################################
|
|
339
341
|
|
|
340
|
-
|
|
341
342
|
# NB: This must stay in the same file where T::Props::Serializable is defined due to
|
|
342
343
|
# T::Props::Decorator#apply_plugin; see https://git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717
|
|
343
344
|
module T::Props::Serializable::ClassMethods
|
|
344
|
-
def prop_by_serialized_forms
|
|
345
|
+
def prop_by_serialized_forms
|
|
346
|
+
@prop_by_serialized_forms ||= {}
|
|
347
|
+
end
|
|
345
348
|
|
|
346
349
|
# @!method self.from_hash(hash, strict)
|
|
347
350
|
#
|
|
348
351
|
# Allocate a new instance and call {#deserialize} to load a new
|
|
349
352
|
# object from a hash.
|
|
350
353
|
# @return [Serializable]
|
|
351
|
-
def from_hash(hash, strict=false)
|
|
354
|
+
def from_hash(hash, strict=false)
|
|
352
355
|
self.decorator.from_hash(hash, strict)
|
|
353
356
|
end
|
|
354
357
|
|
|
@@ -13,15 +13,7 @@ module T::Types
|
|
|
13
13
|
|
|
14
14
|
# @override Base
|
|
15
15
|
def name
|
|
16
|
-
|
|
17
|
-
if Symbol === k && ":#{k}" == k.inspect
|
|
18
|
-
"#{k}: #{v}"
|
|
19
|
-
else
|
|
20
|
-
"#{k.inspect} => #{v}"
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
"{#{entries.join(', ')}}"
|
|
16
|
+
serialize_hash(@types)
|
|
25
17
|
end
|
|
26
18
|
|
|
27
19
|
# @override Base
|
|
@@ -59,10 +51,24 @@ module T::Types
|
|
|
59
51
|
# @override Base
|
|
60
52
|
def describe_obj(obj)
|
|
61
53
|
if obj.is_a?(Hash)
|
|
62
|
-
"type
|
|
54
|
+
"type #{serialize_hash(obj.transform_values(&:class))}"
|
|
63
55
|
else
|
|
64
56
|
super
|
|
65
57
|
end
|
|
66
58
|
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def serialize_hash(hash)
|
|
63
|
+
entries = hash.map do |(k, v)|
|
|
64
|
+
if Symbol === k && ":#{k}" == k.inspect
|
|
65
|
+
"#{k}: #{v}"
|
|
66
|
+
else
|
|
67
|
+
"#{k.inspect} => #{v}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
"{#{entries.join(', ')}}"
|
|
72
|
+
end
|
|
67
73
|
end
|
|
68
74
|
end
|
data/lib/types/types/simple.rb
CHANGED
|
@@ -40,8 +40,10 @@ module T::Types
|
|
|
40
40
|
|
|
41
41
|
module Private
|
|
42
42
|
module Pool
|
|
43
|
+
@cache = ObjectSpace::WeakMap.new
|
|
44
|
+
|
|
43
45
|
def self.type_for_module(mod)
|
|
44
|
-
cached = mod
|
|
46
|
+
cached = @cache[mod]
|
|
45
47
|
return cached if cached
|
|
46
48
|
|
|
47
49
|
type = if mod == ::Array
|
|
@@ -60,7 +62,13 @@ module T::Types
|
|
|
60
62
|
Simple.new(mod)
|
|
61
63
|
end
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
# Unfortunately, we still need to check if the module is frozen,
|
|
66
|
+
# since WeakMap adds a finalizer to the key that is added
|
|
67
|
+
# to the map, so that it can clear the map entry when the key is
|
|
68
|
+
# garbage collected.
|
|
69
|
+
# For a frozen object, though, adding a finalizer is not a valid
|
|
70
|
+
# operation, so this still raises if `mod` is frozen.
|
|
71
|
+
@cache[mod] = type unless mod.frozen?
|
|
64
72
|
type
|
|
65
73
|
end
|
|
66
74
|
end
|
data/lib/types/utils.rb
CHANGED
|
@@ -27,6 +27,14 @@ module T::Utils
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
# Dynamically confirm that `value` is recursively a valid value of
|
|
31
|
+
# type `type`, including recursively through collections. Note that
|
|
32
|
+
# in some cases this runtime check can be very expensive, especially
|
|
33
|
+
# with large collections of objects.
|
|
34
|
+
def self.check_type_recursive!(value, type)
|
|
35
|
+
T::Private::Casts.cast_recursive(value, type, cast_method: "T.check_type_recursive!")
|
|
36
|
+
end
|
|
37
|
+
|
|
30
38
|
# Returns the set of all methods (public, protected, private) defined on a module or its
|
|
31
39
|
# ancestors, excluding Object and its ancestors. Overrides of methods from Object (and its
|
|
32
40
|
# ancestors) are included.
|
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.9103
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stripe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-09-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -173,6 +173,7 @@ files:
|
|
|
173
173
|
- lib/types/private/abstract/validate.rb
|
|
174
174
|
- lib/types/private/casts.rb
|
|
175
175
|
- lib/types/private/class_utils.rb
|
|
176
|
+
- lib/types/private/compiler.rb
|
|
176
177
|
- lib/types/private/decl_state.rb
|
|
177
178
|
- lib/types/private/final.rb
|
|
178
179
|
- lib/types/private/methods/_methods.rb
|