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