Skip to content

Commit b43b733

Browse files
author
Edward Ocampo-Gooding
committed
Report when a Sass type used in a function is unsupported
1 parent 1f4c9b9 commit b43b733

File tree

2 files changed

+100
-53
lines changed

2 files changed

+100
-53
lines changed

lib/sassc/functions_handler.rb

+36-21
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,40 @@ def setup(native_options)
1717
@callbacks[custom_function] = FFI::Function.new(:pointer, [:pointer, :pointer]) do |native_argument_list, cookie|
1818
native_argument_list_length = Native.list_get_length(native_argument_list)
1919
custom_function_arguments = []
20+
errorTag = nil
2021

2122
(0...native_argument_list_length).each do |i|
2223
native_value = Native.list_get_value(native_argument_list, i)
2324

24-
case Native.value_get_tag(native_value)
25+
case value_tag = Native.value_get_tag(native_value)
26+
when :sass_null
27+
# no-op
2528
when :sass_string
2629
native_string = Native.string_get_value(native_value)
2730
argument = Script::String.new(Script::String.unquote(native_string), Script::String.type(native_string))
2831

2932
custom_function_arguments << argument
33+
else
34+
errorTag = error(message: "Sass argument of type #{value_tag} unsupported")
35+
break
3036
end
3137
end
3238

33-
begin
34-
value = functions.send(custom_function, *custom_function_arguments)
35-
36-
if value
37-
value = Script::String.new(Script::String.unquote(value.to_s), value.type)
38-
value.to_native
39-
else
40-
Script::String.new("").to_native
39+
if errorTag
40+
errorTag
41+
else
42+
begin
43+
value = functions.send(custom_function, *custom_function_arguments)
44+
45+
if value
46+
value = Script::String.new(Script::String.unquote(value.to_s), value.type)
47+
value.to_native
48+
else
49+
Script::String.new("").to_native
50+
end
51+
rescue StandardError => exception
52+
error(message: exception.message)
4153
end
42-
rescue StandardError => exception
43-
value = Native::SassValue.new
44-
value[:unknown] = Native::SassUnknown.new
45-
46-
error = Native::SassError.new
47-
error[:tag] = :sass_error
48-
49-
Native.error_set_message(error, Native.native_string(exception))
50-
51-
value[:unknown][:tag] = :sass_error
52-
value[:error] = error
53-
value.pointer
5454
end
5555
end
5656

@@ -70,6 +70,21 @@ def setup(native_options)
7070

7171
private
7272

73+
def error(message:)
74+
value = Native::SassValue.new
75+
value[:unknown] = Native::SassUnknown.new
76+
77+
error = Native::SassError.new
78+
error[:tag] = :sass_error
79+
80+
Native.error_set_message(error, Native.native_string(message))
81+
$stderr.puts "[SassC::FunctionsHandler] #{message}"
82+
83+
value[:unknown][:tag] = :sass_error
84+
value[:error] = error
85+
value.pointer
86+
end
87+
7388
class FunctionWrapper
7489
class << self
7590
attr_accessor :options

test/functions_test.rb

+64-32
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,16 @@
11
require_relative "test_helper"
2+
require "stringio"
23

34
module SassC
45
class FunctionsTest < MiniTest::Test
56
include FixtureHelper
67

7-
SassString = Struct.new(:value, :type) do
8-
def to_s
9-
value
10-
end
8+
def setup
9+
@real_stderr, $stderr = $stderr, StringIO.new
1110
end
1211

13-
module Script::Functions
14-
def javascript_path(path)
15-
Script::String.new("/js/#{path.value}", :string)
16-
end
17-
18-
def no_return_path(path)
19-
nil
20-
end
21-
22-
def sass_return_path(path)
23-
return SassString.new("'#{path.value}'", :string)
24-
end
25-
26-
def optional_arguments(path, optional = "bar")
27-
return SassString.new("#{path}/#{optional}", :string)
28-
end
29-
30-
def function_that_raises_errors()
31-
raise StandardError, "Intentional wrong thing happened somewhere inside the custom function"
32-
end
33-
34-
module Compass
35-
def stylesheet_path(path)
36-
Script::String.new("/css/#{path.value}", :identifier)
37-
end
38-
end
39-
include Compass
12+
def teardown
13+
$stderr = @real_stderr
4014
end
4115

4216
def test_functions_may_return_sass_string_type
@@ -88,9 +62,21 @@ def test_function_with_optional_arguments
8862
EOS
8963
end
9064

65+
def test_function_with_unsupported_tag
66+
engine = Engine.new("div {url: function_with_unsupported_tag(red);}")
67+
68+
exception = assert_raises(SassC::SyntaxError) do
69+
engine.render
70+
end
71+
72+
assert_equal "Error: error in C function function_with_unsupported_tag: Sass argument of type sass_color unsupported\n\n Backtrace:\n \tstdin:1, in function `function_with_unsupported_tag`\n \tstdin:1\n on line 1 of stdin\n>> div {url: function_with_unsupported_tag(red);}\n ----------^\n", exception.message
73+
74+
assert_equal "[SassC::FunctionsHandler] Sass argument of type sass_color unsupported", stderr_output
75+
end
76+
9177
def test_function_with_error
9278
engine = Engine.new("div {url: function_that_raises_errors();}")
93-
exception = assert_raises(SassC::SyntaxError, "") do
79+
exception = assert_raises(SassC::SyntaxError) do
9480
engine.render
9581
end
9682

@@ -103,6 +89,52 @@ def test_function_with_error
10389
>> div {url: function_that_raises_errors();}
10490
----------^
10591
", exception.message
92+
93+
assert_equal "[SassC::FunctionsHandler] Intentional wrong thing happened somewhere inside the custom function", stderr_output
94+
end
95+
96+
private
97+
98+
SassString = Struct.new(:value, :type) do
99+
def to_s
100+
value
101+
end
102+
end
103+
104+
module Script::Functions
105+
def javascript_path(path)
106+
Script::String.new("/js/#{path.value}", :string)
107+
end
108+
109+
def no_return_path(path)
110+
nil
111+
end
112+
113+
def sass_return_path(path)
114+
return SassString.new("'#{path.value}'", :string)
115+
end
116+
117+
def optional_arguments(path, optional = "bar")
118+
return SassString.new("#{path}/#{optional}", :string)
119+
end
120+
121+
def function_that_raises_errors()
122+
raise StandardError, "Intentional wrong thing happened somewhere inside the custom function"
123+
end
124+
125+
def function_with_unsupported_tag(color)
126+
end
127+
128+
module Compass
129+
def stylesheet_path(path)
130+
Script::String.new("/css/#{path.value}", :identifier)
131+
end
132+
end
133+
include Compass
134+
end
135+
136+
def stderr_output
137+
$stderr.string.gsub("\u0000\n", '')
106138
end
107139
end
108140
end

0 commit comments

Comments
 (0)