sassc 1.10.1 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/ext/libsass/.github/CONTRIBUTING.md +65 -0
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +29 -0
- data/ext/libsass/Makefile +8 -3
- data/ext/libsass/Makefile.conf +28 -22
- data/ext/libsass/Readme.md +14 -7
- data/ext/libsass/configure.ac +5 -8
- data/ext/libsass/docs/api-context-internal.md +3 -0
- data/ext/libsass/docs/api-context.md +7 -0
- data/ext/libsass/docs/api-doc.md +4 -0
- data/ext/libsass/docs/api-importer.md +2 -0
- data/ext/libsass/docs/api-value-example.md +55 -0
- data/ext/libsass/docs/api-value.md +49 -22
- data/ext/libsass/docs/implementations.md +4 -0
- data/ext/libsass/include/sass/base.h +5 -4
- data/ext/libsass/include/sass/context.h +3 -0
- data/ext/libsass/include/sass/values.h +28 -27
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/script/ci-build-libsass +3 -3
- data/ext/libsass/script/ci-install-deps +12 -3
- data/ext/libsass/src/ast.cpp +321 -212
- data/ext/libsass/src/ast.hpp +273 -165
- data/ext/libsass/src/ast_factory.hpp +4 -5
- data/ext/libsass/src/ast_fwd_decl.hpp +8 -7
- data/ext/libsass/src/bind.cpp +2 -7
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/check_nesting.cpp +379 -0
- data/ext/libsass/src/check_nesting.hpp +60 -0
- data/ext/libsass/src/constants.cpp +7 -6
- data/ext/libsass/src/constants.hpp +2 -1
- data/ext/libsass/src/context.cpp +7 -1
- data/ext/libsass/src/context.hpp +1 -1
- data/ext/libsass/src/cssize.cpp +76 -32
- data/ext/libsass/src/cssize.hpp +7 -8
- data/ext/libsass/src/debugger.hpp +70 -40
- data/ext/libsass/src/error_handling.cpp +15 -2
- data/ext/libsass/src/error_handling.hpp +19 -0
- data/ext/libsass/src/eval.cpp +107 -161
- data/ext/libsass/src/eval.hpp +12 -8
- data/ext/libsass/src/expand.cpp +81 -74
- data/ext/libsass/src/expand.hpp +13 -12
- data/ext/libsass/src/extend.cpp +149 -142
- data/ext/libsass/src/extend.hpp +10 -3
- data/ext/libsass/src/file.cpp +2 -1
- data/ext/libsass/src/functions.cpp +96 -59
- data/ext/libsass/src/functions.hpp +2 -2
- data/ext/libsass/src/inspect.cpp +33 -45
- data/ext/libsass/src/inspect.hpp +7 -7
- data/ext/libsass/src/json.cpp +17 -5
- data/ext/libsass/src/lexer.cpp +3 -3
- data/ext/libsass/src/listize.cpp +10 -10
- data/ext/libsass/src/listize.hpp +3 -3
- data/ext/libsass/src/node.cpp +30 -30
- data/ext/libsass/src/node.hpp +13 -13
- data/ext/libsass/src/operation.hpp +21 -19
- data/ext/libsass/src/output.cpp +48 -103
- data/ext/libsass/src/output.hpp +0 -1
- data/ext/libsass/src/parser.cpp +161 -133
- data/ext/libsass/src/parser.hpp +10 -7
- data/ext/libsass/src/remove_placeholders.cpp +6 -6
- data/ext/libsass/src/remove_placeholders.hpp +1 -1
- data/ext/libsass/src/sass.cpp +21 -0
- data/ext/libsass/src/sass.hpp +8 -1
- data/ext/libsass/src/sass2scss.cpp +14 -3
- data/ext/libsass/src/sass_context.cpp +69 -24
- data/ext/libsass/src/sass_context.hpp +3 -0
- data/ext/libsass/src/source_map.cpp +22 -10
- data/ext/libsass/src/to_value.cpp +2 -2
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.hpp +3 -1
- data/ext/libsass/src/util.cpp +20 -16
- data/ext/libsass/src/util.hpp +2 -1
- data/ext/libsass/win/libsass.targets +2 -0
- data/ext/libsass/win/libsass.vcxproj.filters +6 -0
- data/lib/sassc/engine.rb +5 -0
- data/lib/sassc/native/native_functions_api.rb +13 -1
- data/lib/sassc/script/value_conversion.rb +11 -1
- data/lib/sassc/script/value_conversion/list.rb +23 -0
- data/lib/sassc/version.rb +1 -1
- data/test/engine_test.rb +18 -2
- data/test/functions_test.rb +30 -0
- data/test/native_test.rb +1 -1
- metadata +8 -3
@@ -35,11 +35,19 @@ namespace Sass {
|
|
35
35
|
: Base(pstate), fn(fn), arg(arg), type(type), value(value)
|
36
36
|
{
|
37
37
|
msg = arg + ": \"";
|
38
|
-
msg += value->to_string(Sass_Inspect_Options());
|
38
|
+
if (value) msg += value->to_string(Sass_Inspect_Options());
|
39
39
|
msg += "\" is not a " + type;
|
40
40
|
msg += " for `" + fn + "'";
|
41
41
|
}
|
42
42
|
|
43
|
+
MissingArgument::MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype)
|
44
|
+
: Base(pstate), fn(fn), arg(arg), fntype(fntype)
|
45
|
+
{
|
46
|
+
msg = fntype + " " + fn;
|
47
|
+
msg += " is missing argument ";
|
48
|
+
msg += arg + ".";
|
49
|
+
}
|
50
|
+
|
43
51
|
InvalidSyntax::InvalidSyntax(ParserState pstate, std::string msg, std::vector<Sass_Import_Entry>* import_stack)
|
44
52
|
: Base(pstate, msg, import_stack)
|
45
53
|
{ }
|
@@ -74,7 +82,6 @@ namespace Sass {
|
|
74
82
|
: Base(org.pstate()), dup(dup), org(org)
|
75
83
|
{
|
76
84
|
msg = "Duplicate key ";
|
77
|
-
dup.get_duplicate_key()->is_delayed(false);
|
78
85
|
msg += dup.get_duplicate_key()->inspect();
|
79
86
|
msg += " in map (";
|
80
87
|
msg += org.inspect();
|
@@ -97,6 +104,12 @@ namespace Sass {
|
|
97
104
|
msg += " isn't a valid CSS value.";
|
98
105
|
}
|
99
106
|
|
107
|
+
StackError::StackError(const AST_Node& node)
|
108
|
+
: Base(node.pstate()), node(node)
|
109
|
+
{
|
110
|
+
msg = "stack level too deep";
|
111
|
+
}
|
112
|
+
|
100
113
|
IncompatibleUnits::IncompatibleUnits(const Number& lhs, const Number& rhs)
|
101
114
|
: lhs(lhs), rhs(rhs)
|
102
115
|
{
|
@@ -45,6 +45,16 @@ namespace Sass {
|
|
45
45
|
virtual ~InvalidParent() throw() {};
|
46
46
|
};
|
47
47
|
|
48
|
+
class MissingArgument : public Base {
|
49
|
+
protected:
|
50
|
+
std::string fn;
|
51
|
+
std::string arg;
|
52
|
+
std::string fntype;
|
53
|
+
public:
|
54
|
+
MissingArgument(ParserState pstate, std::string fn, std::string arg, std::string fntype);
|
55
|
+
virtual ~MissingArgument() throw() {};
|
56
|
+
};
|
57
|
+
|
48
58
|
class InvalidArgumentType : public Base {
|
49
59
|
protected:
|
50
60
|
std::string fn;
|
@@ -115,6 +125,15 @@ namespace Sass {
|
|
115
125
|
virtual ~InvalidValue() throw() {};
|
116
126
|
};
|
117
127
|
|
128
|
+
class StackError : public Base {
|
129
|
+
protected:
|
130
|
+
const AST_Node& node;
|
131
|
+
public:
|
132
|
+
StackError(const AST_Node& node);
|
133
|
+
virtual const char* errtype() const { return "SystemStackError"; }
|
134
|
+
virtual ~StackError() throw() {};
|
135
|
+
};
|
136
|
+
|
118
137
|
class IncompatibleUnits : public OperationError {
|
119
138
|
protected:
|
120
139
|
const Number& lhs;
|
data/ext/libsass/src/eval.cpp
CHANGED
@@ -31,7 +31,14 @@ namespace Sass {
|
|
31
31
|
inline double sub(double x, double y) { return x - y; }
|
32
32
|
inline double mul(double x, double y) { return x * y; }
|
33
33
|
inline double div(double x, double y) { return x / y; } // x/0 checked by caller
|
34
|
-
inline double mod(double x, double y) {
|
34
|
+
inline double mod(double x, double y) { // x/0 checked by caller
|
35
|
+
if ((x > 0 && y < 0) || (x < 0 && y > 0)) {
|
36
|
+
double ret = std::fmod(x, y);
|
37
|
+
return ret ? ret + y : ret;
|
38
|
+
} else {
|
39
|
+
return std::fmod(x, y);
|
40
|
+
}
|
41
|
+
}
|
35
42
|
typedef double (*bop)(double, double);
|
36
43
|
bop ops[Sass_OP::NUM_OPS] = {
|
37
44
|
0, 0, // and, or
|
@@ -41,7 +48,9 @@ namespace Sass {
|
|
41
48
|
|
42
49
|
Eval::Eval(Expand& exp)
|
43
50
|
: exp(exp),
|
44
|
-
ctx(exp.ctx)
|
51
|
+
ctx(exp.ctx),
|
52
|
+
force(false),
|
53
|
+
is_in_comment(false)
|
45
54
|
{ }
|
46
55
|
Eval::~Eval() { }
|
47
56
|
|
@@ -55,7 +64,7 @@ namespace Sass {
|
|
55
64
|
return exp.environment();
|
56
65
|
}
|
57
66
|
|
58
|
-
|
67
|
+
CommaSequence_Selector* Eval::selector()
|
59
68
|
{
|
60
69
|
return exp.selector();
|
61
70
|
}
|
@@ -221,7 +230,7 @@ namespace Sass {
|
|
221
230
|
if (expr->concrete_type() == Expression::MAP) {
|
222
231
|
map = static_cast<Map*>(expr);
|
223
232
|
}
|
224
|
-
else if (
|
233
|
+
else if (CommaSequence_Selector* ls = dynamic_cast<CommaSequence_Selector*>(expr)) {
|
225
234
|
Listize listize(ctx.mem);
|
226
235
|
list = dynamic_cast<List*>(ls->perform(&listize));
|
227
236
|
}
|
@@ -255,7 +264,7 @@ namespace Sass {
|
|
255
264
|
}
|
256
265
|
}
|
257
266
|
else {
|
258
|
-
if (list->length() == 1 && dynamic_cast<
|
267
|
+
if (list->length() == 1 && dynamic_cast<CommaSequence_Selector*>(list)) {
|
259
268
|
list = dynamic_cast<Vectorized<Expression*>*>(list);
|
260
269
|
}
|
261
270
|
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
@@ -436,7 +445,7 @@ namespace Sass {
|
|
436
445
|
Expression* key = (*l)[i+0]->perform(this);
|
437
446
|
Expression* val = (*l)[i+1]->perform(this);
|
438
447
|
// make sure the color key never displays its real name
|
439
|
-
key->is_delayed(true);
|
448
|
+
key->is_delayed(true); // verified
|
440
449
|
*lm << std::make_pair(key, val);
|
441
450
|
}
|
442
451
|
if (lm->has_duplicate_key()) {
|
@@ -497,21 +506,13 @@ namespace Sass {
|
|
497
506
|
String_Schema* ret_schema = 0;
|
498
507
|
enum Sass_OP op_type = b->type();
|
499
508
|
|
500
|
-
// don't eval delayed expressions (the '/' when used as a separator)
|
501
|
-
if (op_type == Sass_OP::DIV && b->is_delayed()) {
|
502
|
-
b->right(b->right()->perform(this));
|
503
|
-
b->left(b->left()->perform(this));
|
504
|
-
return b;
|
505
|
-
}
|
506
|
-
|
507
509
|
// only the last item will be used to eval the binary expression
|
508
510
|
if (String_Schema* s_l = dynamic_cast<String_Schema*>(b->left())) {
|
509
511
|
if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
|
510
|
-
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema,
|
512
|
+
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, b->pstate());
|
511
513
|
Binary_Expression* bin_ex = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, b->pstate(),
|
512
514
|
b->op(), s_l->last(), b->right());
|
513
|
-
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed());
|
514
|
-
// bin_ex->is_interpolant(b->left()->is_interpolant());
|
515
|
+
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // unverified
|
515
516
|
for (size_t i = 0; i < s_l->length() - 1; ++i) {
|
516
517
|
*ret_schema << s_l->at(i)->perform(this);
|
517
518
|
}
|
@@ -521,11 +522,10 @@ namespace Sass {
|
|
521
522
|
}
|
522
523
|
if (String_Schema* s_r = dynamic_cast<String_Schema*>(b->right())) {
|
523
524
|
if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
|
524
|
-
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema,
|
525
|
+
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, b->pstate());
|
525
526
|
Binary_Expression* bin_ex = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, b->pstate(),
|
526
527
|
b->op(), b->left(), s_r->first());
|
527
|
-
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed());
|
528
|
-
// if (op_type == Sass_OP::SUB && b->is_right_interpolant()) bin_ex->is_interpolant(true);
|
528
|
+
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed()); // verified
|
529
529
|
*ret_schema << bin_ex->perform(this);
|
530
530
|
for (size_t i = 1; i < s_r->length(); ++i) {
|
531
531
|
*ret_schema << s_r->at(i)->perform(this);
|
@@ -535,34 +535,18 @@ namespace Sass {
|
|
535
535
|
}
|
536
536
|
|
537
537
|
|
538
|
+
b = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, *b);
|
538
539
|
// don't eval delayed expressions (the '/' when used as a separator)
|
539
|
-
if (op_type == Sass_OP::DIV && b->is_delayed()) {
|
540
|
+
if (!force && op_type == Sass_OP::DIV && b->is_delayed()) {
|
540
541
|
b->right(b->right()->perform(this));
|
541
542
|
b->left(b->left()->perform(this));
|
542
543
|
return b;
|
543
544
|
}
|
544
545
|
|
545
|
-
// b->is_delayed(false);
|
546
546
|
Expression* lhs = b->left();
|
547
547
|
Expression* rhs = b->right();
|
548
548
|
|
549
|
-
//
|
550
|
-
// bool delay_rhs = false;
|
551
|
-
|
552
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(lhs)) {
|
553
|
-
if (schema->is_right_interpolant()) {
|
554
|
-
b->is_delayed(true);
|
555
|
-
// delay_lhs = true;
|
556
|
-
}
|
557
|
-
}
|
558
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(rhs)) {
|
559
|
-
if (schema->is_left_interpolant()) {
|
560
|
-
b->is_delayed(true);
|
561
|
-
// delay_rhs = true;
|
562
|
-
}
|
563
|
-
}
|
564
|
-
|
565
|
-
// maybe fully evaluate structure
|
549
|
+
// fully evaluate their values
|
566
550
|
if (op_type == Sass_OP::EQ ||
|
567
551
|
op_type == Sass_OP::NEQ ||
|
568
552
|
op_type == Sass_OP::GT ||
|
@@ -570,43 +554,16 @@ namespace Sass {
|
|
570
554
|
op_type == Sass_OP::LT ||
|
571
555
|
op_type == Sass_OP::LTE)
|
572
556
|
{
|
573
|
-
|
574
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(lhs)) {
|
575
|
-
if (schema->has_interpolants()) {
|
576
|
-
b->is_delayed(true);
|
577
|
-
}
|
578
|
-
}
|
579
|
-
if (String_Schema* schema = dynamic_cast<String_Schema*>(rhs)) {
|
580
|
-
if (schema->has_interpolants()) {
|
581
|
-
b->is_delayed(true);
|
582
|
-
}
|
583
|
-
}
|
584
|
-
lhs->is_expanded(false);
|
585
|
-
lhs->set_delayed(false);
|
586
|
-
lhs = lhs->perform(this);
|
557
|
+
LOCAL_FLAG(force, true);
|
587
558
|
lhs->is_expanded(false);
|
588
559
|
lhs->set_delayed(false);
|
589
560
|
lhs = lhs->perform(this);
|
590
561
|
rhs->is_expanded(false);
|
591
562
|
rhs->set_delayed(false);
|
592
563
|
rhs = rhs->perform(this);
|
593
|
-
rhs->is_expanded(false);
|
594
|
-
rhs->set_delayed(false);
|
595
|
-
rhs = rhs->perform(this);
|
596
|
-
}
|
597
|
-
else
|
598
|
-
{
|
599
|
-
// rhs->set_delayed(false);
|
600
|
-
// rhs = rhs->perform(this);
|
601
564
|
}
|
602
|
-
|
603
|
-
|
604
|
-
lhs = lhs->perform(this);
|
605
|
-
lhs->is_delayed(false);
|
606
|
-
while (typeid(*lhs) == typeid(Binary_Expression)) {
|
607
|
-
Binary_Expression* lhs_ex = static_cast<Binary_Expression*>(lhs);
|
608
|
-
if (lhs_ex->type() == Sass_OP::DIV && lhs_ex->is_delayed()) break;
|
609
|
-
lhs = Eval::operator()(lhs_ex);
|
565
|
+
else {
|
566
|
+
lhs = lhs->perform(this);
|
610
567
|
}
|
611
568
|
|
612
569
|
switch (op_type) {
|
@@ -624,19 +581,6 @@ namespace Sass {
|
|
624
581
|
// not a logical connective, so go ahead and eval the rhs
|
625
582
|
rhs = rhs->perform(this);
|
626
583
|
|
627
|
-
// upgrade string to number if possible (issue #948)
|
628
|
-
if (op_type == Sass_OP::DIV || op_type == Sass_OP::MUL) {
|
629
|
-
if (String_Constant* str = dynamic_cast<String_Constant*>(rhs)) {
|
630
|
-
std::string value(str->value());
|
631
|
-
const char* start = value.c_str();
|
632
|
-
if (Prelexer::sequence < Prelexer::number >(start) != 0) {
|
633
|
-
rhs = SASS_MEMORY_NEW(ctx.mem, Textual, rhs->pstate(), Textual::DIMENSION, str->value());
|
634
|
-
rhs->is_delayed(false); rhs = rhs->perform(this);
|
635
|
-
}
|
636
|
-
}
|
637
|
-
}
|
638
|
-
|
639
|
-
|
640
584
|
Expression::Concrete_Type l_type = lhs->concrete_type();
|
641
585
|
Expression::Concrete_Type r_type = rhs->concrete_type();
|
642
586
|
|
@@ -662,16 +606,16 @@ namespace Sass {
|
|
662
606
|
std::string value(str->value());
|
663
607
|
const char* start = value.c_str();
|
664
608
|
if (Prelexer::sequence < Prelexer::dimension, Prelexer::end_of_file >(start) != 0) {
|
665
|
-
lhs = SASS_MEMORY_NEW(ctx.mem, Textual,
|
666
|
-
lhs
|
609
|
+
lhs = SASS_MEMORY_NEW(ctx.mem, Textual, b->pstate(), Textual::DIMENSION, str->value());
|
610
|
+
lhs = lhs->perform(this);
|
667
611
|
}
|
668
612
|
}
|
669
613
|
if (String_Constant* str = dynamic_cast<String_Constant*>(rhs)) {
|
670
614
|
std::string value(str->value());
|
671
615
|
const char* start = value.c_str();
|
672
616
|
if (Prelexer::sequence < Prelexer::number >(start) != 0) {
|
673
|
-
rhs = SASS_MEMORY_NEW(ctx.mem, Textual,
|
674
|
-
rhs
|
617
|
+
rhs = SASS_MEMORY_NEW(ctx.mem, Textual, b->pstate(), Textual::DIMENSION, str->value());
|
618
|
+
rhs = rhs->perform(this);
|
675
619
|
}
|
676
620
|
}
|
677
621
|
}
|
@@ -699,7 +643,7 @@ namespace Sass {
|
|
699
643
|
str += b->separator();
|
700
644
|
if (b->op().ws_after) str += " ";
|
701
645
|
str += v_r->to_string(ctx.c_options);
|
702
|
-
String_Constant* val = SASS_MEMORY_NEW(ctx.mem, String_Constant,
|
646
|
+
String_Constant* val = SASS_MEMORY_NEW(ctx.mem, String_Constant, b->pstate(), str);
|
703
647
|
val->is_interpolant(b->left()->has_interpolant());
|
704
648
|
return val;
|
705
649
|
}
|
@@ -760,6 +704,13 @@ namespace Sass {
|
|
760
704
|
b->is_interpolant();
|
761
705
|
if (op_type == Sass_OP::SUB) interpolant = false;
|
762
706
|
// if (op_type == Sass_OP::DIV) interpolant = true;
|
707
|
+
// check for type violations
|
708
|
+
if (l_type == Expression::MAP) {
|
709
|
+
throw Exception::InvalidValue(*v_l);
|
710
|
+
}
|
711
|
+
if (r_type == Expression::MAP) {
|
712
|
+
throw Exception::InvalidValue(*v_r);
|
713
|
+
}
|
763
714
|
Value* ex = op_strings(ctx.mem, b->op(), *v_l, *v_r, ctx.c_options, &pstate, !interpolant); // pass true to compress
|
764
715
|
if (String_Constant* str = dynamic_cast<String_Constant*>(ex))
|
765
716
|
{
|
@@ -815,7 +766,20 @@ namespace Sass {
|
|
815
766
|
if (operand->concrete_type() == Expression::NULL_VAL && dynamic_cast<Variable*>(u->operand())) {
|
816
767
|
u->operand(SASS_MEMORY_NEW(ctx.mem, String_Quoted, u->pstate(), ""));
|
817
768
|
}
|
818
|
-
|
769
|
+
// Never apply unary opertions on colors @see #2140
|
770
|
+
else if (operand->concrete_type() == Expression::COLOR) {
|
771
|
+
Color* c = dynamic_cast<Color*>(operand);
|
772
|
+
|
773
|
+
// Use the color name if this was eval with one
|
774
|
+
if (c->disp().length() > 0) {
|
775
|
+
operand = SASS_MEMORY_NEW(ctx.mem, String_Constant, operand->pstate(), c->disp());
|
776
|
+
u->operand(operand);
|
777
|
+
}
|
778
|
+
}
|
779
|
+
else {
|
780
|
+
u->operand(operand);
|
781
|
+
}
|
782
|
+
|
819
783
|
String_Constant* result = SASS_MEMORY_NEW(ctx.mem, String_Quoted,
|
820
784
|
u->pstate(),
|
821
785
|
u->inspect());
|
@@ -837,26 +801,12 @@ namespace Sass {
|
|
837
801
|
std::string full_name(name + "[f]");
|
838
802
|
Arguments* args = SASS_MEMORY_NEW(ctx.mem, Arguments, *c->arguments());
|
839
803
|
|
840
|
-
// handle call here if valid arg
|
841
|
-
// otherwise we eval arguments to early
|
842
|
-
if (name == "call" && args->length() > 0) {
|
843
|
-
Expression* redirect = args->at(0)->perform(this);
|
844
|
-
args->erase(args->begin());
|
845
|
-
Function_Call* lit = SASS_MEMORY_NEW(ctx.mem, Function_Call,
|
846
|
-
c->pstate(),
|
847
|
-
unquote(redirect->to_string()),
|
848
|
-
args);
|
849
|
-
return operator()(lit);
|
850
|
-
}
|
851
|
-
|
852
804
|
Env* env = environment();
|
853
805
|
if (!env->has(full_name)) {
|
854
806
|
if (!env->has("*[f]")) {
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
b->reset_whitespace();
|
859
|
-
arg->is_delayed(b->can_delay()); // delay
|
807
|
+
for (Argument* arg : args->elements()) {
|
808
|
+
if (List* ls = dynamic_cast<List*>(arg->value())) {
|
809
|
+
if (ls->size() == 0) error("() isn't a valid CSS value.", c->pstate());
|
860
810
|
}
|
861
811
|
}
|
862
812
|
args = static_cast<Arguments*>(args->perform(this));
|
@@ -878,16 +828,26 @@ namespace Sass {
|
|
878
828
|
}
|
879
829
|
}
|
880
830
|
|
831
|
+
// further delay for calls
|
832
|
+
if (full_name != "call[f]") {
|
833
|
+
args->set_delayed(false); // verified
|
834
|
+
}
|
881
835
|
if (full_name != "if[f]") {
|
882
836
|
args = static_cast<Arguments*>(args->perform(this));
|
883
837
|
}
|
884
|
-
|
885
838
|
Definition* def = static_cast<Definition*>((*env)[full_name]);
|
886
839
|
|
887
840
|
if (def->is_overload_stub()) {
|
888
841
|
std::stringstream ss;
|
889
|
-
|
890
|
-
|
842
|
+
size_t L = args->length();
|
843
|
+
// account for rest arguments
|
844
|
+
if (args->has_rest_argument() && args->length() > 0) {
|
845
|
+
// get the rest arguments list
|
846
|
+
List* rest = dynamic_cast<List*>(args->last()->value());
|
847
|
+
// arguments before rest argument plus rest
|
848
|
+
if (rest) L += rest->length() - 1;
|
849
|
+
}
|
850
|
+
ss << full_name << L;
|
891
851
|
full_name = ss.str();
|
892
852
|
std::string resolved_name(full_name);
|
893
853
|
if (!env->has(resolved_name)) error("overloaded function `" + std::string(c->name()) + "` given wrong number of arguments", c->pstate());
|
@@ -908,8 +868,8 @@ namespace Sass {
|
|
908
868
|
Backtrace here(backtrace(), c->pstate(), ", in function `" + c->name() + "`");
|
909
869
|
exp.backtrace_stack.push_back(&here);
|
910
870
|
// eval the body if user-defined or special, invoke underlying CPP function if native
|
911
|
-
if (body && !Prelexer::re_special_fun(
|
912
|
-
else if (func) { result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace()); }
|
871
|
+
if (body && !Prelexer::re_special_fun(name.c_str())) { result = body->perform(this); }
|
872
|
+
else if (func) { result = func(fn_env, *env, ctx, def->signature(), c->pstate(), backtrace(), exp.selector_stack); }
|
913
873
|
if (!result) error(std::string("Function ") + c->name() + " did not return a value", c->pstate());
|
914
874
|
exp.backtrace_stack.pop_back();
|
915
875
|
}
|
@@ -960,8 +920,7 @@ namespace Sass {
|
|
960
920
|
if (result->pstate().file == std::string::npos)
|
961
921
|
result->pstate(c->pstate());
|
962
922
|
|
963
|
-
result
|
964
|
-
if (!result->is_delayed()) result = result->perform(this);
|
923
|
+
result = result->perform(this);
|
965
924
|
result->is_interpolant(c->is_interpolant());
|
966
925
|
exp.env_stack.pop_back();
|
967
926
|
return result;
|
@@ -990,35 +949,13 @@ namespace Sass {
|
|
990
949
|
value = SASS_MEMORY_NEW(ctx.mem, Number, *static_cast<Number*>(value));
|
991
950
|
static_cast<Number*>(value)->zero(true);
|
992
951
|
}
|
993
|
-
else if (value->concrete_type() == Expression::STRING) {
|
994
|
-
if (auto str = dynamic_cast<String_Quoted*>(value)) {
|
995
|
-
value = SASS_MEMORY_NEW(ctx.mem, String_Quoted, *str);
|
996
|
-
} else if (auto str = dynamic_cast<String_Constant*>(value)) {
|
997
|
-
value = SASS_MEMORY_NEW(ctx.mem, String_Quoted, str->pstate(), str->value());
|
998
|
-
}
|
999
|
-
}
|
1000
|
-
else if (value->concrete_type() == Expression::LIST) {
|
1001
|
-
value = SASS_MEMORY_NEW(ctx.mem, List, *static_cast<List*>(value));
|
1002
|
-
}
|
1003
|
-
else if (value->concrete_type() == Expression::MAP) {
|
1004
|
-
value = SASS_MEMORY_NEW(ctx.mem, Map, *static_cast<Map*>(value));
|
1005
|
-
}
|
1006
|
-
else if (value->concrete_type() == Expression::BOOLEAN) {
|
1007
|
-
value = SASS_MEMORY_NEW(ctx.mem, Boolean, *static_cast<Boolean*>(value));
|
1008
|
-
}
|
1009
|
-
else if (value->concrete_type() == Expression::COLOR) {
|
1010
|
-
value = SASS_MEMORY_NEW(ctx.mem, Color, *static_cast<Color*>(value));
|
1011
|
-
}
|
1012
|
-
else if (value->concrete_type() == Expression::NULL_VAL) {
|
1013
|
-
value = SASS_MEMORY_NEW(ctx.mem, Null, value->pstate());
|
1014
|
-
}
|
1015
|
-
else if (value->concrete_type() == Expression::SELECTOR) {
|
1016
|
-
value = value->perform(this); // ->perform(&listize);
|
1017
|
-
}
|
1018
952
|
|
1019
953
|
value->is_interpolant(v->is_interpolant());
|
1020
|
-
value->is_expanded(false);
|
1021
|
-
|
954
|
+
if (force) value->is_expanded(false);
|
955
|
+
value->set_delayed(false); // verified
|
956
|
+
value = value->perform(this);
|
957
|
+
if(!force) (*env)[name] = value;
|
958
|
+
return value;
|
1022
959
|
}
|
1023
960
|
|
1024
961
|
Expression* Eval::operator()(Textual* t)
|
@@ -1095,6 +1032,11 @@ namespace Sass {
|
|
1095
1032
|
return result;
|
1096
1033
|
}
|
1097
1034
|
|
1035
|
+
Expression* Eval::operator()(Color* c)
|
1036
|
+
{
|
1037
|
+
return c;
|
1038
|
+
}
|
1039
|
+
|
1098
1040
|
Expression* Eval::operator()(Number* n)
|
1099
1041
|
{
|
1100
1042
|
return n;
|
@@ -1153,14 +1095,23 @@ namespace Sass {
|
|
1153
1095
|
bool is_null = dynamic_cast<Null*>(item) != 0; // rl != ""
|
1154
1096
|
if (!is_null) *ll << SASS_MEMORY_NEW(ctx.mem, String_Quoted, item->pstate(), rl);
|
1155
1097
|
}
|
1156
|
-
|
1098
|
+
// Check indicates that we probably should not get a list
|
1099
|
+
// here. Normally single list items are already unwrapped.
|
1100
|
+
if (l->size() > 1) {
|
1101
|
+
// string_to_output would fail "#{'_\a' '_\a'}";
|
1102
|
+
std::string str(ll->to_string(ctx.c_options));
|
1103
|
+
newline_to_space(str); // replace directly
|
1104
|
+
res += str; // append to result string
|
1105
|
+
} else {
|
1106
|
+
res += (ll->to_string(ctx.c_options));
|
1107
|
+
}
|
1157
1108
|
ll->is_interpolant(l->is_interpolant());
|
1158
1109
|
}
|
1159
1110
|
|
1160
1111
|
// Value
|
1161
1112
|
// Textual
|
1162
1113
|
// Function_Call
|
1163
|
-
//
|
1114
|
+
// CommaSequence_Selector
|
1164
1115
|
// String_Quoted
|
1165
1116
|
// String_Constant
|
1166
1117
|
// Parent_Selector
|
@@ -1201,7 +1152,7 @@ namespace Sass {
|
|
1201
1152
|
bool is_quoted = dynamic_cast<String_Quoted*>((*s)[i]) != NULL;
|
1202
1153
|
if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
1203
1154
|
else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
1204
|
-
Expression* ex = (*s)[i]->
|
1155
|
+
Expression* ex = (*s)[i]->perform(this);
|
1205
1156
|
interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
|
1206
1157
|
was_quoted = dynamic_cast<String_Quoted*>((*s)[i]) != NULL;
|
1207
1158
|
was_interpolant = (*s)[i]->is_interpolant();
|
@@ -1211,7 +1162,8 @@ namespace Sass {
|
|
1211
1162
|
if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(ctx.mem, Null, s->pstate());
|
1212
1163
|
return SASS_MEMORY_NEW(ctx.mem, String_Constant, s->pstate(), res);
|
1213
1164
|
}
|
1214
|
-
|
1165
|
+
// string schema seems to have a special unquoting behavior (also handles "nested" quotes)
|
1166
|
+
String_Quoted* str = SASS_MEMORY_NEW(ctx.mem, String_Quoted, s->pstate(), res, 0, false, false, false);
|
1215
1167
|
// if (s->is_interpolant()) str->quote_mark(0);
|
1216
1168
|
// String_Constant* str = SASS_MEMORY_NEW(ctx.mem, String_Constant, s->pstate(), res);
|
1217
1169
|
if (str->quote_mark()) str->quote_mark('*');
|
@@ -1227,6 +1179,7 @@ namespace Sass {
|
|
1227
1179
|
Color* c = SASS_MEMORY_NEW(ctx.mem, Color, *name_to_color(s->value()));
|
1228
1180
|
c->pstate(s->pstate());
|
1229
1181
|
c->disp(s->value());
|
1182
|
+
c->is_delayed(true);
|
1230
1183
|
return c;
|
1231
1184
|
}
|
1232
1185
|
return s;
|
@@ -1343,10 +1296,7 @@ namespace Sass {
|
|
1343
1296
|
Expression* Eval::operator()(Argument* a)
|
1344
1297
|
{
|
1345
1298
|
Expression* val = a->value();
|
1346
|
-
// delay missin function arguments?
|
1347
|
-
val->is_delayed(a->is_delayed());
|
1348
1299
|
val = val->perform(this);
|
1349
|
-
val->is_delayed(false);
|
1350
1300
|
|
1351
1301
|
bool is_rest_argument = a->is_rest_argument();
|
1352
1302
|
bool is_keyword_argument = a->is_keyword_argument();
|
@@ -1606,12 +1556,8 @@ namespace Sass {
|
|
1606
1556
|
if ( (sep == "") /* &&
|
1607
1557
|
(sep != "/" || !rqstr || !rqstr->quote_mark()) */
|
1608
1558
|
) {
|
1609
|
-
|
1610
|
-
|
1611
|
-
if (quote_mark && quote_mark != '*') {
|
1612
|
-
return SASS_MEMORY_NEW(mem, String_Constant, lhs.pstate(), quote_mark + unq + quote_mark);
|
1613
|
-
}
|
1614
|
-
return SASS_MEMORY_NEW(mem, String_Quoted, lhs.pstate(), lstr + sep + rstr);
|
1559
|
+
// create a new string that might be quoted on output (but do not unquote what we pass)
|
1560
|
+
return SASS_MEMORY_NEW(mem, String_Quoted, pstate ? *pstate : lhs.pstate(), lstr + rstr, 0, false, true);
|
1615
1561
|
}
|
1616
1562
|
|
1617
1563
|
if (sep != "" && !delayed) {
|
@@ -1622,10 +1568,9 @@ namespace Sass {
|
|
1622
1568
|
if (op == Sass_OP::SUB || op == Sass_OP::DIV) {
|
1623
1569
|
if (lqstr && lqstr->quote_mark()) lstr = quote(lstr);
|
1624
1570
|
if (rqstr && rqstr->quote_mark()) rstr = quote(rstr);
|
1625
|
-
return SASS_MEMORY_NEW(mem, String_Constant, lhs.pstate(), lstr + sep + rstr);
|
1626
1571
|
}
|
1627
1572
|
|
1628
|
-
return SASS_MEMORY_NEW(mem, String_Constant, lhs.pstate(),
|
1573
|
+
return SASS_MEMORY_NEW(mem, String_Constant, pstate ? *pstate : lhs.pstate(), lstr + sep + rstr);
|
1629
1574
|
}
|
1630
1575
|
|
1631
1576
|
Expression* cval_to_astnode(Memory_Manager& mem, union Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate)
|
@@ -1679,10 +1624,10 @@ namespace Sass {
|
|
1679
1624
|
return e;
|
1680
1625
|
}
|
1681
1626
|
|
1682
|
-
|
1627
|
+
CommaSequence_Selector* Eval::operator()(CommaSequence_Selector* s)
|
1683
1628
|
{
|
1684
|
-
std::vector<
|
1685
|
-
|
1629
|
+
std::vector<CommaSequence_Selector*> rv;
|
1630
|
+
CommaSequence_Selector* sl = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, s->pstate());
|
1686
1631
|
sl->is_optional(s->is_optional());
|
1687
1632
|
sl->media_block(s->media_block());
|
1688
1633
|
sl->is_optional(s->is_optional());
|
@@ -1712,9 +1657,10 @@ namespace Sass {
|
|
1712
1657
|
}
|
1713
1658
|
|
1714
1659
|
|
1715
|
-
|
1660
|
+
CommaSequence_Selector* Eval::operator()(Sequence_Selector* s)
|
1716
1661
|
{
|
1717
|
-
|
1662
|
+
bool implicit_parent = !exp.old_at_root_without_rule;
|
1663
|
+
return s->resolve_parent_refs(ctx, selector(), implicit_parent);
|
1718
1664
|
|
1719
1665
|
}
|
1720
1666
|
|
@@ -1728,21 +1674,21 @@ namespace Sass {
|
|
1728
1674
|
return ss;
|
1729
1675
|
}
|
1730
1676
|
|
1731
|
-
|
1677
|
+
CommaSequence_Selector* Eval::operator()(Selector_Schema* s)
|
1732
1678
|
{
|
1733
1679
|
// the parser will look for a brace to end the selector
|
1734
1680
|
std::string result_str(s->contents()->perform(this)->to_string(ctx.c_options));
|
1735
1681
|
result_str = unquote(Util::rtrim(result_str)) + "\n{";
|
1736
1682
|
Parser p = Parser::from_c_str(result_str.c_str(), ctx, s->pstate());
|
1737
1683
|
p.last_media_block = s->media_block();
|
1738
|
-
|
1684
|
+
CommaSequence_Selector* sl = p.parse_selector_list(exp.block_stack.back()->is_root());
|
1739
1685
|
if (s->has_parent_ref()) sl->remove_parent_selectors();
|
1740
1686
|
return operator()(sl);
|
1741
1687
|
}
|
1742
1688
|
|
1743
1689
|
Expression* Eval::operator()(Parent_Selector* p)
|
1744
1690
|
{
|
1745
|
-
|
1691
|
+
CommaSequence_Selector* pr = selector();
|
1746
1692
|
if (pr) {
|
1747
1693
|
exp.selector_stack.pop_back();
|
1748
1694
|
pr = operator()(pr);
|