activesupport 5.2.5 → 6.0.4.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +452 -398
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +27 -1
- data/lib/active_support/cache/file_store.rb +32 -32
- data/lib/active_support/cache/mem_cache_store.rb +12 -7
- data/lib/active_support/cache/memory_store.rb +15 -9
- data/lib/active_support/cache/null_store.rb +8 -3
- data/lib/active_support/cache/redis_cache_store.rb +47 -20
- data/lib/active_support/cache/strategy/local_cache.rb +22 -22
- data/lib/active_support/cache.rb +71 -48
- data/lib/active_support/callbacks.rb +16 -8
- data/lib/active_support/concern.rb +24 -1
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/configurable.rb +7 -11
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/array/conversions.rb +5 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
- data/lib/active_support/core_ext/array.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +11 -16
- data/lib/active_support/core_ext/class/subclasses.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -47
- data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
- data/lib/active_support/core_ext/enumerable.rb +97 -73
- data/lib/active_support/core_ext/hash/compact.rb +2 -26
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +2 -2
- data/lib/active_support/core_ext/hash/keys.rb +0 -29
- data/lib/active_support/core_ext/hash/slice.rb +3 -25
- data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
- data/lib/active_support/core_ext/hash.rb +1 -2
- data/lib/active_support/core_ext/integer/multiple.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -10
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +13 -19
- data/lib/active_support/core_ext/module/delegation.rb +41 -8
- data/lib/active_support/core_ext/module/introspection.rb +38 -13
- data/lib/active_support/core_ext/module/reachable.rb +1 -6
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
- data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/blank.rb +1 -2
- data/lib/active_support/core_ext/object/duplicable.rb +7 -114
- data/lib/active_support/core_ext/object/json.rb +2 -1
- data/lib/active_support/core_ext/object/try.rb +17 -7
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/compare_range.rb +28 -13
- data/lib/active_support/core_ext/range/conversions.rb +31 -29
- data/lib/active_support/core_ext/range/each.rb +0 -1
- data/lib/active_support/core_ext/range/include_range.rb +6 -0
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
- data/lib/active_support/core_ext/regexp.rb +0 -4
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +8 -0
- data/lib/active_support/core_ext/string/filters.rb +42 -1
- data/lib/active_support/core_ext/string/inflections.rb +7 -2
- data/lib/active_support/core_ext/string/multibyte.rb +4 -3
- data/lib/active_support/core_ext/string/output_safety.rb +68 -10
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +34 -3
- data/lib/active_support/core_ext/uri.rb +1 -0
- data/lib/active_support/current_attributes.rb +8 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +74 -18
- data/lib/active_support/deprecation/behaviors.rb +1 -1
- data/lib/active_support/deprecation/method_wrappers.rb +17 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +28 -5
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/descendants_tracker.rb +55 -9
- data/lib/active_support/duration/iso8601_parser.rb +2 -4
- data/lib/active_support/duration/iso8601_serializer.rb +3 -5
- data/lib/active_support/duration.rb +7 -8
- data/lib/active_support/encrypted_configuration.rb +0 -4
- data/lib/active_support/encrypted_file.rb +3 -2
- data/lib/active_support/evented_file_update_checker.rb +39 -10
- data/lib/active_support/execution_wrapper.rb +1 -0
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +22 -18
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +13 -1
- data/lib/active_support/inflector/inflections.rb +1 -5
- data/lib/active_support/inflector/methods.rb +16 -29
- data/lib/active_support/inflector/transliterate.rb +47 -18
- data/lib/active_support/json/decoding.rb +23 -24
- data/lib/active_support/json/encoding.rb +6 -2
- data/lib/active_support/key_generator.rb +0 -32
- data/lib/active_support/lazy_load_hooks.rb +5 -2
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/log_subscriber.rb +31 -9
- data/lib/active_support/logger.rb +1 -16
- data/lib/active_support/logger_silence.rb +28 -12
- data/lib/active_support/logger_thread_safe_level.rb +26 -4
- data/lib/active_support/message_encryptor.rb +4 -6
- data/lib/active_support/message_verifier.rb +5 -5
- data/lib/active_support/messages/metadata.rb +11 -2
- data/lib/active_support/messages/rotator.rb +4 -4
- data/lib/active_support/multibyte/chars.rb +29 -49
- data/lib/active_support/multibyte/unicode.rb +44 -282
- data/lib/active_support/notifications/fanout.rb +98 -13
- data/lib/active_support/notifications/instrumenter.rb +80 -9
- data/lib/active_support/notifications.rb +41 -4
- data/lib/active_support/number_helper/number_converter.rb +4 -5
- data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +3 -2
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -2
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -4
- data/lib/active_support/number_helper/rounding_helper.rb +1 -1
- data/lib/active_support/number_helper.rb +11 -0
- data/lib/active_support/option_merger.rb +21 -3
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +5 -1
- data/lib/active_support/parameter_filter.rb +128 -0
- data/lib/active_support/rails.rb +0 -6
- data/lib/active_support/reloader.rb +4 -5
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/string_inquirer.rb +0 -1
- data/lib/active_support/subscriber.rb +65 -26
- data/lib/active_support/tagged_logging.rb +13 -4
- data/lib/active_support/test_case.rb +91 -0
- data/lib/active_support/testing/assertions.rb +15 -1
- data/lib/active_support/testing/deprecation.rb +0 -1
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +28 -1
- data/lib/active_support/testing/parallelization.rb +134 -0
- data/lib/active_support/testing/stream.rb +1 -2
- data/lib/active_support/testing/time_helpers.rb +7 -9
- data/lib/active_support/time_with_zone.rb +15 -5
- data/lib/active_support/values/time_zone.rb +12 -7
- data/lib/active_support/xml_mini/jdom.rb +2 -3
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
- data/lib/active_support/xml_mini/rexml.rb +2 -2
- data/lib/active_support/xml_mini.rb +2 -10
- data/lib/active_support.rb +2 -1
- metadata +40 -12
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -6,12 +6,19 @@ module ActiveSupport
|
|
6
6
|
extend self
|
7
7
|
|
8
8
|
# A list of all available normalization forms.
|
9
|
-
# See
|
9
|
+
# See https://www.unicode.org/reports/tr15/tr15-29.html for more
|
10
10
|
# information about normalization.
|
11
11
|
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
12
12
|
|
13
|
+
NORMALIZATION_FORM_ALIASES = { # :nodoc:
|
14
|
+
c: :nfc,
|
15
|
+
d: :nfd,
|
16
|
+
kc: :nfkc,
|
17
|
+
kd: :nfkd
|
18
|
+
}
|
19
|
+
|
13
20
|
# The Unicode version that is supported by the implementation
|
14
|
-
UNICODE_VERSION = "
|
21
|
+
UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
|
15
22
|
|
16
23
|
# The default normalization used for operations that require
|
17
24
|
# normalization. It can be set to any of the normalizations
|
@@ -21,199 +28,44 @@ module ActiveSupport
|
|
21
28
|
attr_accessor :default_normalization_form
|
22
29
|
@default_normalization_form = :kc
|
23
30
|
|
24
|
-
# Hangul character boundaries and properties
|
25
|
-
HANGUL_SBASE = 0xAC00
|
26
|
-
HANGUL_LBASE = 0x1100
|
27
|
-
HANGUL_VBASE = 0x1161
|
28
|
-
HANGUL_TBASE = 0x11A7
|
29
|
-
HANGUL_LCOUNT = 19
|
30
|
-
HANGUL_VCOUNT = 21
|
31
|
-
HANGUL_TCOUNT = 28
|
32
|
-
HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
|
33
|
-
HANGUL_SCOUNT = 11172
|
34
|
-
HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
|
35
|
-
|
36
|
-
# Detect whether the codepoint is in a certain character class. Returns
|
37
|
-
# +true+ when it's in the specified character class and +false+ otherwise.
|
38
|
-
# Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
|
39
|
-
# <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
|
40
|
-
#
|
41
|
-
# Primarily used by the grapheme cluster support.
|
42
|
-
def in_char_class?(codepoint, classes)
|
43
|
-
classes.detect { |c| database.boundary[c] === codepoint } ? true : false
|
44
|
-
end
|
45
|
-
|
46
31
|
# Unpack the string at grapheme boundaries. Returns a list of character
|
47
32
|
# lists.
|
48
33
|
#
|
49
34
|
# Unicode.unpack_graphemes('क्षि') # => [[2325, 2381], [2359], [2367]]
|
50
35
|
# Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]]
|
51
36
|
def unpack_graphemes(string)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
eoc = codepoints.length
|
57
|
-
while (pos < eoc)
|
58
|
-
pos += 1
|
59
|
-
previous = codepoints[pos - 1]
|
60
|
-
current = codepoints[pos]
|
61
|
-
|
62
|
-
# See http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules
|
63
|
-
should_break =
|
64
|
-
if pos == eoc
|
65
|
-
true
|
66
|
-
# GB3. CR X LF
|
67
|
-
elsif previous == database.boundary[:cr] && current == database.boundary[:lf]
|
68
|
-
false
|
69
|
-
# GB4. (Control|CR|LF) ÷
|
70
|
-
elsif previous && in_char_class?(previous, [:control, :cr, :lf])
|
71
|
-
true
|
72
|
-
# GB5. ÷ (Control|CR|LF)
|
73
|
-
elsif in_char_class?(current, [:control, :cr, :lf])
|
74
|
-
true
|
75
|
-
# GB6. L X (L|V|LV|LVT)
|
76
|
-
elsif database.boundary[:l] === previous && in_char_class?(current, [:l, :v, :lv, :lvt])
|
77
|
-
false
|
78
|
-
# GB7. (LV|V) X (V|T)
|
79
|
-
elsif in_char_class?(previous, [:lv, :v]) && in_char_class?(current, [:v, :t])
|
80
|
-
false
|
81
|
-
# GB8. (LVT|T) X (T)
|
82
|
-
elsif in_char_class?(previous, [:lvt, :t]) && database.boundary[:t] === current
|
83
|
-
false
|
84
|
-
# GB9. X (Extend | ZWJ)
|
85
|
-
elsif in_char_class?(current, [:extend, :zwj])
|
86
|
-
false
|
87
|
-
# GB9a. X SpacingMark
|
88
|
-
elsif database.boundary[:spacingmark] === current
|
89
|
-
false
|
90
|
-
# GB9b. Prepend X
|
91
|
-
elsif database.boundary[:prepend] === previous
|
92
|
-
false
|
93
|
-
# GB10. (E_Base | EBG) Extend* X E_Modifier
|
94
|
-
elsif (marker...pos).any? { |i| in_char_class?(codepoints[i], [:e_base, :e_base_gaz]) && codepoints[i + 1...pos].all? { |c| database.boundary[:extend] === c } } && database.boundary[:e_modifier] === current
|
95
|
-
false
|
96
|
-
# GB11. ZWJ X (Glue_After_Zwj | EBG)
|
97
|
-
elsif database.boundary[:zwj] === previous && in_char_class?(current, [:glue_after_zwj, :e_base_gaz])
|
98
|
-
false
|
99
|
-
# GB12. ^ (RI RI)* RI X RI
|
100
|
-
# GB13. [^RI] (RI RI)* RI X RI
|
101
|
-
elsif codepoints[marker..pos].all? { |c| database.boundary[:regional_indicator] === c } && codepoints[marker..pos].count { |c| database.boundary[:regional_indicator] === c }.even?
|
102
|
-
false
|
103
|
-
# GB999. Any ÷ Any
|
104
|
-
else
|
105
|
-
true
|
106
|
-
end
|
37
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
38
|
+
ActiveSupport::Multibyte::Unicode#unpack_graphemes is deprecated and will be
|
39
|
+
removed from Rails 6.1. Use string.scan(/\X/).map(&:codepoints) instead.
|
40
|
+
MSG
|
107
41
|
|
108
|
-
|
109
|
-
unpacked << codepoints[marker..pos - 1]
|
110
|
-
marker = pos
|
111
|
-
end
|
112
|
-
end
|
113
|
-
unpacked
|
42
|
+
string.scan(/\X/).map(&:codepoints)
|
114
43
|
end
|
115
44
|
|
116
45
|
# Reverse operation of unpack_graphemes.
|
117
46
|
#
|
118
47
|
# Unicode.pack_graphemes(Unicode.unpack_graphemes('क्षि')) # => 'क्षि'
|
119
48
|
def pack_graphemes(unpacked)
|
120
|
-
|
121
|
-
|
49
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
50
|
+
ActiveSupport::Multibyte::Unicode#pack_graphemes is deprecated and will be
|
51
|
+
removed from Rails 6.1. Use array.flatten.pack("U*") instead.
|
52
|
+
MSG
|
122
53
|
|
123
|
-
|
124
|
-
def reorder_characters(codepoints)
|
125
|
-
length = codepoints.length - 1
|
126
|
-
pos = 0
|
127
|
-
while pos < length do
|
128
|
-
cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos + 1]]
|
129
|
-
if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
|
130
|
-
codepoints[pos..pos + 1] = cp2.code, cp1.code
|
131
|
-
pos += (pos > 0 ? -1 : 1)
|
132
|
-
else
|
133
|
-
pos += 1
|
134
|
-
end
|
135
|
-
end
|
136
|
-
codepoints
|
54
|
+
unpacked.flatten.pack("U*")
|
137
55
|
end
|
138
56
|
|
139
57
|
# Decompose composed characters to the decomposed form.
|
140
58
|
def decompose(type, codepoints)
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
ncp = [] # new codepoints
|
146
|
-
ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
|
147
|
-
ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
|
148
|
-
tindex = sindex % HANGUL_TCOUNT
|
149
|
-
ncp << (HANGUL_TBASE + tindex) unless tindex == 0
|
150
|
-
decomposed.concat ncp
|
151
|
-
# if the codepoint is decomposable in with the current decomposition type
|
152
|
-
elsif (ncp = database.codepoints[cp].decomp_mapping) && (!database.codepoints[cp].decomp_type || type == :compatibility)
|
153
|
-
decomposed.concat decompose(type, ncp.dup)
|
154
|
-
else
|
155
|
-
decomposed << cp
|
156
|
-
end
|
59
|
+
if type == :compatibility
|
60
|
+
codepoints.pack("U*").unicode_normalize(:nfkd).codepoints
|
61
|
+
else
|
62
|
+
codepoints.pack("U*").unicode_normalize(:nfd).codepoints
|
157
63
|
end
|
158
64
|
end
|
159
65
|
|
160
66
|
# Compose decomposed characters to the composed form.
|
161
67
|
def compose(codepoints)
|
162
|
-
|
163
|
-
eoa = codepoints.length - 1
|
164
|
-
starter_pos = 0
|
165
|
-
starter_char = codepoints[0]
|
166
|
-
previous_combining_class = -1
|
167
|
-
while pos < eoa
|
168
|
-
pos += 1
|
169
|
-
lindex = starter_char - HANGUL_LBASE
|
170
|
-
# -- Hangul
|
171
|
-
if 0 <= lindex && lindex < HANGUL_LCOUNT
|
172
|
-
vindex = codepoints[starter_pos + 1] - HANGUL_VBASE rescue vindex = -1
|
173
|
-
if 0 <= vindex && vindex < HANGUL_VCOUNT
|
174
|
-
tindex = codepoints[starter_pos + 2] - HANGUL_TBASE rescue tindex = -1
|
175
|
-
if 0 <= tindex && tindex < HANGUL_TCOUNT
|
176
|
-
j = starter_pos + 2
|
177
|
-
eoa -= 2
|
178
|
-
else
|
179
|
-
tindex = 0
|
180
|
-
j = starter_pos + 1
|
181
|
-
eoa -= 1
|
182
|
-
end
|
183
|
-
codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
|
184
|
-
end
|
185
|
-
starter_pos += 1
|
186
|
-
starter_char = codepoints[starter_pos]
|
187
|
-
# -- Other characters
|
188
|
-
else
|
189
|
-
current_char = codepoints[pos]
|
190
|
-
current = database.codepoints[current_char]
|
191
|
-
if current.combining_class > previous_combining_class
|
192
|
-
if ref = database.composition_map[starter_char]
|
193
|
-
composition = ref[current_char]
|
194
|
-
else
|
195
|
-
composition = nil
|
196
|
-
end
|
197
|
-
unless composition.nil?
|
198
|
-
codepoints[starter_pos] = composition
|
199
|
-
starter_char = composition
|
200
|
-
codepoints.delete_at pos
|
201
|
-
eoa -= 1
|
202
|
-
pos -= 1
|
203
|
-
previous_combining_class = -1
|
204
|
-
else
|
205
|
-
previous_combining_class = current.combining_class
|
206
|
-
end
|
207
|
-
else
|
208
|
-
previous_combining_class = current.combining_class
|
209
|
-
end
|
210
|
-
if current.combining_class == 0
|
211
|
-
starter_pos = pos
|
212
|
-
starter_char = codepoints[pos]
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
codepoints
|
68
|
+
codepoints.pack("U*").unicode_normalize(:nfc).codepoints
|
217
69
|
end
|
218
70
|
|
219
71
|
# Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
|
@@ -265,130 +117,40 @@ module ActiveSupport
|
|
265
117
|
# Default is ActiveSupport::Multibyte::Unicode.default_normalization_form.
|
266
118
|
def normalize(string, form = nil)
|
267
119
|
form ||= @default_normalization_form
|
268
|
-
# See http://www.unicode.org/reports/tr15, Table 1
|
269
|
-
codepoints = string.codepoints.to_a
|
270
|
-
case form
|
271
|
-
when :d
|
272
|
-
reorder_characters(decompose(:canonical, codepoints))
|
273
|
-
when :c
|
274
|
-
compose(reorder_characters(decompose(:canonical, codepoints)))
|
275
|
-
when :kd
|
276
|
-
reorder_characters(decompose(:compatibility, codepoints))
|
277
|
-
when :kc
|
278
|
-
compose(reorder_characters(decompose(:compatibility, codepoints)))
|
279
|
-
else
|
280
|
-
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
281
|
-
end.pack("U*".freeze)
|
282
|
-
end
|
283
|
-
|
284
|
-
def downcase(string)
|
285
|
-
apply_mapping string, :lowercase_mapping
|
286
|
-
end
|
287
|
-
|
288
|
-
def upcase(string)
|
289
|
-
apply_mapping string, :uppercase_mapping
|
290
|
-
end
|
291
120
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping
|
121
|
+
# See https://www.unicode.org/reports/tr15, Table 1
|
122
|
+
if alias_form = NORMALIZATION_FORM_ALIASES[form]
|
123
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
124
|
+
ActiveSupport::Multibyte::Unicode#normalize is deprecated and will be
|
125
|
+
removed from Rails 6.1. Use String#unicode_normalize(:#{alias_form}) instead.
|
126
|
+
MSG
|
299
127
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
128
|
+
string.unicode_normalize(alias_form)
|
129
|
+
else
|
130
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
131
|
+
ActiveSupport::Multibyte::Unicode#normalize is deprecated and will be
|
132
|
+
removed from Rails 6.1. Use String#unicode_normalize instead.
|
133
|
+
MSG
|
306
134
|
|
307
|
-
|
308
|
-
uppercase_mapping > 0 ? uppercase_mapping : lowercase_mapping
|
135
|
+
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
309
136
|
end
|
310
137
|
end
|
311
138
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
def initialize
|
319
|
-
@codepoints = Hash.new(Codepoint.new)
|
320
|
-
@composition_exclusion = []
|
321
|
-
@composition_map = {}
|
322
|
-
@boundary = {}
|
323
|
-
@cp1252 = {}
|
324
|
-
end
|
325
|
-
|
326
|
-
# Lazy load the Unicode database so it's only loaded when it's actually used
|
327
|
-
ATTRIBUTES.each do |attr_name|
|
328
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
329
|
-
def #{attr_name} # def codepoints
|
330
|
-
load # load
|
331
|
-
@#{attr_name} # @codepoints
|
332
|
-
end # end
|
333
|
-
EOS
|
334
|
-
end
|
335
|
-
|
336
|
-
# Loads the Unicode database and returns all the internal objects of
|
337
|
-
# UnicodeDatabase.
|
338
|
-
def load
|
339
|
-
begin
|
340
|
-
@codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, "rb") { |f| Marshal.load f.read }
|
341
|
-
rescue => e
|
342
|
-
raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), ActiveSupport::Multibyte is unusable")
|
343
|
-
end
|
344
|
-
|
345
|
-
# Redefine the === method so we can write shorter rules for grapheme cluster breaks
|
346
|
-
@boundary.each_key do |k|
|
347
|
-
@boundary[k].instance_eval do
|
348
|
-
def ===(other)
|
349
|
-
detect { |i| i === other } ? true : false
|
350
|
-
end
|
351
|
-
end if @boundary[k].kind_of?(Array)
|
352
|
-
end
|
353
|
-
|
354
|
-
# define attr_reader methods for the instance variables
|
355
|
-
class << self
|
356
|
-
attr_reader(*ATTRIBUTES)
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
# Returns the directory in which the data files are stored.
|
361
|
-
def self.dirname
|
362
|
-
File.expand_path("../values", __dir__)
|
363
|
-
end
|
139
|
+
%w(downcase upcase swapcase).each do |method|
|
140
|
+
define_method(method) do |string|
|
141
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
142
|
+
ActiveSupport::Multibyte::Unicode##{method} is deprecated and
|
143
|
+
will be removed from Rails 6.1. Use String methods directly.
|
144
|
+
MSG
|
364
145
|
|
365
|
-
|
366
|
-
def self.filename
|
367
|
-
File.expand_path File.join(dirname, "unicode_tables.dat")
|
146
|
+
string.send(method)
|
368
147
|
end
|
369
148
|
end
|
370
149
|
|
371
150
|
private
|
372
|
-
|
373
|
-
def apply_mapping(string, mapping)
|
374
|
-
database.codepoints
|
375
|
-
string.each_codepoint.map do |codepoint|
|
376
|
-
cp = database.codepoints[codepoint]
|
377
|
-
if cp && (ncp = cp.send(mapping)) && ncp > 0
|
378
|
-
ncp
|
379
|
-
else
|
380
|
-
codepoint
|
381
|
-
end
|
382
|
-
end.pack("U*")
|
383
|
-
end
|
384
|
-
|
385
151
|
def recode_windows1252_chars(string)
|
386
152
|
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
387
153
|
end
|
388
|
-
|
389
|
-
def database
|
390
|
-
@database ||= UnicodeDatabase.new
|
391
|
-
end
|
392
154
|
end
|
393
155
|
end
|
394
156
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "mutex_m"
|
4
4
|
require "concurrent/map"
|
5
|
+
require "set"
|
5
6
|
|
6
7
|
module ActiveSupport
|
7
8
|
module Notifications
|
@@ -13,7 +14,8 @@ module ActiveSupport
|
|
13
14
|
include Mutex_m
|
14
15
|
|
15
16
|
def initialize
|
16
|
-
@
|
17
|
+
@string_subscribers = Hash.new { |h, k| h[k] = [] }
|
18
|
+
@other_subscribers = []
|
17
19
|
@listeners_for = Concurrent::Map.new
|
18
20
|
super
|
19
21
|
end
|
@@ -21,8 +23,13 @@ module ActiveSupport
|
|
21
23
|
def subscribe(pattern = nil, callable = nil, &block)
|
22
24
|
subscriber = Subscribers.new(pattern, callable || block)
|
23
25
|
synchronize do
|
24
|
-
|
25
|
-
|
26
|
+
if String === pattern
|
27
|
+
@string_subscribers[pattern] << subscriber
|
28
|
+
@listeners_for.delete(pattern)
|
29
|
+
else
|
30
|
+
@other_subscribers << subscriber
|
31
|
+
@listeners_for.clear
|
32
|
+
end
|
26
33
|
end
|
27
34
|
subscriber
|
28
35
|
end
|
@@ -31,12 +38,19 @@ module ActiveSupport
|
|
31
38
|
synchronize do
|
32
39
|
case subscriber_or_name
|
33
40
|
when String
|
34
|
-
@
|
41
|
+
@string_subscribers[subscriber_or_name].clear
|
42
|
+
@listeners_for.delete(subscriber_or_name)
|
43
|
+
@other_subscribers.each { |sub| sub.unsubscribe!(subscriber_or_name) }
|
35
44
|
else
|
36
|
-
|
45
|
+
pattern = subscriber_or_name.try(:pattern)
|
46
|
+
if String === pattern
|
47
|
+
@string_subscribers[pattern].delete(subscriber_or_name)
|
48
|
+
@listeners_for.delete(pattern)
|
49
|
+
else
|
50
|
+
@other_subscribers.delete(subscriber_or_name)
|
51
|
+
@listeners_for.clear
|
52
|
+
end
|
37
53
|
end
|
38
|
-
|
39
|
-
@listeners_for.clear
|
40
54
|
end
|
41
55
|
end
|
42
56
|
|
@@ -56,7 +70,8 @@ module ActiveSupport
|
|
56
70
|
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
57
71
|
@listeners_for[name] || synchronize do
|
58
72
|
# use synchronisation when accessing @subscribers
|
59
|
-
@listeners_for[name] ||=
|
73
|
+
@listeners_for[name] ||=
|
74
|
+
@string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
|
60
75
|
end
|
61
76
|
end
|
62
77
|
|
@@ -70,12 +85,29 @@ module ActiveSupport
|
|
70
85
|
|
71
86
|
module Subscribers # :nodoc:
|
72
87
|
def self.new(pattern, listener)
|
88
|
+
subscriber_class = Timed
|
89
|
+
|
73
90
|
if listener.respond_to?(:start) && listener.respond_to?(:finish)
|
74
|
-
|
91
|
+
subscriber_class = Evented
|
75
92
|
else
|
76
|
-
|
93
|
+
# Doing all this to detect a block like `proc { |x| }` vs
|
94
|
+
# `proc { |*x| }` or `proc { |**x| }`
|
95
|
+
if listener.respond_to?(:parameters)
|
96
|
+
params = listener.parameters
|
97
|
+
if params.length == 1 && params.first.first == :opt
|
98
|
+
subscriber_class = EventObject
|
99
|
+
end
|
100
|
+
end
|
77
101
|
end
|
78
102
|
|
103
|
+
wrap_all pattern, subscriber_class.new(pattern, listener)
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.event_object_subscriber(pattern, block)
|
107
|
+
wrap_all pattern, EventObject.new(pattern, block)
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.wrap_all(pattern, subscriber)
|
79
111
|
unless pattern
|
80
112
|
AllMessages.new(subscriber)
|
81
113
|
else
|
@@ -83,9 +115,33 @@ module ActiveSupport
|
|
83
115
|
end
|
84
116
|
end
|
85
117
|
|
118
|
+
class Matcher #:nodoc:
|
119
|
+
attr_reader :pattern, :exclusions
|
120
|
+
|
121
|
+
def self.wrap(pattern)
|
122
|
+
return pattern if String === pattern
|
123
|
+
new(pattern)
|
124
|
+
end
|
125
|
+
|
126
|
+
def initialize(pattern)
|
127
|
+
@pattern = pattern
|
128
|
+
@exclusions = Set.new
|
129
|
+
end
|
130
|
+
|
131
|
+
def unsubscribe!(name)
|
132
|
+
exclusions << -name if pattern === name
|
133
|
+
end
|
134
|
+
|
135
|
+
def ===(name)
|
136
|
+
pattern === name && !exclusions.include?(name)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
86
140
|
class Evented #:nodoc:
|
141
|
+
attr_reader :pattern
|
142
|
+
|
87
143
|
def initialize(pattern, delegate)
|
88
|
-
@pattern = pattern
|
144
|
+
@pattern = Matcher.wrap(pattern)
|
89
145
|
@delegate = delegate
|
90
146
|
@can_publish = delegate.respond_to?(:publish)
|
91
147
|
end
|
@@ -105,11 +161,15 @@ module ActiveSupport
|
|
105
161
|
end
|
106
162
|
|
107
163
|
def subscribed_to?(name)
|
108
|
-
|
164
|
+
pattern === name
|
109
165
|
end
|
110
166
|
|
111
167
|
def matches?(name)
|
112
|
-
|
168
|
+
pattern && pattern === name
|
169
|
+
end
|
170
|
+
|
171
|
+
def unsubscribe!(name)
|
172
|
+
pattern.unsubscribe!(name)
|
113
173
|
end
|
114
174
|
end
|
115
175
|
|
@@ -130,6 +190,27 @@ module ActiveSupport
|
|
130
190
|
end
|
131
191
|
end
|
132
192
|
|
193
|
+
class EventObject < Evented
|
194
|
+
def start(name, id, payload)
|
195
|
+
stack = Thread.current[:_event_stack] ||= []
|
196
|
+
event = build_event name, id, payload
|
197
|
+
event.start!
|
198
|
+
stack.push event
|
199
|
+
end
|
200
|
+
|
201
|
+
def finish(name, id, payload)
|
202
|
+
stack = Thread.current[:_event_stack]
|
203
|
+
event = stack.pop
|
204
|
+
event.finish!
|
205
|
+
@delegate.call event
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
def build_event(name, id, payload)
|
210
|
+
ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
133
214
|
class AllMessages # :nodoc:
|
134
215
|
def initialize(delegate)
|
135
216
|
@delegate = delegate
|
@@ -151,6 +232,10 @@ module ActiveSupport
|
|
151
232
|
true
|
152
233
|
end
|
153
234
|
|
235
|
+
def unsubscribe!(*)
|
236
|
+
false
|
237
|
+
end
|
238
|
+
|
154
239
|
alias :matches? :===
|
155
240
|
end
|
156
241
|
end
|