diff --git a/CHANGELOG.md b/CHANGELOG.md index a9e699cb2..4fe4f33cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprockets/blob/master/UPGRADING.md - Add support for Rack 3.0. Headers set by sprockets will now be lower case. [#758](https://github.com/rails/sprockets/pull/758) +- Make `Sprockets::Utils.module_include` thread safe on JRuby. [#759](https://github.com/rails/sprockets/pull/759) ## 4.1.0 diff --git a/lib/sprockets/utils.rb b/lib/sprockets/utils.rb index 09f5a1db2..e0a5ff7b4 100644 --- a/lib/sprockets/utils.rb +++ b/lib/sprockets/utils.rb @@ -118,33 +118,38 @@ def concat_javascript_sources(buf, source) buf end + MODULE_INCLUDE_MUTEX = Mutex.new + private_constant :MODULE_INCLUDE_MUTEX + # Internal: Inject into target module for the duration of the block. # # mod - Module # # Returns result of block. def module_include(base, mod) - old_methods = {} + MODULE_INCLUDE_MUTEX.synchronize do + old_methods = {} - mod.instance_methods.each do |sym| - old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym) - end + mod.instance_methods.each do |sym| + old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym) + end - mod.instance_methods.each do |sym| - method = mod.instance_method(sym) - if base.method_defined?(sym) - base.send(:alias_method, sym, sym) + mod.instance_methods.each do |sym| + method = mod.instance_method(sym) + if base.method_defined?(sym) + base.send(:alias_method, sym, sym) + end + base.send(:define_method, sym, method) end - base.send(:define_method, sym, method) - end - yield - ensure - mod.instance_methods.each do |sym| - base.send(:undef_method, sym) if base.method_defined?(sym) - end - old_methods.each do |sym, method| - base.send(:define_method, sym, method) + yield + ensure + mod.instance_methods.each do |sym| + base.send(:undef_method, sym) if base.method_defined?(sym) + end + old_methods.each do |sym, method| + base.send(:define_method, sym, method) + end end end