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

Disallow parent selectors in selector-append #2760

Merged
merged 2 commits into from
Nov 25, 2018
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
5 changes: 4 additions & 1 deletion src/fn_selectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ namespace Sass {
str->quote_mark(0);
}
std::string exp_src = exp->to_string();
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces,
exp->pstate(), pstate.src,
/*allow_parent=*/false);

parsedSelectors.push_back(sel);
}

Expand Down
8 changes: 4 additions & 4 deletions src/fn_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,27 +121,27 @@ namespace Sass {
std::stringstream msg;
msg << argname << ": null is not a valid selector: it must be a string,\n";
msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'";
error(msg.str(), pstate, traces);
error(msg.str(), exp->pstate(), traces);
}
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
str->quote_mark(0);
}
std::string exp_src = exp->to_string(ctx.c_options);
return Parser::parse_selector(exp_src.c_str(), ctx, traces);
return Parser::parse_selector(exp_src.c_str(), ctx, traces, exp->pstate(), pstate.src);
}

Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
Expression_Obj exp = ARG(argname, Expression);
if (exp->concrete_type() == Expression::NULL_VAL) {
std::stringstream msg;
msg << argname << ": null is not a string for `" << function_name(sig) << "'";
error(msg.str(), pstate, traces);
error(msg.str(), exp->pstate(), traces);
}
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
str->quote_mark(0);
}
std::string exp_src = exp->to_string(ctx.c_options);
Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces);
Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces, exp->pstate(), pstate.src);
if (sel_list->length() == 0) return {};
Complex_Selector_Obj first = sel_list->first();
if (!first->tail()) return first->head();
Expand Down
14 changes: 7 additions & 7 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ namespace Sass {
using namespace Constants;
using namespace Prelexer;

Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
{
pstate.offset.column = 0;
pstate.offset.line = 0;
Parser p(ctx, pstate, traces);
Parser p(ctx, pstate, traces, allow_parent);
p.source = source ? source : beg;
p.position = beg ? beg : p.source;
p.end = p.position + strlen(p.position);
Expand All @@ -44,11 +44,11 @@ namespace Sass {
return p;
}

Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
{
pstate.offset.column = 0;
pstate.offset.line = 0;
Parser p(ctx, pstate, traces);
Parser p(ctx, pstate, traces, allow_parent);
p.source = source ? source : beg;
p.position = beg ? beg : p.source;
p.end = end ? end : p.position + strlen(p.position);
Expand All @@ -66,10 +66,9 @@ namespace Sass {
pstate.offset.line = 0;
}

Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
{
Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source);
// ToDo: ruby sass errors on parent references
Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source, allow_parent);
// ToDo: remap the source-map entries somehow
return p.parse_selector_list(false);
}
Expand Down Expand Up @@ -818,6 +817,7 @@ namespace Sass {
// parse parent selector
else if (lex< exactly<'&'> >(false))
{
if (!allow_parent) error("Parent selectors aren't allowed here.");
// this produces a linefeed!?
seq->has_parent_reference(true);
seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
Expand Down
13 changes: 7 additions & 6 deletions src/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,24 @@ namespace Sass {
Backtraces traces;
size_t indentation;
size_t nestings;
bool allow_parent;

Token lexed;

Parser(Context& ctx, const ParserState& pstate, Backtraces traces)
Parser(Context& ctx, const ParserState& pstate, Backtraces traces, bool allow_parent = true)
: ParserState(pstate), ctx(ctx), block_stack(), stack(0), last_media_block(),
source(0), position(0), end(0), before_token(pstate), after_token(pstate),
pstate(pstate), traces(traces), indentation(0), nestings(0)
pstate(pstate), traces(traces), indentation(0), nestings(0), allow_parent(allow_parent)
{
stack.push_back(Scope::Root);
}

// static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
static Parser from_c_str(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
static Parser from_c_str(const char* beg, const char* end, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
static Parser from_token(Token t, Context& ctx, Backtraces, ParserState pstate = ParserState("[TOKEN]"), const char* source = 0);
static Parser from_c_str(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = nullptr, bool allow_parent = true);
static Parser from_c_str(const char* beg, const char* end, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = nullptr, bool allow_parent = true);
static Parser from_token(Token t, Context& ctx, Backtraces, ParserState pstate = ParserState("[TOKEN]"), const char* source = nullptr);
// special static parsers to convert strings into certain selectors
static Selector_List_Obj parse_selector(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[SELECTOR]"), const char* source = 0);
static Selector_List_Obj parse_selector(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[SELECTOR]"), const char* source = nullptr, bool allow_parent = true);

#ifdef __clang__

Expand Down