-
Notifications
You must be signed in to change notification settings - Fork 185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure symlinked realpaths are not loaded twice #3189
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,9 @@ module FeatureLoader | |
# A snapshot of $LOADED_FEATURES, to check if the @loaded_features_index cache is up to date. | ||
@loaded_features_version = -1 | ||
|
||
@features_realpath_cache = {} | ||
@loaded_features_realpaths = {} | ||
|
||
@expanded_load_path = [] | ||
# A snapshot of $LOAD_PATH, to check if the @expanded_load_path cache is up to date. | ||
@load_path_version = -1 | ||
|
@@ -140,6 +143,16 @@ def self.find_feature_or_file(feature, use_feature_provided = true) | |
end | ||
end | ||
|
||
def self.load_unless_realpath_loaded(feature, path) | ||
# TODO: does this need to be synchronized? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes of course, you could use a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i was wondering if it should be under That's a good point, though, might be able to do the whole change in java 🤔 |
||
realpath = (@features_realpath_cache[path] ||= File.realpath(path) || path) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK File.realpath never returns false|nil, always a String, or an exception if some part does not exist. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That did seem to be the case for me but I wasn't sure if it was true on all platforms. |
||
return false if @loaded_features_realpaths.key?(realpath) | ||
|
||
result = Primitive.load_feature(feature, path) | ||
@loaded_features_realpaths[realpath] = path | ||
result | ||
end | ||
|
||
def self.expanded_path_provided(path, ext, use_feature_provided) | ||
if use_feature_provided && feature_provided?(path, true) | ||
[:feature_loaded, path, ext] | ||
|
@@ -292,13 +305,24 @@ def self.get_loaded_features_index | |
unless @loaded_features_version == $LOADED_FEATURES.version | ||
raise '$LOADED_FEATURES is frozen; cannot append feature' if $LOADED_FEATURES.frozen? | ||
@loaded_features_index.clear | ||
previous_realpaths = @features_realpath_cache.dup | ||
@features_realpath_cache.clear | ||
@loaded_features_realpaths.clear | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this cache never needs to be cleared. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it was necessary to satisfy the specs, and I saw the CRuby code doing something simliar: |
||
$LOADED_FEATURES.map! do |val| | ||
val = StringValue(val) | ||
#val.freeze # TODO freeze these but post-boot.rb issue using replace | ||
val | ||
end | ||
$LOADED_FEATURES.each_with_index do |val, idx| | ||
features_index_add(val, idx) | ||
# TODO: do we need to do this in a separate loop on a copy to avoid | ||
# concurrency issues? it's already called from with_synchronized_features. | ||
# https://github.com/ruby/ruby/pull/4887/commits/972f2744d8145db965f1c4218313bd200ea0a740#:~:text=To%20avoid%20concurrency%20issues%20when%20rebuilding%20the%20loaded%20features%0Aindex%2C%20the%20building%20of%20the%20index%20itself%20is%20left%20alone%2C%20and%0Aafterwards%2C%20a%20separate%20loop%20is%20done%20on%20a%20copy%20of%20the%20loaded%20feature%0Asnapshot%20in%20order%20to%20rebuild%20the%20realpaths%20hash. | ||
# end | ||
# $LOADED_FEATURES.dup.each_with_index do |val, idx| | ||
realpath = previous_realpaths[val] || (File.exist?(val) ? File.realpath(val) : val) | ||
@features_realpath_cache[val] = realpath | ||
@loaded_features_realpaths[realpath] = val | ||
end | ||
@loaded_features_version = $LOADED_FEATURES.version | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this cache is correct, for instance it seems broken if CWD changes or $LOAD_PATH changes.
Probably that part shouldn't be cached.
You could cache absolute_path->realpath though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, we probably want absolute path as the key.