Skip to content

Commit

Permalink
Disallow parent selectors in selector-append
Browse files Browse the repository at this point in the history
Now correctly errors on inputs such as this one (see sass#2663):

    div {
      a: selector-append('.menu', 'li', '&');
    }
  • Loading branch information
glebm committed Nov 24, 2018
1 parent 5c2501e commit df25b09
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 14 deletions.
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
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

0 comments on commit df25b09

Please sign in to comment.