activesupport 4.2.11.1 → 6.1.7.3
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 +464 -391
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +34 -6
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +61 -55
- data/lib/active_support/cache/mem_cache_store.rb +115 -100
- data/lib/active_support/cache/memory_store.rb +81 -58
- data/lib/active_support/cache/null_store.rb +11 -7
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +90 -42
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +386 -225
- data/lib/active_support/callbacks.rb +661 -594
- data/lib/active_support/concern.rb +80 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +16 -17
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +41 -1
- data/lib/active_support/core_ext/array/conversions.rb +24 -20
- 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 +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -48
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -25
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +17 -14
- data/lib/active_support/core_ext/date/conversions.rb +27 -24
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +167 -65
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +19 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +8 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +186 -22
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +13 -10
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +20 -43
- 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 +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +10 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +63 -69
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +148 -0
- data/lib/active_support/core_ext/module/concerning.rb +19 -14
- data/lib/active_support/core_ext/module/delegation.rb +164 -51
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +23 -22
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -11
- data/lib/active_support/core_ext/name_error.rb +51 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +133 -136
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +5 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -3
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +13 -93
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +63 -21
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +81 -23
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/each.rb +18 -17
- 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 +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +8 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +48 -6
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +102 -26
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +125 -40
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- 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 +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +137 -53
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +22 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +11 -8
- 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 +210 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
- data/lib/active_support/dependencies.rb +241 -175
- data/lib/active_support/deprecation/behaviors.rb +58 -12
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +59 -0
- data/lib/active_support/duration.rb +364 -39
- 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 +170 -0
- data/lib/active_support/execution_wrapper.rb +132 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +7 -5
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +171 -48
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +47 -16
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +58 -14
- data/lib/active_support/inflector/methods.rb +186 -169
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +32 -30
- data/lib/active_support/json/encoding.rb +22 -61
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +11 -43
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +9 -3
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +52 -19
- data/lib/active_support/logger.rb +10 -24
- data/lib/active_support/logger_silence.rb +14 -20
- data/lib/active_support/logger_thread_safe_level.rb +56 -10
- data/lib/active_support/message_encryptor.rb +167 -57
- data/lib/active_support/message_verifier.rb +151 -18
- 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 +35 -80
- data/lib/active_support/multibyte/unicode.rb +22 -330
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +125 -23
- data/lib/active_support/notifications/instrumenter.rb +98 -16
- data/lib/active_support/notifications.rb +82 -14
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -14
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
- data/lib/active_support/number_helper/number_to_human_converter.rb +14 -11
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +12 -10
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +29 -57
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +123 -71
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +7 -5
- data/lib/active_support/ordered_options.rb +35 -7
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +10 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +66 -10
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- 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 +13 -4
- data/lib/active_support/subscriber.rb +80 -31
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +107 -44
- data/lib/active_support/testing/assertions.rb +158 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +13 -10
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +35 -26
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- 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 +13 -8
- data/lib/active_support/testing/stream.rb +43 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +121 -20
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +215 -51
- data/lib/active_support/values/time_zone.rb +223 -71
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -115
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +18 -9
- data/lib/active_support/xml_mini.rb +38 -46
- data/lib/active_support.rb +25 -11
- metadata +100 -43
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/hash/compact.rb +0 -24
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -23
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,226 +1,48 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module ActiveSupport
|
3
4
|
module Multibyte
|
4
5
|
module Unicode
|
5
|
-
|
6
6
|
extend self
|
7
7
|
|
8
|
-
# A list of all available normalization forms.
|
9
|
-
# See http://www.unicode.org/reports/tr15/tr15-29.html for more
|
10
|
-
# information about normalization.
|
11
|
-
NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
|
12
|
-
|
13
8
|
# The Unicode version that is supported by the implementation
|
14
|
-
UNICODE_VERSION =
|
15
|
-
|
16
|
-
# The default normalization used for operations that require
|
17
|
-
# normalization. It can be set to any of the normalizations
|
18
|
-
# in NORMALIZATION_FORMS.
|
19
|
-
#
|
20
|
-
# ActiveSupport::Multibyte::Unicode.default_normalization_form = :c
|
21
|
-
attr_accessor :default_normalization_form
|
22
|
-
@default_normalization_form = :kc
|
23
|
-
|
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
|
-
HANGUL_JAMO_FIRST = 0x1100
|
36
|
-
HANGUL_JAMO_LAST = 0x11FF
|
37
|
-
|
38
|
-
# All the unicode whitespace
|
39
|
-
WHITESPACE = [
|
40
|
-
(0x0009..0x000D).to_a, # White_Space # Cc [5] <control-0009>..<control-000D>
|
41
|
-
0x0020, # White_Space # Zs SPACE
|
42
|
-
0x0085, # White_Space # Cc <control-0085>
|
43
|
-
0x00A0, # White_Space # Zs NO-BREAK SPACE
|
44
|
-
0x1680, # White_Space # Zs OGHAM SPACE MARK
|
45
|
-
(0x2000..0x200A).to_a, # White_Space # Zs [11] EN QUAD..HAIR SPACE
|
46
|
-
0x2028, # White_Space # Zl LINE SEPARATOR
|
47
|
-
0x2029, # White_Space # Zp PARAGRAPH SEPARATOR
|
48
|
-
0x202F, # White_Space # Zs NARROW NO-BREAK SPACE
|
49
|
-
0x205F, # White_Space # Zs MEDIUM MATHEMATICAL SPACE
|
50
|
-
0x3000, # White_Space # Zs IDEOGRAPHIC SPACE
|
51
|
-
].flatten.freeze
|
52
|
-
|
53
|
-
# BOM (byte order mark) can also be seen as whitespace, it's a
|
54
|
-
# non-rendering character used to distinguish between little and big
|
55
|
-
# endian. This is not an issue in utf-8, so it must be ignored.
|
56
|
-
LEADERS_AND_TRAILERS = WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
|
57
|
-
|
58
|
-
# Returns a regular expression pattern that matches the passed Unicode
|
59
|
-
# codepoints.
|
60
|
-
def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
|
61
|
-
array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
|
62
|
-
end
|
63
|
-
TRAILERS_PAT = /(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+\Z/u
|
64
|
-
LEADERS_PAT = /\A(#{codepoints_to_pattern(LEADERS_AND_TRAILERS)})+/u
|
65
|
-
|
66
|
-
# Detect whether the codepoint is in a certain character class. Returns
|
67
|
-
# +true+ when it's in the specified character class and +false+ otherwise.
|
68
|
-
# Valid character classes are: <tt>:cr</tt>, <tt>:lf</tt>, <tt>:l</tt>,
|
69
|
-
# <tt>:v</tt>, <tt>:lv</tt>, <tt>:lvt</tt> and <tt>:t</tt>.
|
70
|
-
#
|
71
|
-
# Primarily used by the grapheme cluster support.
|
72
|
-
def in_char_class?(codepoint, classes)
|
73
|
-
classes.detect { |c| database.boundary[c] === codepoint } ? true : false
|
74
|
-
end
|
9
|
+
UNICODE_VERSION = RbConfig::CONFIG["UNICODE_VERSION"]
|
75
10
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# Unicode.unpack_graphemes('Café') # => [[67], [97], [102], [233]]
|
81
|
-
def unpack_graphemes(string)
|
82
|
-
codepoints = string.codepoints.to_a
|
83
|
-
unpacked = []
|
84
|
-
pos = 0
|
85
|
-
marker = 0
|
86
|
-
eoc = codepoints.length
|
87
|
-
while(pos < eoc)
|
88
|
-
pos += 1
|
89
|
-
previous = codepoints[pos-1]
|
90
|
-
current = codepoints[pos]
|
91
|
-
if (
|
92
|
-
# CR X LF
|
93
|
-
( previous == database.boundary[:cr] and current == database.boundary[:lf] ) or
|
94
|
-
# L X (L|V|LV|LVT)
|
95
|
-
( database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
|
96
|
-
# (LV|V) X (V|T)
|
97
|
-
( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
|
98
|
-
# (LVT|T) X (T)
|
99
|
-
( in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current ) or
|
100
|
-
# X Extend
|
101
|
-
(database.boundary[:extend] === current)
|
102
|
-
)
|
103
|
-
else
|
104
|
-
unpacked << codepoints[marker..pos-1]
|
105
|
-
marker = pos
|
106
|
-
end
|
107
|
-
end
|
108
|
-
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 7.0."
|
14
|
+
)
|
109
15
|
end
|
110
16
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
unpacked.flatten.pack('U*')
|
116
|
-
end
|
117
|
-
|
118
|
-
# Re-order codepoints so the string becomes canonical.
|
119
|
-
def reorder_characters(codepoints)
|
120
|
-
length = codepoints.length- 1
|
121
|
-
pos = 0
|
122
|
-
while pos < length do
|
123
|
-
cp1, cp2 = database.codepoints[codepoints[pos]], database.codepoints[codepoints[pos+1]]
|
124
|
-
if (cp1.combining_class > cp2.combining_class) && (cp2.combining_class > 0)
|
125
|
-
codepoints[pos..pos+1] = cp2.code, cp1.code
|
126
|
-
pos += (pos > 0 ? -1 : 1)
|
127
|
-
else
|
128
|
-
pos += 1
|
129
|
-
end
|
130
|
-
end
|
131
|
-
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 7.0."
|
20
|
+
)
|
132
21
|
end
|
133
22
|
|
134
23
|
# Decompose composed characters to the decomposed form.
|
135
24
|
def decompose(type, codepoints)
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
ncp = [] # new codepoints
|
141
|
-
ncp << HANGUL_LBASE + sindex / HANGUL_NCOUNT
|
142
|
-
ncp << HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
|
143
|
-
tindex = sindex % HANGUL_TCOUNT
|
144
|
-
ncp << (HANGUL_TBASE + tindex) unless tindex == 0
|
145
|
-
decomposed.concat ncp
|
146
|
-
# if the codepoint is decomposable in with the current decomposition type
|
147
|
-
elsif (ncp = database.codepoints[cp].decomp_mapping) and (!database.codepoints[cp].decomp_type || type == :compatibility)
|
148
|
-
decomposed.concat decompose(type, ncp.dup)
|
149
|
-
else
|
150
|
-
decomposed << cp
|
151
|
-
end
|
25
|
+
if type == :compatibility
|
26
|
+
codepoints.pack("U*").unicode_normalize(:nfkd).codepoints
|
27
|
+
else
|
28
|
+
codepoints.pack("U*").unicode_normalize(:nfd).codepoints
|
152
29
|
end
|
153
30
|
end
|
154
31
|
|
155
32
|
# Compose decomposed characters to the composed form.
|
156
33
|
def compose(codepoints)
|
157
|
-
|
158
|
-
eoa = codepoints.length - 1
|
159
|
-
starter_pos = 0
|
160
|
-
starter_char = codepoints[0]
|
161
|
-
previous_combining_class = -1
|
162
|
-
while pos < eoa
|
163
|
-
pos += 1
|
164
|
-
lindex = starter_char - HANGUL_LBASE
|
165
|
-
# -- Hangul
|
166
|
-
if 0 <= lindex and lindex < HANGUL_LCOUNT
|
167
|
-
vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
|
168
|
-
if 0 <= vindex and vindex < HANGUL_VCOUNT
|
169
|
-
tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
|
170
|
-
if 0 <= tindex and tindex < HANGUL_TCOUNT
|
171
|
-
j = starter_pos + 2
|
172
|
-
eoa -= 2
|
173
|
-
else
|
174
|
-
tindex = 0
|
175
|
-
j = starter_pos + 1
|
176
|
-
eoa -= 1
|
177
|
-
end
|
178
|
-
codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
|
179
|
-
end
|
180
|
-
starter_pos += 1
|
181
|
-
starter_char = codepoints[starter_pos]
|
182
|
-
# -- Other characters
|
183
|
-
else
|
184
|
-
current_char = codepoints[pos]
|
185
|
-
current = database.codepoints[current_char]
|
186
|
-
if current.combining_class > previous_combining_class
|
187
|
-
if ref = database.composition_map[starter_char]
|
188
|
-
composition = ref[current_char]
|
189
|
-
else
|
190
|
-
composition = nil
|
191
|
-
end
|
192
|
-
unless composition.nil?
|
193
|
-
codepoints[starter_pos] = composition
|
194
|
-
starter_char = composition
|
195
|
-
codepoints.delete_at pos
|
196
|
-
eoa -= 1
|
197
|
-
pos -= 1
|
198
|
-
previous_combining_class = -1
|
199
|
-
else
|
200
|
-
previous_combining_class = current.combining_class
|
201
|
-
end
|
202
|
-
else
|
203
|
-
previous_combining_class = current.combining_class
|
204
|
-
end
|
205
|
-
if current.combining_class == 0
|
206
|
-
starter_pos = pos
|
207
|
-
starter_char = codepoints[pos]
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
codepoints
|
34
|
+
codepoints.pack("U*").unicode_normalize(:nfc).codepoints
|
212
35
|
end
|
213
36
|
|
214
|
-
# Ruby >= 2.1 has String#scrub, which is faster than the workaround used for < 2.1.
|
215
37
|
# Rubinius' String#scrub, however, doesn't support ASCII-incompatible chars.
|
216
|
-
if
|
38
|
+
if !defined?(Rubinius)
|
217
39
|
# Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent
|
218
40
|
# resulting in a valid UTF-8 string.
|
219
41
|
#
|
220
42
|
# Passing +true+ will forcibly tidy all bytes, assuming that the string's
|
221
43
|
# encoding is entirely CP1252 or ISO-8859-1.
|
222
44
|
def tidy_bytes(string, force = false)
|
223
|
-
return string if string.empty?
|
45
|
+
return string if string.empty? || string.ascii_only?
|
224
46
|
return recode_windows1252_chars(string) if force
|
225
47
|
string.scrub { |bad| recode_windows1252_chars(bad) }
|
226
48
|
end
|
@@ -236,7 +58,7 @@ module ActiveSupport
|
|
236
58
|
reader = Encoding::Converter.new(Encoding::UTF_8, Encoding::UTF_16LE)
|
237
59
|
|
238
60
|
source = string.dup
|
239
|
-
out =
|
61
|
+
out = "".force_encoding(Encoding::UTF_16LE)
|
240
62
|
|
241
63
|
loop do
|
242
64
|
reader.primitive_convert(source, out)
|
@@ -251,140 +73,10 @@ module ActiveSupport
|
|
251
73
|
end
|
252
74
|
end
|
253
75
|
|
254
|
-
# Returns the KC normalization of the string by default. NFKC is
|
255
|
-
# considered the best normalization form for passing strings to databases
|
256
|
-
# and validations.
|
257
|
-
#
|
258
|
-
# * <tt>string</tt> - The string to perform normalization on.
|
259
|
-
# * <tt>form</tt> - The form you want to normalize in. Should be one of
|
260
|
-
# the following: <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>.
|
261
|
-
# Default is ActiveSupport::Multibyte.default_normalization_form.
|
262
|
-
def normalize(string, form=nil)
|
263
|
-
form ||= @default_normalization_form
|
264
|
-
# See http://www.unicode.org/reports/tr15, Table 1
|
265
|
-
codepoints = string.codepoints.to_a
|
266
|
-
case form
|
267
|
-
when :d
|
268
|
-
reorder_characters(decompose(:canonical, codepoints))
|
269
|
-
when :c
|
270
|
-
compose(reorder_characters(decompose(:canonical, codepoints)))
|
271
|
-
when :kd
|
272
|
-
reorder_characters(decompose(:compatibility, codepoints))
|
273
|
-
when :kc
|
274
|
-
compose(reorder_characters(decompose(:compatibility, codepoints)))
|
275
|
-
else
|
276
|
-
raise ArgumentError, "#{form} is not a valid normalization variant", caller
|
277
|
-
end.pack('U*')
|
278
|
-
end
|
279
|
-
|
280
|
-
def downcase(string)
|
281
|
-
apply_mapping string, :lowercase_mapping
|
282
|
-
end
|
283
|
-
|
284
|
-
def upcase(string)
|
285
|
-
apply_mapping string, :uppercase_mapping
|
286
|
-
end
|
287
|
-
|
288
|
-
def swapcase(string)
|
289
|
-
apply_mapping string, :swapcase_mapping
|
290
|
-
end
|
291
|
-
|
292
|
-
# Holds data about a codepoint in the Unicode database.
|
293
|
-
class Codepoint
|
294
|
-
attr_accessor :code, :combining_class, :decomp_type, :decomp_mapping, :uppercase_mapping, :lowercase_mapping
|
295
|
-
|
296
|
-
# Initializing Codepoint object with default values
|
297
|
-
def initialize
|
298
|
-
@combining_class = 0
|
299
|
-
@uppercase_mapping = 0
|
300
|
-
@lowercase_mapping = 0
|
301
|
-
end
|
302
|
-
|
303
|
-
def swapcase_mapping
|
304
|
-
uppercase_mapping > 0 ? uppercase_mapping : lowercase_mapping
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
# Holds static data from the Unicode database.
|
309
|
-
class UnicodeDatabase
|
310
|
-
ATTRIBUTES = :codepoints, :composition_exclusion, :composition_map, :boundary, :cp1252
|
311
|
-
|
312
|
-
attr_writer(*ATTRIBUTES)
|
313
|
-
|
314
|
-
def initialize
|
315
|
-
@codepoints = Hash.new(Codepoint.new)
|
316
|
-
@composition_exclusion = []
|
317
|
-
@composition_map = {}
|
318
|
-
@boundary = {}
|
319
|
-
@cp1252 = {}
|
320
|
-
end
|
321
|
-
|
322
|
-
# Lazy load the Unicode database so it's only loaded when it's actually used
|
323
|
-
ATTRIBUTES.each do |attr_name|
|
324
|
-
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
325
|
-
def #{attr_name} # def codepoints
|
326
|
-
load # load
|
327
|
-
@#{attr_name} # @codepoints
|
328
|
-
end # end
|
329
|
-
EOS
|
330
|
-
end
|
331
|
-
|
332
|
-
# Loads the Unicode database and returns all the internal objects of
|
333
|
-
# UnicodeDatabase.
|
334
|
-
def load
|
335
|
-
begin
|
336
|
-
@codepoints, @composition_exclusion, @composition_map, @boundary, @cp1252 = File.open(self.class.filename, 'rb') { |f| Marshal.load f.read }
|
337
|
-
rescue => e
|
338
|
-
raise IOError.new("Couldn't load the Unicode tables for UTF8Handler (#{e.message}), ActiveSupport::Multibyte is unusable")
|
339
|
-
end
|
340
|
-
|
341
|
-
# Redefine the === method so we can write shorter rules for grapheme cluster breaks
|
342
|
-
@boundary.each do |k,_|
|
343
|
-
@boundary[k].instance_eval do
|
344
|
-
def ===(other)
|
345
|
-
detect { |i| i === other } ? true : false
|
346
|
-
end
|
347
|
-
end if @boundary[k].kind_of?(Array)
|
348
|
-
end
|
349
|
-
|
350
|
-
# define attr_reader methods for the instance variables
|
351
|
-
class << self
|
352
|
-
attr_reader(*ATTRIBUTES)
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
# Returns the directory in which the data files are stored.
|
357
|
-
def self.dirname
|
358
|
-
File.dirname(__FILE__) + '/../values/'
|
359
|
-
end
|
360
|
-
|
361
|
-
# Returns the filename for the data file for this version.
|
362
|
-
def self.filename
|
363
|
-
File.expand_path File.join(dirname, "unicode_tables.dat")
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
76
|
private
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
string.each_codepoint.map do |codepoint|
|
372
|
-
cp = database.codepoints[codepoint]
|
373
|
-
if cp and (ncp = cp.send(mapping)) and ncp > 0
|
374
|
-
ncp
|
375
|
-
else
|
376
|
-
codepoint
|
377
|
-
end
|
378
|
-
end.pack('U*')
|
379
|
-
end
|
380
|
-
|
381
|
-
def recode_windows1252_chars(string)
|
382
|
-
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
383
|
-
end
|
384
|
-
|
385
|
-
def database
|
386
|
-
@database ||= UnicodeDatabase.new
|
387
|
-
end
|
77
|
+
def recode_windows1252_chars(string)
|
78
|
+
string.encode(Encoding::UTF_8, Encoding::Windows_1252, invalid: :replace, undef: :replace)
|
79
|
+
end
|
388
80
|
end
|
389
81
|
end
|
390
82
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport #:nodoc:
|
2
4
|
module Multibyte
|
3
|
-
autoload :Chars,
|
4
|
-
autoload :Unicode,
|
5
|
+
autoload :Chars, "active_support/multibyte/chars"
|
6
|
+
autoload :Unicode, "active_support/multibyte/unicode"
|
5
7
|
|
6
8
|
# The proxy class returned when calling mb_chars. You can use this accessor
|
7
9
|
# to configure your own proxy class so you can support other encodings. See
|
@@ -1,5 +1,9 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mutex_m"
|
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
|
-
@
|
15
|
-
@
|
18
|
+
@string_subscribers = Hash.new { |h, k| h[k] = [] }
|
19
|
+
@other_subscribers = []
|
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
|
|
@@ -42,8 +59,8 @@ module ActiveSupport
|
|
42
59
|
listeners_for(name).each { |s| s.start(name, id, payload) }
|
43
60
|
end
|
44
61
|
|
45
|
-
def finish(name, id, payload)
|
46
|
-
|
62
|
+
def finish(name, id, payload, listeners = listeners_for(name))
|
63
|
+
listeners.each { |s| s.finish(name, id, payload) }
|
47
64
|
end
|
48
65
|
|
49
66
|
def publish(name, *args)
|
@@ -51,10 +68,11 @@ module ActiveSupport
|
|
51
68
|
end
|
52
69
|
|
53
70
|
def listeners_for(name)
|
54
|
-
# this is correctly done double-checked locking (
|
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)
|
71
|
-
|
72
|
-
|
88
|
+
def self.new(pattern, listener, monotonic)
|
89
|
+
subscriber_class = monotonic ? MonotonicTimed : Timed
|
90
|
+
|
91
|
+
if listener.respond_to?(:start) && listener.respond_to?(:finish)
|
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
|