Skip to content
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

allow passing functions directly #162

Merged
merged 1 commit into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/sassc/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Engine
def initialize(template, options = {})
@template = template
@options = options
@functions = options.fetch(:functions, Script::Functions)
end

def render
Expand All @@ -37,7 +38,7 @@ def render
Native.option_set_omit_source_map_url(native_options, true) if omit_source_map_url?

import_handler.setup(native_options)
functions_handler.setup(native_options)
functions_handler.setup(native_options, functions: @functions)

status = Native.compile_data_context(data_context)

Expand Down
16 changes: 8 additions & 8 deletions lib/sassc/functions_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@ def initialize(options)
@options = options
end

def setup(native_options)
def setup(native_options, functions: Script::Functions)
@callbacks = {}
@function_names = {}

list = Native.make_function_list(Script.custom_functions.count)
list = Native.make_function_list(Script.custom_functions(functions: functions).count)

# use an anonymous class wrapper to avoid mutations in a threaded environment
functions = Class.new do
functions_wrapper = Class.new do
attr_accessor :options
include Script::Functions
include functions
end.new
functions.options = @options
functions_wrapper.options = @options

Script.custom_functions.each_with_index do |custom_function, i|
Script.custom_functions(functions: functions).each_with_index do |custom_function, i|
@callbacks[custom_function] = FFI::Function.new(:pointer, [:pointer, :pointer]) do |native_argument_list, cookie|
begin
function_arguments = arguments_from_native_list(native_argument_list)
result = functions.send(custom_function, *function_arguments)
result = functions_wrapper.send(custom_function, *function_arguments)
to_native_value(result)
rescue StandardError => exception
# This rescues any exceptions that occur either in value conversion
Expand All @@ -32,7 +32,7 @@ def setup(native_options)
end
end

@function_names[custom_function] = Script.formatted_function_name(custom_function)
@function_names[custom_function] = Script.formatted_function_name(custom_function, functions: functions)

callback = Native.make_function(
@function_names[custom_function],
Expand Down
8 changes: 4 additions & 4 deletions lib/sassc/script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
module SassC
module Script

def self.custom_functions
Functions.public_instance_methods
def self.custom_functions(functions: Functions)
functions.public_instance_methods
end

def self.formatted_function_name(function_name)
params = Functions.instance_method(function_name).parameters
def self.formatted_function_name(function_name, functions: Functions)
params = functions.instance_method(function_name).parameters
params = params.map { |param_type, name| "$#{name}#{': null' if param_type == :opt}" }.join(", ")
return "#{function_name}(#{params})"
end
Expand Down
17 changes: 17 additions & 0 deletions test/functions_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ def test_concurrency
end
end

def test_pass_custom_functions_as_a_parameter
out = Engine.new("div { url: test-function(); }", {functions: ExternalFunctions}).render
assert_match /custom_function/, out
end

def test_pass_incompatible_type_to_custom_functions
assert_raises(TypeError) do
Engine.new("div { url: test-function(); }", {functions: Class.new}).render
end
end

private

def assert_sass(sass, expected_css)
Expand Down Expand Up @@ -319,5 +330,11 @@ def returns_sass_list

end

module ExternalFunctions
def test_function
SassC::Script::Value::String.new("custom_function", :string)
end
end

end
end