Add code to allow the CSS parser to report errors. This code is not enabled by default in any builds, but it could be useful for chrome authors to catch CSS errors. We may want to turn it on in debug builds at some point, but it needs some work first. r=attinasi

This commit is contained in:
dbaron%fas.harvard.edu 2000-09-06 02:27:46 +00:00
Родитель 41a82e22b2
Коммит c9392da530
9 изменённых файлов: 693 добавлений и 9 удалений

Просмотреть файл

@ -318,6 +318,34 @@ NS_NewCSSParser(nsICSSParser** aInstancePtrResult)
return it->QueryInterface(kICSSParserIID, (void **) aInstancePtrResult);
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define REPORT_UNEXPECTED_EOF() mScanner->ReportError(NS_LITERAL_STRING("Unexpected end of file"))
#define REPORT_UNEXPECTED_TOKEN() ReportUnexpectedToken(mScanner,mToken,nsnull)
#define REPORT_UNEXPECTED_TOKEN1(_reas) ReportUnexpectedToken(mScanner,mToken,_reas)
static void ReportUnexpectedToken(nsCSSScanner *sc,
nsCSSToken& tok,
char* reason)
{
nsString err;
if (!reason) {
err.AssignWithConversion("Unexpected token ");
} else {
err.AssignWithConversion(reason);
}
tok.AppendToString(err);
sc->ReportError(err.GetUnicode());
}
#else
#define REPORT_UNEXPECTED_EOF();
#define REPORT_UNEXPECTED_TOKEN();
#define REPORT_UNEXPECTED_TOKEN1(_reas);
#endif
CSSParserImpl::CSSParserImpl()
: mToken(),
mHavePushBack(PR_FALSE),
@ -328,10 +356,10 @@ CSSParserImpl::CSSParserImpl()
mChildLoader(nsnull),
mSection(eCSSSection_Charset),
mNavQuirkMode(PR_FALSE),
mParsingCompoundProperty(PR_FALSE),
mCaseSensitive(PR_FALSE),
mNameSpace(nsnull),
mGroupStack(nsnull)
mGroupStack(nsnull),
mParsingCompoundProperty(PR_FALSE)
{
NS_INIT_REFCNT();
@ -423,6 +451,9 @@ CSSParserImpl::InitScanner(nsIUnicharInputStream* aInput, nsIURI* aURI)
return NS_ERROR_OUT_OF_MEMORY;
}
mScanner->Init(aInput);
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->InitErrorReporting(aURI);
#endif
NS_IF_RELEASE(mURL);
mURL = aURI;
NS_IF_ADDREF(mURL);
@ -685,6 +716,7 @@ PRBool CSSParserImpl::ExpectEndProperty(PRInt32& aErrorCode, PRBool aSkipWS)
UngetToken();
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -692,6 +724,7 @@ PRBool CSSParserImpl::ExpectEndProperty(PRInt32& aErrorCode, PRBool aSkipWS)
nsString* CSSParserImpl::NextIdent(PRInt32& aErrorCode)
{
// XXX Error reporting?
if (!GetToken(aErrorCode, PR_TRUE)) {
return nsnull;
}
@ -706,6 +739,7 @@ PRBool CSSParserImpl::SkipAtRule(PRInt32& aErrorCode)
{
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Symbol == mToken.mType) {
@ -767,6 +801,12 @@ PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode)
return PR_TRUE;
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
nsString err;
err.AssignWithConversion("Unrecognized at-rule ");
mToken.AppendToString(err);
mScanner->ReportError(err.GetUnicode());
#endif
// Skip over unsupported at rule, don't advance section
return SkipAtRule(aErrorCode);
@ -785,6 +825,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
PRBool expectIdent = PR_TRUE;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol == mToken.mType) {
@ -793,9 +834,11 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
UngetToken();
return PR_TRUE;
} else if (',' != symbol) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
} else if (expectIdent) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
@ -819,11 +862,13 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
expectIdent = PR_FALSE;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
@ -839,6 +884,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
nsAutoString url;
@ -871,6 +917,7 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode)
}
}
}
REPORT_UNEXPECTED_TOKEN();
// don't advance section, simply ignore invalid @import
return PR_FALSE;
}
@ -911,7 +958,7 @@ PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpe
return result;
}
// Parse a CSS2 media rule: "@media medium [, mdeium] { ... }"
// Parse a CSS2 media rule: "@media medium [, medium] { ... }"
PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
{
nsAutoString mediaStr;
@ -933,6 +980,7 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
for (;;) {
// Get next non-whitespace token
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (mToken.IsSymbol('}')) { // done!
@ -974,6 +1022,7 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
@ -983,6 +1032,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
if (eCSSToken_Ident == mToken.mType) {
prefix = mToken.mIdent;
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
}
@ -1010,6 +1060,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
}
}
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
@ -1078,6 +1129,9 @@ CSSParserImpl::SkipDeclaration(PRInt32& aErrorCode, PRBool aCheckForBraces)
nsCSSToken* tk = &mToken;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
REPORT_UNEXPECTED_EOF();
}
return PR_FALSE;
}
if (eCSSToken_Symbol == tk->mType) {
@ -1108,6 +1162,7 @@ void CSSParserImpl::SkipRuleSet(PRInt32& aErrorCode)
nsCSSToken* tk = &mToken;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol == tk->mType) {
@ -1125,6 +1180,8 @@ void CSSParserImpl::SkipRuleSet(PRInt32& aErrorCode)
}
}
// XXX Make sure report errors before calling Skip*
PRBool CSSParserImpl::PushGroup(nsICSSGroupRule* aRule)
{
if (! mGroupStack) {
@ -1225,6 +1282,9 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
SelectorList* list = nsnull;
if (! ParseSelectorGroup(aErrorCode, list)) {
// must have at least one selector group
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Selector expected"));
#endif
aListHead = nsnull;
return PR_FALSE;
}
@ -1235,6 +1295,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
nsCSSToken* tk = &mToken;
for (;;) {
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol != tk->mType) {
@ -1259,6 +1320,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
break;
}
}
REPORT_UNEXPECTED_TOKEN();
delete aListHead;
aListHead = nsnull;
@ -1381,11 +1443,18 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
weight += selector.CalcWeight();
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
if (!list)
mScanner->ReportError(NS_LITERAL_STRING("Selector expected"));
#endif
if (PRUnichar(0) != combinator) { // no dangling combinators
if (list) {
delete list;
}
list = nsnull;
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Dangling combinator"));
#endif
}
aList = list;
if (nsnull != list) {
@ -1416,6 +1485,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
nsAutoString buffer;
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (mToken.IsSymbol('*')) { // universal element selector, or universal namespace
@ -1426,6 +1496,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.SetNameSpace(kNameSpaceID_Unknown); // namespace wildcard
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1444,6 +1515,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1488,11 +1560,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_IF_RELEASE(prefix);
} // else, no delcared namespaces
if (kNameSpaceID_Unknown == nameSpaceID) { // unknown prefix, dump it
REPORT_UNEXPECTED_TOKEN1("Unknown namespace prefix ");
return PR_FALSE;
}
aSelector.SetNameSpace(nameSpaceID);
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1511,6 +1585,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1547,6 +1622,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// get mandatory tag
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1565,6 +1641,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1581,6 +1658,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.SetID(mToken.mIdent);
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1588,9 +1666,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol('.')) { // .class
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Ident != mToken.mType) { // malformed selector (XXX what about leading digits?)
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1601,9 +1681,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol(':')) { // :pseudo
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Ident != mToken.mType) { // malformed selector
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1632,11 +1714,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken();
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else { // multiple pseudo elements, not legal
REPORT_UNEXPECTED_TOKEN1("Extra pseudo-element ");
UngetToken();
NS_RELEASE(pseudo);
return PR_FALSE;
@ -1646,6 +1730,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol('[')) { // attribute
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1657,6 +1742,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1664,16 +1750,19 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
}
else if (mToken.IsSymbol('|')) { // NO namespace
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1681,6 +1770,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1703,9 +1793,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_IF_RELEASE(prefix);
} // else, no delcared namespaces
if (kNameSpaceID_Unknown == nameSpaceID) { // unknown prefix, dump it
REPORT_UNEXPECTED_TOKEN1("Unknown namespace prefix ");
return PR_FALSE;
}
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1713,12 +1805,14 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
}
else { // malformed
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1727,6 +1821,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr.ToLowerCase();
}
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Symbol == mToken.mType) ||
@ -1749,17 +1844,20 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
func = NS_ATTR_FUNC_EQUALS;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken(); // bad function
return PR_FALSE;
}
if (NS_ATTR_FUNC_SET != func) { // get value
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
mToken.AppendToString(aSource);
nsAutoString value(mToken.mIdent);
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (mToken.IsSymbol(']')) {
@ -1768,17 +1866,20 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.AddAttribute(nameSpaceID, attr, func, value, mCaseSensitive);
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken(); // bad dog, no biscut!
return PR_FALSE;
}
@ -1801,6 +1902,7 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
{
if (aCheckForBraces) {
if (!ExpectSymbol(aErrorCode, '{', PR_TRUE)) {
REPORT_UNEXPECTED_TOKEN();
return nsnull;
}
}
@ -1823,6 +1925,9 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
break;
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Declaration dropped"));
#endif
// Since the skipped declaration didn't end the block we parse
// the next declaration.
}
@ -1838,9 +1943,11 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
nsCSSToken* tk = &mToken;
nscolor rgba;
switch (tk->mType) {
@ -1880,6 +1987,7 @@ PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
aValue.SetColorValue(rgba);
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE; // already pushed back
}
break;
@ -1933,6 +2041,7 @@ PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
}
// It's not a color
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1942,6 +2051,7 @@ PRBool CSSParserImpl::ParseColorComponent(PRInt32& aErrorCode,
char aStop)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
float value;
@ -1954,6 +2064,7 @@ PRBool CSSParserImpl::ParseColorComponent(PRInt32& aErrorCode,
value = tk->mNumber * 255.0f;
break;
default:
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1979,12 +2090,16 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
nsAutoString propertyName;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
REPORT_UNEXPECTED_EOF();
}
return PR_FALSE;
}
if (eCSSToken_Ident == tk->mType) {
propertyName = tk->mIdent;
// grab the ident before the ExpectSymbol trashes the token
if (!ExpectSymbol(aErrorCode, ':', PR_TRUE)) {
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
break;
@ -2002,9 +2117,20 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
// Map property name to it's ID and then parse the property
nsCSSProperty propID = nsCSSProps::LookupProperty(propertyName);
if (eCSSProperty_UNKNOWN == propID) { // unknown property
#ifdef CSS_REPORT_PARSE_ERRORS
nsString err(NS_LITERAL_STRING("Unknown property "));
err.Append(propertyName);
mScanner->ReportError(err.GetUnicode());
#endif
return PR_FALSE;
}
if (! ParseProperty(aErrorCode, aDeclaration, propID, aChangeHint)) {
#ifdef CSS_REPORT_PARSE_ERRORS
// XXX Much better to put stuff in the value parsers instead...
nsString err(NS_LITERAL_STRING("Error parsing value for property "));
err.Append(propertyName);
mScanner->ReportError(err.GetUnicode());
#endif
return PR_FALSE;
}
@ -2013,6 +2139,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
// Premature eof is not ok when proper termination is mandated
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
return PR_TRUE;
@ -2023,10 +2150,12 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
// Look for important ident
if (!GetToken(aErrorCode, PR_TRUE)) {
// Premature eof is not ok
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Ident != tk->mType) ||
!tk->mIdent.EqualsIgnoreCase("important")) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -2054,6 +2183,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
// Premature eof is not ok
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
return PR_TRUE;
@ -2065,6 +2195,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!aCheckForBraces) {
// If we didn't hit eof and we didn't see a semicolon then the
// declaration is not properly terminated.
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
if ('}' == tk->mSymbol) {
@ -2072,6 +2203,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
return PR_TRUE;
}
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
@ -2802,6 +2934,9 @@ PRBool CSSParserImpl::ParseProperty(PRInt32& aErrorCode,
case eCSSProperty_text_shadow_x:
case eCSSProperty_text_shadow_y:
// The user can't use these
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Attempt to use inaccessible property"));
#endif
return PR_FALSE;
default: // must be single property
@ -2812,7 +2947,9 @@ PRBool CSSParserImpl::ParseProperty(PRInt32& aErrorCode,
aErrorCode = AppendValue(aDeclaration, aPropID, value, aChangeHint);
return PR_TRUE;
}
// XXX Report errors?
}
// XXX Report errors?
}
}
return PR_FALSE;

Просмотреть файл

@ -29,6 +29,15 @@
static char* kNullPointer = "null pointer";
#endif
#ifdef CSS_REPORT_PARSE_ERRORS
#include "nsCOMPtr.h"
#include "nsIURI.h"
#include "nsIConsoleService.h"
#include "nsIScriptError.h"
#include "nsIServiceManager.h"
#include "nsComponentManagerUtils.h"
#endif
// Don't bother collecting whitespace characters in token's mIdent buffer
#undef COLLECT_WHITESPACE
@ -164,6 +173,9 @@ nsCSSScanner::nsCSSScanner()
mPushback = mLocalPushback;
mPushbackCount = 0;
mPushbackSize = 4;
#ifdef CSS_REPORT_PARSE_ERRORS
mLastRead = 0;
#endif
}
nsCSSScanner::~nsCSSScanner()
@ -187,11 +199,59 @@ void nsCSSScanner::Init(nsIUnicharInputStream* aInput)
NS_IF_ADDREF(aInput);
}
#ifdef CSS_REPORT_PARSE_ERRORS
void nsCSSScanner::InitErrorReporting(nsIURI* aURI)
{
if (aURI) {
aURI->GetSpec(getter_Copies(mFileName));
} else {
mFileName = "from DOM";
}
mLineNumber = 1;
mColNumber = 0;
}
void nsCSSScanner::ReportError(const PRUnichar* aError)
{
printf("CSS Error (%s :%lu.%lu): %s.\n",
mFileName.get(),
mLineNumber,
mColNumber,
NS_ConvertUCS2toUTF8(aError).GetBuffer());
// Log it to the JavaScript console
nsCOMPtr<nsIConsoleService> consoleService
(do_GetService("mozilla.consoleservice.1"));
nsCOMPtr<nsIScriptError> errorObject
(do_CreateInstance("mozilla.scripterror.1"));
if (consoleService && errorObject) {
nsresult rv;
rv = errorObject->Init(aError,
NS_ConvertASCIItoUCS2(mFileName.get()).GetUnicode(),
NS_LITERAL_STRING(""),
mLineNumber,
mColNumber,
0,
"CSS Parser");
if (NS_SUCCEEDED(rv))
consoleService->LogMessage(errorObject);
}
}
#endif // CSS_REPORT_PARSE_ERRORS
void nsCSSScanner::Close()
{
NS_IF_RELEASE(mInput);
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define TAB_STOP_WIDTH 8
#endif
// Returns -1 on error or eof
PRInt32 nsCSSScanner::Read(PRInt32& aErrorCode)
{
@ -211,6 +271,17 @@ PRInt32 nsCSSScanner::Read(PRInt32& aErrorCode)
}
}
rv = PRInt32(mBuffer[mOffset++]);
#ifdef CSS_REPORT_PARSE_ERRORS
if (((rv == '\n') && (mLastRead != '\r')) || (rv == '\r')) {
mLineNumber++;
mColNumber = 0;
} else if (rv == '\t') {
mColNumber = ((mColNumber - 1 + TAB_STOP_WIDTH) / TAB_STOP_WIDTH)
* TAB_STOP_WIDTH;
} else if (rv != '\n') {
mColNumber++;
}
#endif
}
mLastRead = rv;
//printf("Read => %x\n", rv);

Просмотреть файл

@ -25,6 +25,14 @@
#include "nsString.h"
class nsIUnicharInputStream;
// for testing
//#define CSS_REPORT_PARSE_ERRORS
#ifdef CSS_REPORT_PARSE_ERRORS
#include "nsXPIDLString.h"
class nsIURI;
#endif
// Token types
enum nsCSSTokenType {
// A css identifier (e.g. foo)
@ -97,6 +105,11 @@ class nsCSSScanner {
// Init the scanner.
void Init(nsIUnicharInputStream* aInput);
#ifdef CSS_REPORT_PARSE_ERRORS
void InitErrorReporting(nsIURI* aURI);
void ReportError(const PRUnichar* aError);
#endif
// Get the next token. Return nsfalse on EOF or ERROR. aTokenResult
// is filled in with the data for the token.
PRBool Next(PRInt32& aErrorCode, nsCSSToken& aTokenResult);
@ -139,6 +152,13 @@ protected:
PRInt32 mPushbackSize;
PRInt32 mLastRead;
PRUnichar mLocalPushback[4];
#ifdef CSS_REPORT_PARSE_ERRORS
nsXPIDLCString mFileName;
PRUint32 mLineNumber;
PRUint32 mColNumber;
#endif
};
#endif /* nsCSSScanner_h___ */

Просмотреть файл

@ -318,6 +318,34 @@ NS_NewCSSParser(nsICSSParser** aInstancePtrResult)
return it->QueryInterface(kICSSParserIID, (void **) aInstancePtrResult);
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define REPORT_UNEXPECTED_EOF() mScanner->ReportError(NS_LITERAL_STRING("Unexpected end of file"))
#define REPORT_UNEXPECTED_TOKEN() ReportUnexpectedToken(mScanner,mToken,nsnull)
#define REPORT_UNEXPECTED_TOKEN1(_reas) ReportUnexpectedToken(mScanner,mToken,_reas)
static void ReportUnexpectedToken(nsCSSScanner *sc,
nsCSSToken& tok,
char* reason)
{
nsString err;
if (!reason) {
err.AssignWithConversion("Unexpected token ");
} else {
err.AssignWithConversion(reason);
}
tok.AppendToString(err);
sc->ReportError(err.GetUnicode());
}
#else
#define REPORT_UNEXPECTED_EOF();
#define REPORT_UNEXPECTED_TOKEN();
#define REPORT_UNEXPECTED_TOKEN1(_reas);
#endif
CSSParserImpl::CSSParserImpl()
: mToken(),
mHavePushBack(PR_FALSE),
@ -328,10 +356,10 @@ CSSParserImpl::CSSParserImpl()
mChildLoader(nsnull),
mSection(eCSSSection_Charset),
mNavQuirkMode(PR_FALSE),
mParsingCompoundProperty(PR_FALSE),
mCaseSensitive(PR_FALSE),
mNameSpace(nsnull),
mGroupStack(nsnull)
mGroupStack(nsnull),
mParsingCompoundProperty(PR_FALSE)
{
NS_INIT_REFCNT();
@ -423,6 +451,9 @@ CSSParserImpl::InitScanner(nsIUnicharInputStream* aInput, nsIURI* aURI)
return NS_ERROR_OUT_OF_MEMORY;
}
mScanner->Init(aInput);
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->InitErrorReporting(aURI);
#endif
NS_IF_RELEASE(mURL);
mURL = aURI;
NS_IF_ADDREF(mURL);
@ -685,6 +716,7 @@ PRBool CSSParserImpl::ExpectEndProperty(PRInt32& aErrorCode, PRBool aSkipWS)
UngetToken();
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -692,6 +724,7 @@ PRBool CSSParserImpl::ExpectEndProperty(PRInt32& aErrorCode, PRBool aSkipWS)
nsString* CSSParserImpl::NextIdent(PRInt32& aErrorCode)
{
// XXX Error reporting?
if (!GetToken(aErrorCode, PR_TRUE)) {
return nsnull;
}
@ -706,6 +739,7 @@ PRBool CSSParserImpl::SkipAtRule(PRInt32& aErrorCode)
{
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Symbol == mToken.mType) {
@ -767,6 +801,12 @@ PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode)
return PR_TRUE;
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
nsString err;
err.AssignWithConversion("Unrecognized at-rule ");
mToken.AppendToString(err);
mScanner->ReportError(err.GetUnicode());
#endif
// Skip over unsupported at rule, don't advance section
return SkipAtRule(aErrorCode);
@ -785,6 +825,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
PRBool expectIdent = PR_TRUE;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol == mToken.mType) {
@ -793,9 +834,11 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
UngetToken();
return PR_TRUE;
} else if (',' != symbol) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
} else if (expectIdent) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
@ -819,11 +862,13 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
expectIdent = PR_FALSE;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
@ -839,6 +884,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
nsAutoString url;
@ -871,6 +917,7 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode)
}
}
}
REPORT_UNEXPECTED_TOKEN();
// don't advance section, simply ignore invalid @import
return PR_FALSE;
}
@ -911,7 +958,7 @@ PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpe
return result;
}
// Parse a CSS2 media rule: "@media medium [, mdeium] { ... }"
// Parse a CSS2 media rule: "@media medium [, medium] { ... }"
PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
{
nsAutoString mediaStr;
@ -933,6 +980,7 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
for (;;) {
// Get next non-whitespace token
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (mToken.IsSymbol('}')) { // done!
@ -974,6 +1022,7 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
@ -983,6 +1032,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
if (eCSSToken_Ident == mToken.mType) {
prefix = mToken.mIdent;
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
}
@ -1010,6 +1060,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
}
}
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
@ -1078,6 +1129,9 @@ CSSParserImpl::SkipDeclaration(PRInt32& aErrorCode, PRBool aCheckForBraces)
nsCSSToken* tk = &mToken;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
REPORT_UNEXPECTED_EOF();
}
return PR_FALSE;
}
if (eCSSToken_Symbol == tk->mType) {
@ -1108,6 +1162,7 @@ void CSSParserImpl::SkipRuleSet(PRInt32& aErrorCode)
nsCSSToken* tk = &mToken;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol == tk->mType) {
@ -1125,6 +1180,8 @@ void CSSParserImpl::SkipRuleSet(PRInt32& aErrorCode)
}
}
// XXX Make sure report errors before calling Skip*
PRBool CSSParserImpl::PushGroup(nsICSSGroupRule* aRule)
{
if (! mGroupStack) {
@ -1225,6 +1282,9 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
SelectorList* list = nsnull;
if (! ParseSelectorGroup(aErrorCode, list)) {
// must have at least one selector group
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Selector expected"));
#endif
aListHead = nsnull;
return PR_FALSE;
}
@ -1235,6 +1295,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
nsCSSToken* tk = &mToken;
for (;;) {
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol != tk->mType) {
@ -1259,6 +1320,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
break;
}
}
REPORT_UNEXPECTED_TOKEN();
delete aListHead;
aListHead = nsnull;
@ -1381,11 +1443,18 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
weight += selector.CalcWeight();
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
if (!list)
mScanner->ReportError(NS_LITERAL_STRING("Selector expected"));
#endif
if (PRUnichar(0) != combinator) { // no dangling combinators
if (list) {
delete list;
}
list = nsnull;
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Dangling combinator"));
#endif
}
aList = list;
if (nsnull != list) {
@ -1416,6 +1485,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
nsAutoString buffer;
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (mToken.IsSymbol('*')) { // universal element selector, or universal namespace
@ -1426,6 +1496,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.SetNameSpace(kNameSpaceID_Unknown); // namespace wildcard
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1444,6 +1515,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1488,11 +1560,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_IF_RELEASE(prefix);
} // else, no delcared namespaces
if (kNameSpaceID_Unknown == nameSpaceID) { // unknown prefix, dump it
REPORT_UNEXPECTED_TOKEN1("Unknown namespace prefix ");
return PR_FALSE;
}
aSelector.SetNameSpace(nameSpaceID);
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1511,6 +1585,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1547,6 +1622,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// get mandatory tag
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1565,6 +1641,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1581,6 +1658,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.SetID(mToken.mIdent);
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1588,9 +1666,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol('.')) { // .class
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Ident != mToken.mType) { // malformed selector (XXX what about leading digits?)
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1601,9 +1681,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol(':')) { // :pseudo
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Ident != mToken.mType) { // malformed selector
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1632,11 +1714,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken();
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else { // multiple pseudo elements, not legal
REPORT_UNEXPECTED_TOKEN1("Extra pseudo-element ");
UngetToken();
NS_RELEASE(pseudo);
return PR_FALSE;
@ -1646,6 +1730,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol('[')) { // attribute
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1657,6 +1742,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1664,16 +1750,19 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
}
else if (mToken.IsSymbol('|')) { // NO namespace
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1681,6 +1770,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1703,9 +1793,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_IF_RELEASE(prefix);
} // else, no delcared namespaces
if (kNameSpaceID_Unknown == nameSpaceID) { // unknown prefix, dump it
REPORT_UNEXPECTED_TOKEN1("Unknown namespace prefix ");
return PR_FALSE;
}
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1713,12 +1805,14 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
}
else { // malformed
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1727,6 +1821,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr.ToLowerCase();
}
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Symbol == mToken.mType) ||
@ -1749,17 +1844,20 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
func = NS_ATTR_FUNC_EQUALS;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken(); // bad function
return PR_FALSE;
}
if (NS_ATTR_FUNC_SET != func) { // get value
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
mToken.AppendToString(aSource);
nsAutoString value(mToken.mIdent);
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (mToken.IsSymbol(']')) {
@ -1768,17 +1866,20 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.AddAttribute(nameSpaceID, attr, func, value, mCaseSensitive);
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken(); // bad dog, no biscut!
return PR_FALSE;
}
@ -1801,6 +1902,7 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
{
if (aCheckForBraces) {
if (!ExpectSymbol(aErrorCode, '{', PR_TRUE)) {
REPORT_UNEXPECTED_TOKEN();
return nsnull;
}
}
@ -1823,6 +1925,9 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
break;
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Declaration dropped"));
#endif
// Since the skipped declaration didn't end the block we parse
// the next declaration.
}
@ -1838,9 +1943,11 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
nsCSSToken* tk = &mToken;
nscolor rgba;
switch (tk->mType) {
@ -1880,6 +1987,7 @@ PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
aValue.SetColorValue(rgba);
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE; // already pushed back
}
break;
@ -1933,6 +2041,7 @@ PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
}
// It's not a color
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1942,6 +2051,7 @@ PRBool CSSParserImpl::ParseColorComponent(PRInt32& aErrorCode,
char aStop)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
float value;
@ -1954,6 +2064,7 @@ PRBool CSSParserImpl::ParseColorComponent(PRInt32& aErrorCode,
value = tk->mNumber * 255.0f;
break;
default:
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1979,12 +2090,16 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
nsAutoString propertyName;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
REPORT_UNEXPECTED_EOF();
}
return PR_FALSE;
}
if (eCSSToken_Ident == tk->mType) {
propertyName = tk->mIdent;
// grab the ident before the ExpectSymbol trashes the token
if (!ExpectSymbol(aErrorCode, ':', PR_TRUE)) {
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
break;
@ -2002,9 +2117,20 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
// Map property name to it's ID and then parse the property
nsCSSProperty propID = nsCSSProps::LookupProperty(propertyName);
if (eCSSProperty_UNKNOWN == propID) { // unknown property
#ifdef CSS_REPORT_PARSE_ERRORS
nsString err(NS_LITERAL_STRING("Unknown property "));
err.Append(propertyName);
mScanner->ReportError(err.GetUnicode());
#endif
return PR_FALSE;
}
if (! ParseProperty(aErrorCode, aDeclaration, propID, aChangeHint)) {
#ifdef CSS_REPORT_PARSE_ERRORS
// XXX Much better to put stuff in the value parsers instead...
nsString err(NS_LITERAL_STRING("Error parsing value for property "));
err.Append(propertyName);
mScanner->ReportError(err.GetUnicode());
#endif
return PR_FALSE;
}
@ -2013,6 +2139,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
// Premature eof is not ok when proper termination is mandated
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
return PR_TRUE;
@ -2023,10 +2150,12 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
// Look for important ident
if (!GetToken(aErrorCode, PR_TRUE)) {
// Premature eof is not ok
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Ident != tk->mType) ||
!tk->mIdent.EqualsIgnoreCase("important")) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -2054,6 +2183,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
// Premature eof is not ok
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
return PR_TRUE;
@ -2065,6 +2195,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!aCheckForBraces) {
// If we didn't hit eof and we didn't see a semicolon then the
// declaration is not properly terminated.
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
if ('}' == tk->mSymbol) {
@ -2072,6 +2203,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
return PR_TRUE;
}
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
@ -2802,6 +2934,9 @@ PRBool CSSParserImpl::ParseProperty(PRInt32& aErrorCode,
case eCSSProperty_text_shadow_x:
case eCSSProperty_text_shadow_y:
// The user can't use these
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Attempt to use inaccessible property"));
#endif
return PR_FALSE;
default: // must be single property
@ -2812,7 +2947,9 @@ PRBool CSSParserImpl::ParseProperty(PRInt32& aErrorCode,
aErrorCode = AppendValue(aDeclaration, aPropID, value, aChangeHint);
return PR_TRUE;
}
// XXX Report errors?
}
// XXX Report errors?
}
}
return PR_FALSE;

Просмотреть файл

@ -29,6 +29,15 @@
static char* kNullPointer = "null pointer";
#endif
#ifdef CSS_REPORT_PARSE_ERRORS
#include "nsCOMPtr.h"
#include "nsIURI.h"
#include "nsIConsoleService.h"
#include "nsIScriptError.h"
#include "nsIServiceManager.h"
#include "nsComponentManagerUtils.h"
#endif
// Don't bother collecting whitespace characters in token's mIdent buffer
#undef COLLECT_WHITESPACE
@ -164,6 +173,9 @@ nsCSSScanner::nsCSSScanner()
mPushback = mLocalPushback;
mPushbackCount = 0;
mPushbackSize = 4;
#ifdef CSS_REPORT_PARSE_ERRORS
mLastRead = 0;
#endif
}
nsCSSScanner::~nsCSSScanner()
@ -187,11 +199,59 @@ void nsCSSScanner::Init(nsIUnicharInputStream* aInput)
NS_IF_ADDREF(aInput);
}
#ifdef CSS_REPORT_PARSE_ERRORS
void nsCSSScanner::InitErrorReporting(nsIURI* aURI)
{
if (aURI) {
aURI->GetSpec(getter_Copies(mFileName));
} else {
mFileName = "from DOM";
}
mLineNumber = 1;
mColNumber = 0;
}
void nsCSSScanner::ReportError(const PRUnichar* aError)
{
printf("CSS Error (%s :%lu.%lu): %s.\n",
mFileName.get(),
mLineNumber,
mColNumber,
NS_ConvertUCS2toUTF8(aError).GetBuffer());
// Log it to the JavaScript console
nsCOMPtr<nsIConsoleService> consoleService
(do_GetService("mozilla.consoleservice.1"));
nsCOMPtr<nsIScriptError> errorObject
(do_CreateInstance("mozilla.scripterror.1"));
if (consoleService && errorObject) {
nsresult rv;
rv = errorObject->Init(aError,
NS_ConvertASCIItoUCS2(mFileName.get()).GetUnicode(),
NS_LITERAL_STRING(""),
mLineNumber,
mColNumber,
0,
"CSS Parser");
if (NS_SUCCEEDED(rv))
consoleService->LogMessage(errorObject);
}
}
#endif // CSS_REPORT_PARSE_ERRORS
void nsCSSScanner::Close()
{
NS_IF_RELEASE(mInput);
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define TAB_STOP_WIDTH 8
#endif
// Returns -1 on error or eof
PRInt32 nsCSSScanner::Read(PRInt32& aErrorCode)
{
@ -211,6 +271,17 @@ PRInt32 nsCSSScanner::Read(PRInt32& aErrorCode)
}
}
rv = PRInt32(mBuffer[mOffset++]);
#ifdef CSS_REPORT_PARSE_ERRORS
if (((rv == '\n') && (mLastRead != '\r')) || (rv == '\r')) {
mLineNumber++;
mColNumber = 0;
} else if (rv == '\t') {
mColNumber = ((mColNumber - 1 + TAB_STOP_WIDTH) / TAB_STOP_WIDTH)
* TAB_STOP_WIDTH;
} else if (rv != '\n') {
mColNumber++;
}
#endif
}
mLastRead = rv;
//printf("Read => %x\n", rv);

Просмотреть файл

@ -25,6 +25,14 @@
#include "nsString.h"
class nsIUnicharInputStream;
// for testing
//#define CSS_REPORT_PARSE_ERRORS
#ifdef CSS_REPORT_PARSE_ERRORS
#include "nsXPIDLString.h"
class nsIURI;
#endif
// Token types
enum nsCSSTokenType {
// A css identifier (e.g. foo)
@ -97,6 +105,11 @@ class nsCSSScanner {
// Init the scanner.
void Init(nsIUnicharInputStream* aInput);
#ifdef CSS_REPORT_PARSE_ERRORS
void InitErrorReporting(nsIURI* aURI);
void ReportError(const PRUnichar* aError);
#endif
// Get the next token. Return nsfalse on EOF or ERROR. aTokenResult
// is filled in with the data for the token.
PRBool Next(PRInt32& aErrorCode, nsCSSToken& aTokenResult);
@ -139,6 +152,13 @@ protected:
PRInt32 mPushbackSize;
PRInt32 mLastRead;
PRUnichar mLocalPushback[4];
#ifdef CSS_REPORT_PARSE_ERRORS
nsXPIDLCString mFileName;
PRUint32 mLineNumber;
PRUint32 mColNumber;
#endif
};
#endif /* nsCSSScanner_h___ */

Просмотреть файл

@ -318,6 +318,34 @@ NS_NewCSSParser(nsICSSParser** aInstancePtrResult)
return it->QueryInterface(kICSSParserIID, (void **) aInstancePtrResult);
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define REPORT_UNEXPECTED_EOF() mScanner->ReportError(NS_LITERAL_STRING("Unexpected end of file"))
#define REPORT_UNEXPECTED_TOKEN() ReportUnexpectedToken(mScanner,mToken,nsnull)
#define REPORT_UNEXPECTED_TOKEN1(_reas) ReportUnexpectedToken(mScanner,mToken,_reas)
static void ReportUnexpectedToken(nsCSSScanner *sc,
nsCSSToken& tok,
char* reason)
{
nsString err;
if (!reason) {
err.AssignWithConversion("Unexpected token ");
} else {
err.AssignWithConversion(reason);
}
tok.AppendToString(err);
sc->ReportError(err.GetUnicode());
}
#else
#define REPORT_UNEXPECTED_EOF();
#define REPORT_UNEXPECTED_TOKEN();
#define REPORT_UNEXPECTED_TOKEN1(_reas);
#endif
CSSParserImpl::CSSParserImpl()
: mToken(),
mHavePushBack(PR_FALSE),
@ -328,10 +356,10 @@ CSSParserImpl::CSSParserImpl()
mChildLoader(nsnull),
mSection(eCSSSection_Charset),
mNavQuirkMode(PR_FALSE),
mParsingCompoundProperty(PR_FALSE),
mCaseSensitive(PR_FALSE),
mNameSpace(nsnull),
mGroupStack(nsnull)
mGroupStack(nsnull),
mParsingCompoundProperty(PR_FALSE)
{
NS_INIT_REFCNT();
@ -423,6 +451,9 @@ CSSParserImpl::InitScanner(nsIUnicharInputStream* aInput, nsIURI* aURI)
return NS_ERROR_OUT_OF_MEMORY;
}
mScanner->Init(aInput);
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->InitErrorReporting(aURI);
#endif
NS_IF_RELEASE(mURL);
mURL = aURI;
NS_IF_ADDREF(mURL);
@ -685,6 +716,7 @@ PRBool CSSParserImpl::ExpectEndProperty(PRInt32& aErrorCode, PRBool aSkipWS)
UngetToken();
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -692,6 +724,7 @@ PRBool CSSParserImpl::ExpectEndProperty(PRInt32& aErrorCode, PRBool aSkipWS)
nsString* CSSParserImpl::NextIdent(PRInt32& aErrorCode)
{
// XXX Error reporting?
if (!GetToken(aErrorCode, PR_TRUE)) {
return nsnull;
}
@ -706,6 +739,7 @@ PRBool CSSParserImpl::SkipAtRule(PRInt32& aErrorCode)
{
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Symbol == mToken.mType) {
@ -767,6 +801,12 @@ PRBool CSSParserImpl::ParseAtRule(PRInt32& aErrorCode)
return PR_TRUE;
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
nsString err;
err.AssignWithConversion("Unrecognized at-rule ");
mToken.AppendToString(err);
mScanner->ReportError(err.GetUnicode());
#endif
// Skip over unsupported at rule, don't advance section
return SkipAtRule(aErrorCode);
@ -785,6 +825,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
PRBool expectIdent = PR_TRUE;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol == mToken.mType) {
@ -793,9 +834,11 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
UngetToken();
return PR_TRUE;
} else if (',' != symbol) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
} else if (expectIdent) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
@ -819,11 +862,13 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
expectIdent = PR_FALSE;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
break;
}
@ -839,6 +884,7 @@ PRBool CSSParserImpl::GatherMedia(PRInt32& aErrorCode, nsString& aMedia,
PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
nsAutoString url;
@ -871,6 +917,7 @@ PRBool CSSParserImpl::ParseImportRule(PRInt32& aErrorCode)
}
}
}
REPORT_UNEXPECTED_TOKEN();
// don't advance section, simply ignore invalid @import
return PR_FALSE;
}
@ -911,7 +958,7 @@ PRBool CSSParserImpl::ProcessImport(PRInt32& aErrorCode, const nsString& aURLSpe
return result;
}
// Parse a CSS2 media rule: "@media medium [, mdeium] { ... }"
// Parse a CSS2 media rule: "@media medium [, medium] { ... }"
PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
{
nsAutoString mediaStr;
@ -933,6 +980,7 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
for (;;) {
// Get next non-whitespace token
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (mToken.IsSymbol('}')) { // done!
@ -974,6 +1022,7 @@ PRBool CSSParserImpl::ParseMediaRule(PRInt32& aErrorCode)
PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
@ -983,6 +1032,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
if (eCSSToken_Ident == mToken.mType) {
prefix = mToken.mIdent;
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
}
@ -1010,6 +1060,7 @@ PRBool CSSParserImpl::ParseNameSpaceRule(PRInt32& aErrorCode)
}
}
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
@ -1078,6 +1129,9 @@ CSSParserImpl::SkipDeclaration(PRInt32& aErrorCode, PRBool aCheckForBraces)
nsCSSToken* tk = &mToken;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
REPORT_UNEXPECTED_EOF();
}
return PR_FALSE;
}
if (eCSSToken_Symbol == tk->mType) {
@ -1108,6 +1162,7 @@ void CSSParserImpl::SkipRuleSet(PRInt32& aErrorCode)
nsCSSToken* tk = &mToken;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol == tk->mType) {
@ -1125,6 +1180,8 @@ void CSSParserImpl::SkipRuleSet(PRInt32& aErrorCode)
}
}
// XXX Make sure report errors before calling Skip*
PRBool CSSParserImpl::PushGroup(nsICSSGroupRule* aRule)
{
if (! mGroupStack) {
@ -1225,6 +1282,9 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
SelectorList* list = nsnull;
if (! ParseSelectorGroup(aErrorCode, list)) {
// must have at least one selector group
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Selector expected"));
#endif
aListHead = nsnull;
return PR_FALSE;
}
@ -1235,6 +1295,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
nsCSSToken* tk = &mToken;
for (;;) {
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
break;
}
if (eCSSToken_Symbol != tk->mType) {
@ -1259,6 +1320,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
break;
}
}
REPORT_UNEXPECTED_TOKEN();
delete aListHead;
aListHead = nsnull;
@ -1381,11 +1443,18 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
weight += selector.CalcWeight();
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
if (!list)
mScanner->ReportError(NS_LITERAL_STRING("Selector expected"));
#endif
if (PRUnichar(0) != combinator) { // no dangling combinators
if (list) {
delete list;
}
list = nsnull;
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Dangling combinator"));
#endif
}
aList = list;
if (nsnull != list) {
@ -1416,6 +1485,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
nsAutoString buffer;
if (! GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (mToken.IsSymbol('*')) { // universal element selector, or universal namespace
@ -1426,6 +1496,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.SetNameSpace(kNameSpaceID_Unknown); // namespace wildcard
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1444,6 +1515,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1488,11 +1560,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_IF_RELEASE(prefix);
} // else, no delcared namespaces
if (kNameSpaceID_Unknown == nameSpaceID) { // unknown prefix, dump it
REPORT_UNEXPECTED_TOKEN1("Unknown namespace prefix ");
return PR_FALSE;
}
aSelector.SetNameSpace(nameSpaceID);
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1511,6 +1585,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1547,6 +1622,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// get mandatory tag
if (! GetToken(aErrorCode, PR_FALSE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1565,6 +1641,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
// don't set tag
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1581,6 +1658,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.SetID(mToken.mIdent);
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1588,9 +1666,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol('.')) { // .class
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // get ident
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Ident != mToken.mType) { // malformed selector (XXX what about leading digits?)
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1601,9 +1681,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol(':')) { // :pseudo
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (eCSSToken_Ident != mToken.mType) { // malformed selector
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1632,11 +1714,13 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
UngetToken();
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else { // multiple pseudo elements, not legal
REPORT_UNEXPECTED_TOKEN1("Extra pseudo-element ");
UngetToken();
NS_RELEASE(pseudo);
return PR_FALSE;
@ -1646,6 +1730,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
else if (mToken.IsSymbol('[')) { // attribute
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1657,6 +1742,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {
mToken.AppendToString(aSource);
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1664,16 +1750,19 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
}
else if (mToken.IsSymbol('|')) { // NO namespace
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1681,6 +1770,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1703,9 +1793,11 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
NS_IF_RELEASE(prefix);
} // else, no delcared namespaces
if (kNameSpaceID_Unknown == nameSpaceID) { // unknown prefix, dump it
REPORT_UNEXPECTED_TOKEN1("Unknown namespace prefix ");
return PR_FALSE;
}
if (! GetToken(aErrorCode, PR_FALSE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
mToken.AppendToString(aSource);
@ -1713,12 +1805,14 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr = mToken.mIdent;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
}
else { // malformed
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1727,6 +1821,7 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
attr.ToLowerCase();
}
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Symbol == mToken.mType) ||
@ -1749,17 +1844,20 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
func = NS_ATTR_FUNC_EQUALS;
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken(); // bad function
return PR_FALSE;
}
if (NS_ATTR_FUNC_SET != func) { // get value
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) {
mToken.AppendToString(aSource);
nsAutoString value(mToken.mIdent);
if (! GetToken(aErrorCode, PR_TRUE)) { // premature EOF
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if (mToken.IsSymbol(']')) {
@ -1768,17 +1866,20 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,
aSelector.AddAttribute(nameSpaceID, attr, func, value, mCaseSensitive);
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
}
}
else {
REPORT_UNEXPECTED_TOKEN();
UngetToken(); // bad dog, no biscut!
return PR_FALSE;
}
@ -1801,6 +1902,7 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
{
if (aCheckForBraces) {
if (!ExpectSymbol(aErrorCode, '{', PR_TRUE)) {
REPORT_UNEXPECTED_TOKEN();
return nsnull;
}
}
@ -1823,6 +1925,9 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
break;
}
}
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Declaration dropped"));
#endif
// Since the skipped declaration didn't end the block we parse
// the next declaration.
}
@ -1838,9 +1943,11 @@ CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,
PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
nsCSSToken* tk = &mToken;
nscolor rgba;
switch (tk->mType) {
@ -1880,6 +1987,7 @@ PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
aValue.SetColorValue(rgba);
return PR_TRUE;
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE; // already pushed back
}
break;
@ -1933,6 +2041,7 @@ PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue)
}
// It's not a color
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1942,6 +2051,7 @@ PRBool CSSParserImpl::ParseColorComponent(PRInt32& aErrorCode,
char aStop)
{
if (!GetToken(aErrorCode, PR_TRUE)) {
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
float value;
@ -1954,6 +2064,7 @@ PRBool CSSParserImpl::ParseColorComponent(PRInt32& aErrorCode,
value = tk->mNumber * 255.0f;
break;
default:
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -1979,12 +2090,16 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
nsAutoString propertyName;
for (;;) {
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
REPORT_UNEXPECTED_EOF();
}
return PR_FALSE;
}
if (eCSSToken_Ident == tk->mType) {
propertyName = tk->mIdent;
// grab the ident before the ExpectSymbol trashes the token
if (!ExpectSymbol(aErrorCode, ':', PR_TRUE)) {
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
break;
@ -2002,9 +2117,20 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
// Map property name to it's ID and then parse the property
nsCSSProperty propID = nsCSSProps::LookupProperty(propertyName);
if (eCSSProperty_UNKNOWN == propID) { // unknown property
#ifdef CSS_REPORT_PARSE_ERRORS
nsString err(NS_LITERAL_STRING("Unknown property "));
err.Append(propertyName);
mScanner->ReportError(err.GetUnicode());
#endif
return PR_FALSE;
}
if (! ParseProperty(aErrorCode, aDeclaration, propID, aChangeHint)) {
#ifdef CSS_REPORT_PARSE_ERRORS
// XXX Much better to put stuff in the value parsers instead...
nsString err(NS_LITERAL_STRING("Error parsing value for property "));
err.Append(propertyName);
mScanner->ReportError(err.GetUnicode());
#endif
return PR_FALSE;
}
@ -2013,6 +2139,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
// Premature eof is not ok when proper termination is mandated
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
return PR_TRUE;
@ -2023,10 +2150,12 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
// Look for important ident
if (!GetToken(aErrorCode, PR_TRUE)) {
// Premature eof is not ok
REPORT_UNEXPECTED_EOF();
return PR_FALSE;
}
if ((eCSSToken_Ident != tk->mType) ||
!tk->mIdent.EqualsIgnoreCase("important")) {
REPORT_UNEXPECTED_TOKEN();
UngetToken();
return PR_FALSE;
}
@ -2054,6 +2183,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!GetToken(aErrorCode, PR_TRUE)) {
if (aCheckForBraces) {
// Premature eof is not ok
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
return PR_TRUE;
@ -2065,6 +2195,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
if (!aCheckForBraces) {
// If we didn't hit eof and we didn't see a semicolon then the
// declaration is not properly terminated.
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
if ('}' == tk->mSymbol) {
@ -2072,6 +2203,7 @@ CSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,
return PR_TRUE;
}
}
REPORT_UNEXPECTED_TOKEN();
return PR_FALSE;
}
@ -2802,6 +2934,9 @@ PRBool CSSParserImpl::ParseProperty(PRInt32& aErrorCode,
case eCSSProperty_text_shadow_x:
case eCSSProperty_text_shadow_y:
// The user can't use these
#ifdef CSS_REPORT_PARSE_ERRORS
mScanner->ReportError(NS_LITERAL_STRING("Attempt to use inaccessible property"));
#endif
return PR_FALSE;
default: // must be single property
@ -2812,7 +2947,9 @@ PRBool CSSParserImpl::ParseProperty(PRInt32& aErrorCode,
aErrorCode = AppendValue(aDeclaration, aPropID, value, aChangeHint);
return PR_TRUE;
}
// XXX Report errors?
}
// XXX Report errors?
}
}
return PR_FALSE;

Просмотреть файл

@ -29,6 +29,15 @@
static char* kNullPointer = "null pointer";
#endif
#ifdef CSS_REPORT_PARSE_ERRORS
#include "nsCOMPtr.h"
#include "nsIURI.h"
#include "nsIConsoleService.h"
#include "nsIScriptError.h"
#include "nsIServiceManager.h"
#include "nsComponentManagerUtils.h"
#endif
// Don't bother collecting whitespace characters in token's mIdent buffer
#undef COLLECT_WHITESPACE
@ -164,6 +173,9 @@ nsCSSScanner::nsCSSScanner()
mPushback = mLocalPushback;
mPushbackCount = 0;
mPushbackSize = 4;
#ifdef CSS_REPORT_PARSE_ERRORS
mLastRead = 0;
#endif
}
nsCSSScanner::~nsCSSScanner()
@ -187,11 +199,59 @@ void nsCSSScanner::Init(nsIUnicharInputStream* aInput)
NS_IF_ADDREF(aInput);
}
#ifdef CSS_REPORT_PARSE_ERRORS
void nsCSSScanner::InitErrorReporting(nsIURI* aURI)
{
if (aURI) {
aURI->GetSpec(getter_Copies(mFileName));
} else {
mFileName = "from DOM";
}
mLineNumber = 1;
mColNumber = 0;
}
void nsCSSScanner::ReportError(const PRUnichar* aError)
{
printf("CSS Error (%s :%lu.%lu): %s.\n",
mFileName.get(),
mLineNumber,
mColNumber,
NS_ConvertUCS2toUTF8(aError).GetBuffer());
// Log it to the JavaScript console
nsCOMPtr<nsIConsoleService> consoleService
(do_GetService("mozilla.consoleservice.1"));
nsCOMPtr<nsIScriptError> errorObject
(do_CreateInstance("mozilla.scripterror.1"));
if (consoleService && errorObject) {
nsresult rv;
rv = errorObject->Init(aError,
NS_ConvertASCIItoUCS2(mFileName.get()).GetUnicode(),
NS_LITERAL_STRING(""),
mLineNumber,
mColNumber,
0,
"CSS Parser");
if (NS_SUCCEEDED(rv))
consoleService->LogMessage(errorObject);
}
}
#endif // CSS_REPORT_PARSE_ERRORS
void nsCSSScanner::Close()
{
NS_IF_RELEASE(mInput);
}
#ifdef CSS_REPORT_PARSE_ERRORS
#define TAB_STOP_WIDTH 8
#endif
// Returns -1 on error or eof
PRInt32 nsCSSScanner::Read(PRInt32& aErrorCode)
{
@ -211,6 +271,17 @@ PRInt32 nsCSSScanner::Read(PRInt32& aErrorCode)
}
}
rv = PRInt32(mBuffer[mOffset++]);
#ifdef CSS_REPORT_PARSE_ERRORS
if (((rv == '\n') && (mLastRead != '\r')) || (rv == '\r')) {
mLineNumber++;
mColNumber = 0;
} else if (rv == '\t') {
mColNumber = ((mColNumber - 1 + TAB_STOP_WIDTH) / TAB_STOP_WIDTH)
* TAB_STOP_WIDTH;
} else if (rv != '\n') {
mColNumber++;
}
#endif
}
mLastRead = rv;
//printf("Read => %x\n", rv);

Просмотреть файл

@ -25,6 +25,14 @@
#include "nsString.h"
class nsIUnicharInputStream;
// for testing
//#define CSS_REPORT_PARSE_ERRORS
#ifdef CSS_REPORT_PARSE_ERRORS
#include "nsXPIDLString.h"
class nsIURI;
#endif
// Token types
enum nsCSSTokenType {
// A css identifier (e.g. foo)
@ -97,6 +105,11 @@ class nsCSSScanner {
// Init the scanner.
void Init(nsIUnicharInputStream* aInput);
#ifdef CSS_REPORT_PARSE_ERRORS
void InitErrorReporting(nsIURI* aURI);
void ReportError(const PRUnichar* aError);
#endif
// Get the next token. Return nsfalse on EOF or ERROR. aTokenResult
// is filled in with the data for the token.
PRBool Next(PRInt32& aErrorCode, nsCSSToken& aTokenResult);
@ -139,6 +152,13 @@ protected:
PRInt32 mPushbackSize;
PRInt32 mLastRead;
PRUnichar mLocalPushback[4];
#ifdef CSS_REPORT_PARSE_ERRORS
nsXPIDLCString mFileName;
PRUint32 mLineNumber;
PRUint32 mColNumber;
#endif
};
#endif /* nsCSSScanner_h___ */