From 971cb103fc2b02ecee2ed919a2e49b5ffb2637cd Mon Sep 17 00:00:00 2001 From: Ryan Boland Date: Aug 19 2019 18:27:36 +0000 Subject: Merge pull request #138 from ahorek/concurrency_fix thread safe function helpers --- diff --git a/lib/sassc/functions_handler.rb b/lib/sassc/functions_handler.rb index c223779..97a1097 100644 --- a/lib/sassc/functions_handler.rb +++ b/lib/sassc/functions_handler.rb @@ -12,7 +12,11 @@ module SassC list = Native.make_function_list(Script.custom_functions.count) - functions = FunctionWrapper.extend(Script::Functions) + # use an anonymous class wrapper to avoid mutations in a threaded environment + functions = Class.new do + attr_accessor :options + include Script::Functions + end.new functions.options = @options Script.custom_functions.each_with_index do |custom_function, i| @@ -65,11 +69,5 @@ module SassC $stderr.puts "[SassC::FunctionsHandler] #{message}" Native.make_error(message) end - - class FunctionWrapper - class << self - attr_accessor :options - end - end end end diff --git a/test/functions_test.rb b/test/functions_test.rb index 71fc0fa..5cf7aec 100644 --- a/test/functions_test.rb +++ b/test/functions_test.rb @@ -185,6 +185,22 @@ module SassC CSS end + def test_concurrency + 10.times do + threads = [] + 10.times do |i| + threads << Thread.new(i) do |id| + out = Engine.new("div { url: inspect_options(); }", {test_key1: 'test_value', test_key2: id}).render + assert_match /test_key1/, out + assert_match /test_key2/, out + assert_match /test_value/, out + assert_match /#{id}/, out + end + end + threads.each(&:join) + end + end + private def assert_sass(sass, expected_css) @@ -279,6 +295,10 @@ module SassC return argument end + def inspect_options + SassC::Script::Value::String.new(self.options.inspect, :string) + end + def returns_sass_value return SassC::Script::Value::Color.new(red: 0, green: 0, blue: 0) end