| Index: Source/core/css/CSSParser.h
|
| diff --git a/Source/core/css/CSSParser.h b/Source/core/css/CSSParser.h
|
| index a28c3f6250f51e649bd0fc39d6955bbfe76675af..99d1d108773dc57be0c382759ffb0f8a7bc26342 100644
|
| --- a/Source/core/css/CSSParser.h
|
| +++ b/Source/core/css/CSSParser.h
|
| @@ -3,6 +3,7 @@
|
| * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
|
| * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
|
| * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
|
| + * Copyright (C) 2013 Opera Software ASA. All rights reserved.
|
| *
|
| * This library is free software; you can redistribute it and/or
|
| * modify it under the terms of the GNU Library General Public
|
| @@ -67,6 +68,68 @@ class WebKitCSSArrayFunctionValue;
|
| class WebKitCSSMixFunctionValue;
|
| class WebKitCSSShaderValue;
|
|
|
| +// Keep track of matching parentheses using a stack of opening brackets.
|
| +// Needed for correct error recovery.
|
| +class BracketStack {
|
| +public:
|
| + inline void push(int bracket) { m_stack.append(bracket); }
|
| +
|
| + inline void pop(int bracket)
|
| + {
|
| + if (m_stack.size() > 0) {
|
| + switch (bracket) {
|
| + case '}':
|
| + if (m_stack.last() == '{')
|
| + m_stack.removeLast();
|
| + break;
|
| + case ')':
|
| + if (m_stack.last() == '(')
|
| + m_stack.removeLast();
|
| + break;
|
| + case ']':
|
| + if (m_stack.last() == '[')
|
| + m_stack.removeLast();
|
| + break;
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + inline int pop()
|
| + {
|
| + if (!m_stack.size())
|
| + return 0;
|
| +
|
| + int ret = 0;
|
| + switch (top()) {
|
| + case '{':
|
| + ret = '}';
|
| + break;
|
| + case '(':
|
| + ret = ')';
|
| + break;
|
| + case '[':
|
| + ret = ']';
|
| + break;
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| + break;
|
| + }
|
| + m_stack.removeLast();
|
| + return ret;
|
| + }
|
| +
|
| + int top() const { return m_stack.last(); }
|
| +
|
| + inline size_t level() const { return m_stack.size(); }
|
| +
|
| +private:
|
| + // Make room for 16 levels deep nesting of parentheses initially.
|
| + Vector<int, 16> m_stack;
|
| +};
|
| +
|
| class CSSParser {
|
| friend inline int cssyylex(void*, CSSParser*);
|
|
|
| @@ -405,6 +468,12 @@ public:
|
| PassRefPtr<CSSPrimitiveValue> createPrimitiveStringValue(CSSParserValue*);
|
| PassRefPtr<CSSPrimitiveValue> createPrimitiveVariableNameValue(CSSParserValue*);
|
|
|
| + // Store block level.
|
| + void markMediaListStart();
|
| +
|
| + // Error token reached while parsing a media_query, synchronized at current token.
|
| + MediaQuery* recoverMediaQuery();
|
| +
|
| static KURL completeURL(const CSSParserContext&, const String& url);
|
|
|
| Location currentLocation();
|
| @@ -553,6 +622,18 @@ private:
|
| bool m_inViewport;
|
| #endif
|
|
|
| + enum ReEmissionState {
|
| + DontEmit,
|
| + ReEmit,
|
| + DidReEmit
|
| + };
|
| +
|
| + inline void markCurrentTokenForReEmission();
|
| +
|
| + ReEmissionState m_reEmissionState;
|
| + BracketStack m_brackets;
|
| + size_t m_storedBlockLevel;
|
| +
|
| int (CSSParser::*m_lexFunc)(void*);
|
|
|
| Vector<RefPtr<StyleRuleBase> > m_parsedRules;
|
| @@ -705,6 +786,18 @@ inline int cssyylex(void* yylval, CSSParser* parser)
|
| return parser->lex(yylval);
|
| }
|
|
|
| +inline void CSSParser::markCurrentTokenForReEmission()
|
| +{
|
| + // Sanity check.
|
| + // Re-emitting a token which has just been re-emitted may cause an infinite
|
| + // loop. Also, marking a token for re-emit twice also doesn't make sense.
|
| + ASSERT(m_reEmissionState == DontEmit);
|
| +
|
| + // Make sure we don't enter an infinite loop if the assert triggers.
|
| + if (m_reEmissionState == DontEmit)
|
| + m_reEmissionState = ReEmit;
|
| +}
|
| +
|
| } // namespace WebCore
|
|
|
| #endif // CSSParser_h
|
|
|