diff --git a/lib/sass/compiler/host/function_registry.rb b/lib/sass/compiler/host/function_registry.rb index 29e2c11..9f8786a 100644 --- a/lib/sass/compiler/host/function_registry.rb +++ b/lib/sass/compiler/host/function_registry.rb @@ -7,11 +7,12 @@ class Host # # It stores sass custom functions and handles function calls. class FunctionRegistry - attr_reader :global_functions + attr_reader :environment, :global_functions def initialize(functions, alert_color:) functions = functions.transform_keys(&:to_s) + @environment = BasicObject.new @global_functions = functions.keys @functions_by_name = functions.transform_keys do |signature| index = signature.index('(') diff --git a/lib/sass/compiler/host/protofier.rb b/lib/sass/compiler/host/protofier.rb index 610e3f7..04497fc 100644 --- a/lib/sass/compiler/host/protofier.rb +++ b/lib/sass/compiler/host/protofier.rb @@ -64,6 +64,8 @@ def to_proto(obj) ) when Sass::Value::Function if obj.instance_variable_defined?(:@id) + assert_compiler_value(obj) + EmbeddedProtocol::Value.new( compiler_function: EmbeddedProtocol::Value::CompilerFunction.new( id: obj.instance_variable_get(:@id) @@ -78,6 +80,8 @@ def to_proto(obj) ) end when Sass::Value::Mixin + assert_compiler_value(obj) + EmbeddedProtocol::Value.new( compiler_mixin: EmbeddedProtocol::Value::CompilerMixin.new( id: obj.instance_variable_get(:@id) @@ -148,17 +152,11 @@ def from_proto(proto) end ) when :compiler_function - Sass::Value::Function.allocate.instance_eval do - @id = obj.id - self - end + compiler_value(Sass::Value::Function, obj.id) when :host_function raise Sass::ScriptError, 'The compiler may not send Value.host_function to host' when :compiler_mixin - Sass::Value::Mixin.allocate.instance_eval do - @id = obj.id - self - end + compiler_value(Sass::Value::Mixin, obj.id) when :calculation Calculation.from_proto(obj) when :singleton @@ -177,6 +175,23 @@ def from_proto(proto) end end + private + + def assert_compiler_value(value) + unless value.instance_variable_get(:@environment) == @function_registry.environment + raise Sass::ScriptError, "Returned #{value} does not belong to this compilation" + end + + value + end + + def compiler_value(klass, id) + value = klass.allocate + value.instance_variable_set(:@environment, @function_registry.environment) + value.instance_variable_set(:@id, id) + value + end + # The {Number} Protofier. module Number module_function diff --git a/lib/sass/value/function.rb b/lib/sass/value/function.rb index eef9103..82a1046 100644 --- a/lib/sass/value/function.rb +++ b/lib/sass/value/function.rb @@ -15,6 +15,9 @@ def initialize(signature, &callback) @callback = callback.freeze end + # @return [Object, nil] + protected attr_reader :environment + # @return [Integer, nil] protected attr_reader :id @@ -26,10 +29,10 @@ def initialize(signature, &callback) # @return [::Boolean] def ==(other) - if id.nil? - other.equal?(self) + if defined?(@id) + other.is_a?(Sass::Value::Function) && other.environment == environment && other.id == id else - other.is_a?(Sass::Value::Function) && other.id == id + other.equal?(self) end end diff --git a/lib/sass/value/mixin.rb b/lib/sass/value/mixin.rb index 2f65fdb..469eb75 100644 --- a/lib/sass/value/mixin.rb +++ b/lib/sass/value/mixin.rb @@ -12,12 +12,15 @@ class << self private :new end + # @return [Object] + protected attr_reader :environment + # @return [Integer] protected attr_reader :id # @return [::Boolean] def ==(other) - other.is_a?(Sass::Value::Mixin) && other.id == id + other.is_a?(Sass::Value::Mixin) && other.environment == environment && other.id == id end # @return [Integer]