activesupport 4.2.11.1 → 6.0.3.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 +399 -411
- 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 +48 -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 +58 -53
- data/lib/active_support/cache/mem_cache_store.rb +95 -91
- data/lib/active_support/cache/memory_store.rb +39 -36
- 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 +75 -42
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +331 -217
- data/lib/active_support/callbacks.rb +650 -592
- data/lib/active_support/concern.rb +35 -6
- 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 +13 -14
- 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/prepend_and_append.rb +4 -6
- 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 +3 -1
- 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 +45 -31
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -6
- 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 +25 -23
- 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 +154 -65
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -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 +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +114 -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/compact.rb +4 -23
- 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 +12 -9
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +19 -42
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +5 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
- 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 +8 -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 +46 -46
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +133 -30
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +44 -19
- data/lib/active_support/core_ext/module/reachable.rb +5 -7
- 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 +22 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
- data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
- 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 +51 -20
- 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 +76 -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_range.rb +7 -21
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -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 +2 -0
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +16 -6
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +7 -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 +66 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +16 -7
- data/lib/active_support/core_ext/string/output_safety.rb +93 -40
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- 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/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +115 -52
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +20 -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 +6 -7
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes.rb +203 -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 +117 -0
- data/lib/active_support/dependencies.rb +208 -166
- data/lib/active_support/deprecation/behaviors.rb +44 -11
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +61 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/descendants_tracker.rb +57 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +53 -0
- data/lib/active_support/duration.rb +315 -40
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +100 -0
- data/lib/active_support/evented_file_update_checker.rb +234 -0
- data/lib/active_support/execution_wrapper.rb +129 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/gem_version.rb +6 -4
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +129 -30
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +50 -14
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +58 -13
- data/lib/active_support/inflector/methods.rb +159 -145
- data/lib/active_support/inflector/transliterate.rb +84 -34
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +32 -30
- data/lib/active_support/json/encoding.rb +17 -60
- 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 +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +44 -19
- data/lib/active_support/logger.rb +9 -23
- data/lib/active_support/logger_silence.rb +32 -14
- data/lib/active_support/logger_thread_safe_level.rb +32 -8
- data/lib/active_support/message_encryptor.rb +166 -53
- data/lib/active_support/message_verifier.rb +149 -16
- data/lib/active_support/messages/metadata.rb +72 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte/chars.rb +56 -63
- data/lib/active_support/multibyte/unicode.rb +56 -290
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +109 -22
- data/lib/active_support/notifications/instrumenter.rb +107 -16
- data/lib/active_support/notifications.rb +51 -10
- data/lib/active_support/number_helper/number_converter.rb +16 -15
- data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
- data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
- 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 +25 -57
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +105 -68
- data/lib/active_support/option_merger.rb +24 -4
- data/lib/active_support/ordered_hash.rb +7 -5
- data/lib/active_support/ordered_options.rb +27 -5
- data/lib/active_support/parameter_filter.rb +128 -0
- data/lib/active_support/per_thread_registry.rb +9 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +11 -4
- data/lib/active_support/subscriber.rb +74 -30
- data/lib/active_support/tagged_logging.rb +25 -13
- data/lib/active_support/test_case.rb +107 -44
- data/lib/active_support/testing/assertions.rb +151 -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.rb +134 -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 +84 -20
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +179 -39
- data/lib/active_support/values/time_zone.rb +203 -63
- 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 +11 -9
- data/lib/active_support/xml_mini.rb +38 -46
- data/lib/active_support.rb +13 -11
- metadata +84 -26
- data/lib/active_support/concurrency/latch.rb +0 -27
- 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/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/object/itself.rb +0 -15
- 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,73 +1,97 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
require "thread"
|
5
|
+
require "concurrent/map"
|
6
|
+
require "pathname"
|
7
|
+
require "active_support/core_ext/module/aliasing"
|
8
|
+
require "active_support/core_ext/module/attribute_accessors"
|
9
|
+
require "active_support/core_ext/module/introspection"
|
10
|
+
require "active_support/core_ext/module/anonymous"
|
11
|
+
require "active_support/core_ext/object/blank"
|
12
|
+
require "active_support/core_ext/kernel/reporting"
|
13
|
+
require "active_support/core_ext/load_error"
|
14
|
+
require "active_support/core_ext/name_error"
|
15
|
+
require "active_support/core_ext/string/starts_ends_with"
|
16
|
+
require "active_support/dependencies/interlock"
|
17
|
+
require "active_support/inflector"
|
16
18
|
|
17
19
|
module ActiveSupport #:nodoc:
|
18
20
|
module Dependencies #:nodoc:
|
19
21
|
extend self
|
20
22
|
|
23
|
+
UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
|
24
|
+
private_constant :UNBOUND_METHOD_MODULE_NAME
|
25
|
+
|
26
|
+
mattr_accessor :interlock, default: Interlock.new
|
27
|
+
|
28
|
+
# :doc:
|
29
|
+
|
30
|
+
# Execute the supplied block without interference from any
|
31
|
+
# concurrent loads.
|
32
|
+
def self.run_interlock
|
33
|
+
Dependencies.interlock.running { yield }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Execute the supplied block while holding an exclusive lock,
|
37
|
+
# preventing any other thread from being inside a #run_interlock
|
38
|
+
# block at the same time.
|
39
|
+
def self.load_interlock
|
40
|
+
Dependencies.interlock.loading { yield }
|
41
|
+
end
|
42
|
+
|
43
|
+
# Execute the supplied block while holding an exclusive lock,
|
44
|
+
# preventing any other thread from being inside a #run_interlock
|
45
|
+
# block at the same time.
|
46
|
+
def self.unload_interlock
|
47
|
+
Dependencies.interlock.unloading { yield }
|
48
|
+
end
|
49
|
+
|
50
|
+
# :nodoc:
|
51
|
+
|
21
52
|
# Should we turn on Ruby warnings on the first load of dependent files?
|
22
|
-
mattr_accessor :warnings_on_first_load
|
23
|
-
self.warnings_on_first_load = false
|
53
|
+
mattr_accessor :warnings_on_first_load, default: false
|
24
54
|
|
25
55
|
# All files ever loaded.
|
26
|
-
mattr_accessor :history
|
27
|
-
self.history = Set.new
|
56
|
+
mattr_accessor :history, default: Set.new
|
28
57
|
|
29
58
|
# All files currently loaded.
|
30
|
-
mattr_accessor :loaded
|
31
|
-
self.loaded = Set.new
|
59
|
+
mattr_accessor :loaded, default: Set.new
|
32
60
|
|
33
61
|
# Stack of files being loaded.
|
34
|
-
mattr_accessor :loading
|
35
|
-
self.loading = []
|
62
|
+
mattr_accessor :loading, default: []
|
36
63
|
|
37
64
|
# Should we load files or require them?
|
38
|
-
mattr_accessor :mechanism
|
39
|
-
self.mechanism = ENV['NO_RELOAD'] ? :require : :load
|
65
|
+
mattr_accessor :mechanism, default: ENV["NO_RELOAD"] ? :require : :load
|
40
66
|
|
41
67
|
# The set of directories from which we may automatically load files. Files
|
42
68
|
# under these directories will be reloaded on each request in development mode,
|
43
69
|
# unless the directory also appears in autoload_once_paths.
|
44
|
-
mattr_accessor :autoload_paths
|
45
|
-
self.autoload_paths = []
|
70
|
+
mattr_accessor :autoload_paths, default: []
|
46
71
|
|
47
72
|
# The set of directories from which automatically loaded constants are loaded
|
48
73
|
# only once. All directories in this set must also be present in +autoload_paths+.
|
49
|
-
mattr_accessor :autoload_once_paths
|
50
|
-
|
74
|
+
mattr_accessor :autoload_once_paths, default: []
|
75
|
+
|
76
|
+
# This is a private set that collects all eager load paths during bootstrap.
|
77
|
+
# Useful for Zeitwerk integration. Its public interface is the config.* path
|
78
|
+
# accessors of each engine.
|
79
|
+
mattr_accessor :_eager_load_paths, default: Set.new
|
51
80
|
|
52
81
|
# An array of qualified constant names that have been loaded. Adding a name
|
53
82
|
# to this array will cause it to be unloaded the next time Dependencies are
|
54
83
|
# cleared.
|
55
|
-
mattr_accessor :autoloaded_constants
|
56
|
-
self.autoloaded_constants = []
|
84
|
+
mattr_accessor :autoloaded_constants, default: []
|
57
85
|
|
58
86
|
# An array of constant names that need to be unloaded on every request. Used
|
59
87
|
# to allow arbitrary constants to be marked for unloading.
|
60
|
-
mattr_accessor :explicitly_unloadable_constants
|
61
|
-
self.explicitly_unloadable_constants = []
|
88
|
+
mattr_accessor :explicitly_unloadable_constants, default: []
|
62
89
|
|
63
|
-
# The logger
|
64
|
-
# (including benchmarking) if available. Can be set to nil for no logging.
|
65
|
-
# Compatible with both Ruby's own Logger and Log4r loggers.
|
90
|
+
# The logger used when tracing autoloads.
|
66
91
|
mattr_accessor :logger
|
67
92
|
|
68
|
-
#
|
69
|
-
mattr_accessor :
|
70
|
-
self.log_activity = false
|
93
|
+
# If true, trace autoloads with +logger.debug+.
|
94
|
+
mattr_accessor :verbose, default: false
|
71
95
|
|
72
96
|
# The WatchStack keeps a stack of the modules being watched as files are
|
73
97
|
# loaded. If a file in the process of being loaded (parent.rb) triggers the
|
@@ -75,7 +99,7 @@ module ActiveSupport #:nodoc:
|
|
75
99
|
# handles the new constants.
|
76
100
|
#
|
77
101
|
# If child.rb is being autoloaded, its constants will be added to
|
78
|
-
# autoloaded_constants. If it was being
|
102
|
+
# autoloaded_constants. If it was being required, they will be discarded.
|
79
103
|
#
|
80
104
|
# This is handled by walking back up the watch stack and adding the constants
|
81
105
|
# found by child.rb to the list of original constants in parent.rb.
|
@@ -87,9 +111,11 @@ module ActiveSupport #:nodoc:
|
|
87
111
|
# parent.rb then requires namespace/child.rb, the stack will look like
|
88
112
|
# [[Object], [Namespace]].
|
89
113
|
|
114
|
+
attr_reader :watching
|
115
|
+
|
90
116
|
def initialize
|
91
117
|
@watching = []
|
92
|
-
@stack = Hash.new { |h,k| h[k] = [] }
|
118
|
+
@stack = Hash.new { |h, k| h[k] = [] }
|
93
119
|
end
|
94
120
|
|
95
121
|
def each(&block)
|
@@ -115,11 +141,11 @@ module ActiveSupport #:nodoc:
|
|
115
141
|
next unless mod.is_a?(Module)
|
116
142
|
|
117
143
|
# Get a list of the constants that were added
|
118
|
-
new_constants = mod.
|
144
|
+
new_constants = mod.constants(false) - original_constants
|
119
145
|
|
120
|
-
#
|
146
|
+
# @stack[namespace] returns an Array of the constants that are being evaluated
|
121
147
|
# for that namespace. For instance, if parent.rb requires child.rb, the first
|
122
|
-
# element of
|
148
|
+
# element of @stack[Object] will be an Array of the constants that were present
|
123
149
|
# before parent.rb was required. The second element will be an Array of the
|
124
150
|
# constants that were present before child.rb was required.
|
125
151
|
@stack[namespace].each do |namespace_constants|
|
@@ -143,7 +169,7 @@ module ActiveSupport #:nodoc:
|
|
143
169
|
@watching << namespaces.map do |namespace|
|
144
170
|
module_name = Dependencies.to_constant_name(namespace)
|
145
171
|
original_constants = Dependencies.qualified_const_defined?(module_name) ?
|
146
|
-
Inflector.constantize(module_name).
|
172
|
+
Inflector.constantize(module_name).constants(false) : []
|
147
173
|
|
148
174
|
@stack[module_name] << original_constants
|
149
175
|
module_name
|
@@ -151,14 +177,13 @@ module ActiveSupport #:nodoc:
|
|
151
177
|
end
|
152
178
|
|
153
179
|
private
|
154
|
-
|
155
|
-
|
156
|
-
|
180
|
+
def pop_modules(modules)
|
181
|
+
modules.each { |mod| @stack[mod].pop }
|
182
|
+
end
|
157
183
|
end
|
158
184
|
|
159
185
|
# An internal stack used to record which constants are loaded by any block.
|
160
|
-
mattr_accessor :constant_watch_stack
|
161
|
-
self.constant_watch_stack = WatchStack.new
|
186
|
+
mattr_accessor :constant_watch_stack, default: WatchStack.new
|
162
187
|
|
163
188
|
# Module includes this module.
|
164
189
|
module ModuleConstMissing #:nodoc:
|
@@ -179,6 +204,11 @@ module ActiveSupport #:nodoc:
|
|
179
204
|
end
|
180
205
|
end
|
181
206
|
|
207
|
+
def self.include_into(base)
|
208
|
+
base.include(self)
|
209
|
+
append_features(base)
|
210
|
+
end
|
211
|
+
|
182
212
|
def const_missing(const_name)
|
183
213
|
from_mod = anonymous? ? guess_for_anonymous(const_name) : self
|
184
214
|
Dependencies.load_missing_constant(from_mod, const_name)
|
@@ -208,6 +238,21 @@ module ActiveSupport #:nodoc:
|
|
208
238
|
base.class_eval do
|
209
239
|
define_method(:load, Kernel.instance_method(:load))
|
210
240
|
private :load
|
241
|
+
|
242
|
+
define_method(:require, Kernel.instance_method(:require))
|
243
|
+
private :require
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def self.include_into(base)
|
248
|
+
base.include(self)
|
249
|
+
|
250
|
+
if base.instance_method(:load).owner == base
|
251
|
+
base.remove_method(:load)
|
252
|
+
end
|
253
|
+
|
254
|
+
if base.instance_method(:require).owner == base
|
255
|
+
base.remove_method(:require)
|
211
256
|
end
|
212
257
|
end
|
213
258
|
|
@@ -215,6 +260,8 @@ module ActiveSupport #:nodoc:
|
|
215
260
|
Dependencies.require_or_load(file_name)
|
216
261
|
end
|
217
262
|
|
263
|
+
# :doc:
|
264
|
+
|
218
265
|
# Interprets a file using <tt>mechanism</tt> and marks its defined
|
219
266
|
# constants as autoloaded. <tt>file_name</tt> can be either a string or
|
220
267
|
# respond to <tt>to_path</tt>.
|
@@ -224,7 +271,7 @@ module ActiveSupport #:nodoc:
|
|
224
271
|
# resolution deterministic for constants with the same relative name in
|
225
272
|
# different namespaces whose evaluation would depend on load order
|
226
273
|
# otherwise.
|
227
|
-
def require_dependency(file_name, message = "No such file to load -- %s")
|
274
|
+
def require_dependency(file_name, message = "No such file to load -- %s.rb")
|
228
275
|
file_name = file_name.to_path if file_name.respond_to?(:to_path)
|
229
276
|
unless file_name.is_a?(String)
|
230
277
|
raise ArgumentError, "the file name must either be a String or implement #to_path -- you passed #{file_name.inspect}"
|
@@ -233,9 +280,13 @@ module ActiveSupport #:nodoc:
|
|
233
280
|
Dependencies.depend_on(file_name, message)
|
234
281
|
end
|
235
282
|
|
283
|
+
# :nodoc:
|
284
|
+
|
236
285
|
def load_dependency(file)
|
237
|
-
if Dependencies.load? &&
|
238
|
-
Dependencies.
|
286
|
+
if Dependencies.load? && Dependencies.constant_watch_stack.watching?
|
287
|
+
descs = Dependencies.constant_watch_stack.watching.flatten.uniq
|
288
|
+
|
289
|
+
Dependencies.new_constants_in(*descs) { yield }
|
239
290
|
else
|
240
291
|
yield
|
241
292
|
end
|
@@ -262,18 +313,17 @@ module ActiveSupport #:nodoc:
|
|
262
313
|
end
|
263
314
|
|
264
315
|
private
|
316
|
+
def load(file, wrap = false)
|
317
|
+
result = false
|
318
|
+
load_dependency(file) { result = super }
|
319
|
+
result
|
320
|
+
end
|
265
321
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
def require(file)
|
273
|
-
result = false
|
274
|
-
load_dependency(file) { result = super }
|
275
|
-
result
|
276
|
-
end
|
322
|
+
def require(file)
|
323
|
+
result = false
|
324
|
+
load_dependency(file) { result = super }
|
325
|
+
result
|
326
|
+
end
|
277
327
|
end
|
278
328
|
|
279
329
|
# Exception file-blaming.
|
@@ -298,9 +348,9 @@ module ActiveSupport #:nodoc:
|
|
298
348
|
end
|
299
349
|
|
300
350
|
def hook!
|
301
|
-
Object
|
302
|
-
Module
|
303
|
-
Exception.
|
351
|
+
Loadable.include_into(Object)
|
352
|
+
ModuleConstMissing.include_into(Module)
|
353
|
+
Exception.include(Blamable)
|
304
354
|
end
|
305
355
|
|
306
356
|
def unhook!
|
@@ -324,75 +374,77 @@ module ActiveSupport #:nodoc:
|
|
324
374
|
end
|
325
375
|
|
326
376
|
def clear
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
377
|
+
Dependencies.unload_interlock do
|
378
|
+
loaded.clear
|
379
|
+
loading.clear
|
380
|
+
remove_unloadable_constants!
|
381
|
+
end
|
331
382
|
end
|
332
383
|
|
333
384
|
def require_or_load(file_name, const_path = nil)
|
334
|
-
|
335
|
-
file_name = $` if file_name =~ /\.rb\z/
|
385
|
+
file_name = file_name.chomp(".rb")
|
336
386
|
expanded = File.expand_path(file_name)
|
337
387
|
return if loaded.include?(expanded)
|
338
388
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
loading << expanded
|
343
|
-
|
344
|
-
begin
|
345
|
-
if load?
|
346
|
-
log "loading #{file_name}"
|
389
|
+
Dependencies.load_interlock do
|
390
|
+
# Maybe it got loaded while we were waiting for our lock:
|
391
|
+
return if loaded.include?(expanded)
|
347
392
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
393
|
+
# Record that we've seen this file *before* loading it to avoid an
|
394
|
+
# infinite loop with mutual dependencies.
|
395
|
+
loaded << expanded
|
396
|
+
loading << expanded
|
352
397
|
|
353
|
-
|
354
|
-
|
398
|
+
begin
|
399
|
+
if load?
|
400
|
+
# Enable warnings if this file has not been loaded before and
|
401
|
+
# warnings_on_first_load is set.
|
402
|
+
load_args = ["#{file_name}.rb"]
|
403
|
+
load_args << const_path unless const_path.nil?
|
404
|
+
|
405
|
+
if !warnings_on_first_load || history.include?(expanded)
|
406
|
+
result = load_file(*load_args)
|
407
|
+
else
|
408
|
+
enable_warnings { result = load_file(*load_args) }
|
409
|
+
end
|
355
410
|
else
|
356
|
-
|
411
|
+
result = require file_name
|
357
412
|
end
|
358
|
-
|
359
|
-
|
360
|
-
|
413
|
+
rescue Exception
|
414
|
+
loaded.delete expanded
|
415
|
+
raise
|
416
|
+
ensure
|
417
|
+
loading.pop
|
361
418
|
end
|
362
|
-
rescue Exception
|
363
|
-
loaded.delete expanded
|
364
|
-
raise
|
365
|
-
ensure
|
366
|
-
loading.pop
|
367
|
-
end
|
368
419
|
|
369
|
-
|
370
|
-
|
371
|
-
|
420
|
+
# Record history *after* loading so first load gets warnings.
|
421
|
+
history << expanded
|
422
|
+
result
|
423
|
+
end
|
372
424
|
end
|
373
425
|
|
374
426
|
# Is the provided constant path defined?
|
375
427
|
def qualified_const_defined?(path)
|
376
|
-
Object.
|
428
|
+
Object.const_defined?(path, false)
|
377
429
|
end
|
378
430
|
|
379
431
|
# Given +path+, a filesystem path to a ruby file, return an array of
|
380
432
|
# constant paths which would cause Dependencies to attempt to load this
|
381
433
|
# file.
|
382
434
|
def loadable_constants_for_path(path, bases = autoload_paths)
|
383
|
-
path =
|
435
|
+
path = path.chomp(".rb")
|
384
436
|
expanded_path = File.expand_path(path)
|
385
437
|
paths = []
|
386
438
|
|
387
439
|
bases.each do |root|
|
388
440
|
expanded_root = File.expand_path(root)
|
389
|
-
next unless
|
441
|
+
next unless expanded_path.start_with?(expanded_root)
|
390
442
|
|
391
|
-
|
392
|
-
|
393
|
-
next if nesting.blank?
|
443
|
+
root_size = expanded_root.size
|
444
|
+
next if expanded_path[root_size] != ?/
|
394
445
|
|
395
|
-
|
446
|
+
nesting = expanded_path[(root_size + 1)..-1]
|
447
|
+
paths << nesting.camelize unless nesting.blank?
|
396
448
|
end
|
397
449
|
|
398
450
|
paths.uniq!
|
@@ -401,7 +453,7 @@ module ActiveSupport #:nodoc:
|
|
401
453
|
|
402
454
|
# Search for a file in autoload_paths matching the provided suffix.
|
403
455
|
def search_for_file(path_suffix)
|
404
|
-
path_suffix
|
456
|
+
path_suffix += ".rb" unless path_suffix.ends_with?(".rb")
|
405
457
|
|
406
458
|
autoload_paths.each do |root|
|
407
459
|
path = File.join(root, path_suffix)
|
@@ -421,7 +473,7 @@ module ActiveSupport #:nodoc:
|
|
421
473
|
end
|
422
474
|
|
423
475
|
def load_once_path?(path)
|
424
|
-
# to_s works around a
|
476
|
+
# to_s works around a ruby issue where String#starts_with?(Pathname)
|
425
477
|
# will raise a TypeError: no implicit conversion of Pathname into String
|
426
478
|
autoload_once_paths.any? { |base| path.starts_with? base.to_s }
|
427
479
|
end
|
@@ -435,7 +487,9 @@ module ActiveSupport #:nodoc:
|
|
435
487
|
return nil unless base_path = autoloadable_module?(path_suffix)
|
436
488
|
mod = Module.new
|
437
489
|
into.const_set const_name, mod
|
490
|
+
log("constant #{qualified_name} autoloaded (module autovivified from #{File.join(base_path, path_suffix)})")
|
438
491
|
autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
|
492
|
+
autoloaded_constants.uniq!
|
439
493
|
mod
|
440
494
|
end
|
441
495
|
|
@@ -448,7 +502,6 @@ module ActiveSupport #:nodoc:
|
|
448
502
|
# set of names that the file at +path+ may define. See
|
449
503
|
# +loadable_constants_for_path+ for more details.
|
450
504
|
def load_file(path, const_paths = loadable_constants_for_path(path))
|
451
|
-
log_call path, const_paths
|
452
505
|
const_paths = [const_paths].compact unless const_paths.is_a? Array
|
453
506
|
parent_paths = const_paths.collect { |const_path| const_path[/.*(?=::)/] || ::Object }
|
454
507
|
|
@@ -459,7 +512,6 @@ module ActiveSupport #:nodoc:
|
|
459
512
|
|
460
513
|
autoloaded_constants.concat newly_defined_paths unless load_once_path?(path)
|
461
514
|
autoloaded_constants.uniq!
|
462
|
-
log "loading #{path} defined #{newly_defined_paths * ', '}" unless newly_defined_paths.empty?
|
463
515
|
result
|
464
516
|
end
|
465
517
|
|
@@ -473,32 +525,35 @@ module ActiveSupport #:nodoc:
|
|
473
525
|
# it is not possible to load the constant into from_mod, try its parent
|
474
526
|
# module using +const_missing+.
|
475
527
|
def load_missing_constant(from_mod, const_name)
|
476
|
-
log_call from_mod, const_name
|
477
|
-
|
478
528
|
unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
|
479
529
|
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
|
480
530
|
end
|
481
531
|
|
482
|
-
qualified_name = qualified_name_for
|
532
|
+
qualified_name = qualified_name_for(from_mod, const_name)
|
483
533
|
path_suffix = qualified_name.underscore
|
484
534
|
|
485
535
|
file_path = search_for_file(path_suffix)
|
486
536
|
|
487
537
|
if file_path
|
488
538
|
expanded = File.expand_path(file_path)
|
489
|
-
expanded.sub!(/\.rb\z/,
|
539
|
+
expanded.sub!(/\.rb\z/, "")
|
490
540
|
|
491
541
|
if loading.include?(expanded)
|
492
542
|
raise "Circular dependency detected while autoloading constant #{qualified_name}"
|
493
543
|
else
|
494
544
|
require_or_load(expanded, qualified_name)
|
495
|
-
|
496
|
-
|
545
|
+
|
546
|
+
if from_mod.const_defined?(const_name, false)
|
547
|
+
log("constant #{qualified_name} autoloaded from #{expanded}.rb")
|
548
|
+
return from_mod.const_get(const_name)
|
549
|
+
else
|
550
|
+
raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it"
|
551
|
+
end
|
497
552
|
end
|
498
553
|
elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
|
499
554
|
return mod
|
500
|
-
elsif (parent = from_mod.
|
501
|
-
! from_mod.
|
555
|
+
elsif (parent = from_mod.module_parent) && parent != from_mod &&
|
556
|
+
! from_mod.module_parents.any? { |p| p.const_defined?(const_name, false) }
|
502
557
|
# If our parents do not have a constant named +const_name+ then we are free
|
503
558
|
# to attempt to load upwards. If they do have such a constant, then this
|
504
559
|
# const_missing must be due to from_mod::const_name, which should not
|
@@ -530,7 +585,7 @@ module ActiveSupport #:nodoc:
|
|
530
585
|
end
|
531
586
|
|
532
587
|
name_error = NameError.new("uninitialized constant #{qualified_name}", const_name)
|
533
|
-
name_error.set_backtrace(caller.reject {|l| l.starts_with? __FILE__ })
|
588
|
+
name_error.set_backtrace(caller.reject { |l| l.starts_with? __FILE__ })
|
534
589
|
raise name_error
|
535
590
|
end
|
536
591
|
|
@@ -542,6 +597,7 @@ module ActiveSupport #:nodoc:
|
|
542
597
|
# as the environment will be in an inconsistent state, e.g. other constants
|
543
598
|
# may have already been unloaded and not accessible.
|
544
599
|
def remove_unloadable_constants!
|
600
|
+
log("removing unloadable constants")
|
545
601
|
autoloaded_constants.each { |const| remove_constant const }
|
546
602
|
autoloaded_constants.clear
|
547
603
|
Reference.clear!
|
@@ -550,7 +606,7 @@ module ActiveSupport #:nodoc:
|
|
550
606
|
|
551
607
|
class ClassCache
|
552
608
|
def initialize
|
553
|
-
@store =
|
609
|
+
@store = Concurrent::Map.new
|
554
610
|
end
|
555
611
|
|
556
612
|
def empty?
|
@@ -574,7 +630,7 @@ module ActiveSupport #:nodoc:
|
|
574
630
|
|
575
631
|
def store(klass)
|
576
632
|
return self unless klass.respond_to?(:name)
|
577
|
-
raise(ArgumentError,
|
633
|
+
raise(ArgumentError, "anonymous classes cannot be cached") if klass.name.empty?
|
578
634
|
@store[klass.name] = klass
|
579
635
|
self
|
580
636
|
end
|
@@ -605,10 +661,10 @@ module ActiveSupport #:nodoc:
|
|
605
661
|
|
606
662
|
# Determine if the given constant has been automatically loaded.
|
607
663
|
def autoloaded?(desc)
|
608
|
-
return false if desc.is_a?(Module) && desc.
|
664
|
+
return false if desc.is_a?(Module) && real_mod_name(desc).nil?
|
609
665
|
name = to_constant_name desc
|
610
|
-
return false unless qualified_const_defined?
|
611
|
-
|
666
|
+
return false unless qualified_const_defined?(name)
|
667
|
+
autoloaded_constants.include?(name)
|
612
668
|
end
|
613
669
|
|
614
670
|
# Will the provided constant descriptor be unloaded?
|
@@ -638,54 +694,49 @@ module ActiveSupport #:nodoc:
|
|
638
694
|
# exception, any new constants are regarded as being only partially defined
|
639
695
|
# and will be removed immediately.
|
640
696
|
def new_constants_in(*descs)
|
641
|
-
log_call(*descs)
|
642
|
-
|
643
697
|
constant_watch_stack.watch_namespaces(descs)
|
644
|
-
|
698
|
+
success = false
|
645
699
|
|
646
700
|
begin
|
647
701
|
yield # Now yield to the code that is to define new constants.
|
648
|
-
|
702
|
+
success = true
|
649
703
|
ensure
|
650
704
|
new_constants = constant_watch_stack.new_constants
|
651
705
|
|
652
|
-
|
653
|
-
return new_constants unless aborting
|
706
|
+
return new_constants if success
|
654
707
|
|
655
|
-
|
656
|
-
new_constants.each { |c| remove_constant(c) }
|
708
|
+
# Remove partially loaded constants.
|
709
|
+
new_constants.each { |c| remove_constant(c) }
|
657
710
|
end
|
658
|
-
|
659
|
-
[]
|
660
711
|
end
|
661
712
|
|
662
713
|
# Convert the provided const desc to a qualified constant name (as a string).
|
663
714
|
# A module, class, symbol, or string may be provided.
|
664
715
|
def to_constant_name(desc) #:nodoc:
|
665
716
|
case desc
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
717
|
+
when String then desc.sub(/^::/, "")
|
718
|
+
when Symbol then desc.to_s
|
719
|
+
when Module
|
720
|
+
real_mod_name(desc) ||
|
721
|
+
raise(ArgumentError, "Anonymous modules have no name to be referenced by")
|
722
|
+
else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
|
672
723
|
end
|
673
724
|
end
|
674
725
|
|
675
726
|
def remove_constant(const) #:nodoc:
|
676
727
|
# Normalize ::Foo, ::Object::Foo, Object::Foo, Object::Object::Foo, etc. as Foo.
|
677
|
-
normalized = const.to_s.sub(/\A::/,
|
678
|
-
normalized.sub!(/\A(Object::)+/,
|
728
|
+
normalized = const.to_s.sub(/\A::/, "")
|
729
|
+
normalized.sub!(/\A(Object::)+/, "")
|
679
730
|
|
680
|
-
constants = normalized.split(
|
731
|
+
constants = normalized.split("::")
|
681
732
|
to_remove = constants.pop
|
682
733
|
|
683
734
|
# Remove the file path from the loaded list.
|
684
735
|
file_path = search_for_file(const.underscore)
|
685
736
|
if file_path
|
686
737
|
expanded = File.expand_path(file_path)
|
687
|
-
expanded.sub!(/\.rb\z/,
|
688
|
-
|
738
|
+
expanded.sub!(/\.rb\z/, "")
|
739
|
+
loaded.delete(expanded)
|
689
740
|
end
|
690
741
|
|
691
742
|
if constants.empty?
|
@@ -698,13 +749,11 @@ module ActiveSupport #:nodoc:
|
|
698
749
|
# here than require the caller to be clever. We check the parent
|
699
750
|
# rather than the very const argument because we do not want to
|
700
751
|
# trigger Kernel#autoloads, see the comment below.
|
701
|
-
parent_name = constants.join(
|
752
|
+
parent_name = constants.join("::")
|
702
753
|
return unless qualified_const_defined?(parent_name)
|
703
754
|
parent = constantize(parent_name)
|
704
755
|
end
|
705
756
|
|
706
|
-
log "removing constant #{const}"
|
707
|
-
|
708
757
|
# In an autoloaded user.rb like this
|
709
758
|
#
|
710
759
|
# autoload :Foo, 'foo'
|
@@ -725,7 +774,7 @@ module ActiveSupport #:nodoc:
|
|
725
774
|
begin
|
726
775
|
constantized = parent.const_get(to_remove, false)
|
727
776
|
rescue NameError
|
728
|
-
|
777
|
+
# The constant is no longer reachable, just skip it.
|
729
778
|
return
|
730
779
|
else
|
731
780
|
constantized.before_remove_const if constantized.respond_to?(:before_remove_const)
|
@@ -735,26 +784,19 @@ module ActiveSupport #:nodoc:
|
|
735
784
|
begin
|
736
785
|
parent.instance_eval { remove_const to_remove }
|
737
786
|
rescue NameError
|
738
|
-
|
787
|
+
# The constant is no longer reachable, just skip it.
|
739
788
|
end
|
740
789
|
end
|
741
790
|
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
arg_str = args.collect { |arg| arg.inspect } * ', '
|
746
|
-
/in `([a-z_\?\!]+)'/ =~ caller(1).first
|
747
|
-
selector = $1 || '<unknown>'
|
748
|
-
log "called #{selector}(#{arg_str})"
|
749
|
-
end
|
750
|
-
end
|
751
|
-
|
752
|
-
def log(msg)
|
753
|
-
logger.debug "Dependencies: #{msg}" if log_activity?
|
754
|
-
end
|
791
|
+
def log(message)
|
792
|
+
logger.debug("autoloading: #{message}") if logger && verbose
|
793
|
+
end
|
755
794
|
|
756
|
-
|
757
|
-
|
795
|
+
private
|
796
|
+
# Returns the original name of a class or module even if `name` has been
|
797
|
+
# overridden.
|
798
|
+
def real_mod_name(mod)
|
799
|
+
UNBOUND_METHOD_MODULE_NAME.bind(mod).call
|
758
800
|
end
|
759
801
|
end
|
760
802
|
end
|