Skip to content

Commit ae310a7

Browse files
committed
Fix minor internal issue with varargs
1 parent b95b017 commit ae310a7

File tree

1 file changed

+49
-13
lines changed

1 file changed

+49
-13
lines changed

bind.cpp

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,40 @@ namespace Sass {
4747

4848
// If the current parameter is the rest parameter, process and break the loop
4949
if (p->is_rest_parameter()) {
50+
// The next argument by coincidence provides a rest argument
5051
if (a->is_rest_argument()) {
51-
// rest param and rest arg -- just add one to the other
52-
if (env->has_local(p->name())) {
53-
*static_cast<List*>(env->local_frame()[p->name()])
54-
+= static_cast<List*>(a->value());
52+
// We should always get a list for rest arguments
53+
if (List* rest = dynamic_cast<List*>(a->value())) {
54+
// arg contains a list
55+
List* args = rest;
56+
// make sure it's an arglist
57+
if (rest->is_arglist()) {
58+
// can pass it through as it was
59+
env->local_frame()[p->name()] = args;
60+
}
61+
// create a new list and wrap each item as an argument
62+
// otherwise we will not be able to fetch it again
63+
else {
64+
// create a new list object for wrapped items
65+
List* arglist = new (ctx.mem) List(p->pstate(),
66+
0,
67+
rest->separator(),
68+
true);
69+
// wrap each item from list as an argument
70+
for (Expression* item : rest->elements()) {
71+
(*arglist) << new (ctx.mem) Argument(item->pstate(),
72+
item,
73+
"",
74+
false,
75+
false);
76+
}
77+
// assign new arglist to environment
78+
env->local_frame()[p->name()] = arglist;
79+
}
5580
}
81+
// invalid state
5682
else {
57-
env->local_frame()[p->name()] = a->value();
83+
throw runtime_error("invalid state");
5884
}
5985
} else if (a->is_keyword_argument()) {
6086

@@ -72,27 +98,36 @@ namespace Sass {
7298

7399
} else {
74100

75-
// copy all remaining arguments into the rest parameter, preserving names
101+
// create a new list object for wrapped items
76102
List* arglist = new (ctx.mem) List(p->pstate(),
77103
0,
78104
List::COMMA,
79105
true);
80-
env->local_frame()[p->name()] = arglist;
106+
// consume the next args
81107
while (ia < LA) {
82-
a = (*as)[ia];
108+
// get and post inc
109+
a = (*as)[ia++];
110+
// wrap current argument into new object
111+
(*arglist) << new (ctx.mem) Argument(a->pstate(),
112+
a->value(),
113+
a->name(),
114+
false);
115+
// check if we have rest argument
83116
if (a->is_rest_argument()) {
117+
// preserve the list separator from rest args
84118
if (List* rest = dynamic_cast<List*>(a->value())) {
85119
arglist->separator(rest->separator());
86120
}
121+
// no more arguments
122+
break;
87123
}
88-
(*arglist) << new (ctx.mem) Argument(a->pstate(),
89-
a->value(),
90-
a->name(),
91-
false);
92-
++ia;
93124
}
125+
// assign new arglist to environment
126+
env->local_frame()[p->name()] = arglist;
94127
}
128+
// consumed parameter
95129
++ip;
130+
// no more paramaters
96131
break;
97132
}
98133

@@ -167,6 +202,7 @@ namespace Sass {
167202
env->local_frame()[a->name()] = a->value();
168203
}
169204
}
205+
// EO while ia
170206

171207
// If we make it here, we're out of args but may have leftover params.
172208
// That's only okay if they have default values, or were already bound by

0 commit comments

Comments
 (0)