Commit 70ed3e19 authored by oliver@apple.com's avatar oliver@apple.com

2010-12-20 Oliver Hunt <oliver@apple.com>

        Reviewed by Geoffrey Garen.

        |delete name| in strict mode code should be an early error
        https://bugs.webkit.org/show_bug.cgi?id=50431

        Disallow the |delete IDENTIFIER| production in strict mode, and removed
        a bunch of now unnecessary code.

        * parser/JSParser.cpp:
        (JSC::JSParser::Scope::collectFreeVariables):
        (JSC::jsParse):
        (JSC::JSParser::parseProgram):
        (JSC::JSParser::parseUnaryExpression):
        * parser/JSParser.h:
        * parser/Parser.cpp:
        (JSC::Parser::parse):
        * parser/Parser.h:
        (JSC::Parser::parse):
2010-12-20  Oliver Hunt  <oliver@apple.com>

        Reviewed by Geoffrey Garen.

        |delete name| in strict mode code should be an early error
        https://bugs.webkit.org/show_bug.cgi?id=50431

        Add a test to ensure that |delete IDENTIFIER| is disallowed, even if
        IDENTIFIER resolves to a deletable property.

        * fast/js/basic-strict-mode-expected.txt:
        * fast/js/script-tests/basic-strict-mode.js:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@74377 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 36f2f525
2010-12-20 Oliver Hunt <oliver@apple.com>
Reviewed by Geoffrey Garen.
|delete name| in strict mode code should be an early error
https://bugs.webkit.org/show_bug.cgi?id=50431
Disallow the |delete IDENTIFIER| production in strict mode, and removed
a bunch of now unnecessary code.
* parser/JSParser.cpp:
(JSC::JSParser::Scope::collectFreeVariables):
(JSC::jsParse):
(JSC::JSParser::parseProgram):
(JSC::JSParser::parseUnaryExpression):
* parser/JSParser.h:
* parser/Parser.cpp:
(JSC::Parser::parse):
* parser/Parser.h:
(JSC::Parser::parse):
2010-12-20 Gavin Barraclough <barraclough@apple.com>
Reviewed by Olver Hunt.
......
......@@ -68,7 +68,7 @@ COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
class JSParser {
public:
JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*);
bool parseProgram(JSGlobalObject*);
bool parseProgram();
private:
struct AllowInOverride {
AllowInOverride(JSParser* parser)
......@@ -295,15 +295,7 @@ private:
ASSERT(m_strictMode);
m_writtenVariables.add(ident->impl());
}
bool deleteProperty(const Identifier* ident)
{
if (m_declaredVariables.contains(ident->impl()))
return false;
m_deletedVariables.add(ident->impl());
return true;
}
void preventNewDecls() { m_allowsNewDecls = false; }
bool allowsNewDecls() const { return m_allowsNewDecls; }
......@@ -342,16 +334,7 @@ private:
m_writtenVariables.add(*ptr);
}
}
if (nestedScope->m_deletedVariables.size()) {
IdentifierSet::iterator end = nestedScope->m_deletedVariables.end();
for (IdentifierSet::iterator ptr = nestedScope->m_deletedVariables.begin(); ptr != end; ++ptr) {
if (nestedScope->m_declaredVariables.contains(*ptr))
return false;
if (m_declaredVariables.contains(*ptr))
return false;
m_deletedVariables.add(*ptr);
}
}
return true;
}
......@@ -364,17 +347,6 @@ private:
}
}
bool getDeletedVariables(IdentifierSet& deletedVariables)
{
IdentifierSet::iterator end = m_deletedVariables.end();
for (IdentifierSet::iterator ptr = m_deletedVariables.begin(); ptr != end; ++ptr) {
if (m_declaredVariables.contains(*ptr))
return false;
}
deletedVariables.swap(m_deletedVariables);
return true;
}
void getCapturedVariables(IdentifierSet& capturedVariables)
{
if (m_needsFullActivation || m_usesEval) {
......@@ -407,7 +379,6 @@ private:
IdentifierSet m_usedVariables;
IdentifierSet m_closedVariables;
IdentifierSet m_writtenVariables;
IdentifierSet m_deletedVariables;
};
typedef Vector<Scope, 10> ScopeStack;
......@@ -468,20 +439,13 @@ private:
m_scopeStack.last().declareWrite(ident);
}
bool deleteProperty(const Identifier* ident)
{
if (!m_syntaxAlreadyValidated)
return m_scopeStack.last().deleteProperty(ident);
return true;
}
ScopeStack m_scopeStack;
};
int jsParse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
{
JSParser parser(lexicalGlobalObject->globalData().lexer, &lexicalGlobalObject->globalData(), parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider());
return parser.parseProgram(lexicalGlobalObject);
JSParser parser(globalData->lexer, globalData, parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider());
return parser.parseProgram();
}
JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider)
......@@ -513,7 +477,7 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* p
m_lexer->setLastLineNumber(tokenLine());
}
bool JSParser::parseProgram(JSGlobalObject* lexicalGlobalObject)
bool JSParser::parseProgram()
{
ASTBuilder context(m_globalData, m_lexer);
if (m_lexer->isReparsing())
......@@ -522,17 +486,6 @@ bool JSParser::parseProgram(JSGlobalObject* lexicalGlobalObject)
SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
if (!sourceElements || !consume(EOFTOK))
return true;
if (!m_syntaxAlreadyValidated) {
IdentifierSet deletedVariables;
if (!scope->getDeletedVariables(deletedVariables))
return true;
IdentifierSet::const_iterator end = deletedVariables.end();
SymbolTable& globalEnvRecord = lexicalGlobalObject->symbolTable();
for (IdentifierSet::const_iterator ptr = deletedVariables.begin(); ptr != end; ++ptr) {
if (!globalEnvRecord.get(*ptr).isNull())
return true;
}
}
IdentifierSet capturedVariables;
scope->getCapturedVariables(capturedVariables);
m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features() | (scope->strictMode() ? StrictModeFeature : 0),
......@@ -1932,8 +1885,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB
expr = context.createVoid(expr);
break;
case DELETETOKEN:
if (strictMode() && context.isResolve(expr))
failIfFalse(deleteProperty(m_lastIdentifier));
failIfTrueIfStrict(context.isResolve(expr));
expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
break;
default:
......
......@@ -31,7 +31,7 @@ namespace JSC {
class ExecState;
class FunctionParameters;
class Identifier;
class JSGlobalObject;
class JSGlobalData;
class SourceCode;
enum {
......@@ -159,6 +159,6 @@ struct JSToken {
enum JSParserStrictness { JSParseNormal, JSParseStrict };
enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
int jsParse(JSGlobalObject*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*);
int jsParse(JSGlobalData*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*);
}
#endif // JSParser_h
......@@ -29,9 +29,9 @@
namespace JSC {
void Parser::parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg)
void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg)
{
ASSERT(lexicalGlobalObject);
ASSERT(globalData);
m_sourceElements = 0;
int defaultErrLine;
......@@ -45,10 +45,10 @@ void Parser::parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* para
*errLine = -1;
*errMsg = UString();
Lexer& lexer = *lexicalGlobalObject->globalData().lexer;
Lexer& lexer = *globalData->lexer;
lexer.setCode(*m_source, m_arena);
int parseError = jsParse(lexicalGlobalObject, parameters, strictness, mode, m_source);
int parseError = jsParse(globalData, parameters, strictness, mode, m_source);
int lineNumber = lexer.lineNumber();
bool lexError = lexer.sawError();
lexer.clear();
......
......@@ -57,7 +57,7 @@ namespace JSC {
ParserArena& arena() { return m_arena; }
private:
void parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg);
void parse(JSGlobalData*, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg);
// Used to determine type of error to report.
bool isFunctionBodyNode(ScopeNode*) { return false; }
......@@ -85,7 +85,7 @@ namespace JSC {
m_source = &source;
if (ParsedNode::scopeIsFunction)
lexicalGlobalObject->globalData().lexer->setIsReparsing();
parse(lexicalGlobalObject, parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg);
parse(&lexicalGlobalObject->globalData(), parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg);
RefPtr<ParsedNode> result;
if (m_sourceElements) {
......
2010-12-20 Oliver Hunt <oliver@apple.com>
Reviewed by Geoffrey Garen.
|delete name| in strict mode code should be an early error
https://bugs.webkit.org/show_bug.cgi?id=50431
Add a test to ensure that |delete IDENTIFIER| is disallowed, even if
IDENTIFIER resolves to a deletable property.
* fast/js/basic-strict-mode-expected.txt:
* fast/js/script-tests/basic-strict-mode.js:
2010-12-20 Andrei Popescu <andreip@google.com>
Reviewed by Jeremy Orlow.
......
......@@ -67,6 +67,7 @@ PASS 'use strict'; for(;;)continue missingLabel threw exception SyntaxError: Par
PASS 'use strict'; 007; threw exception SyntaxError: Parse error.
PASS 'use strict'; '\007'; threw exception SyntaxError: Parse error.
PASS '\007'; 'use strict'; threw exception SyntaxError: Parse error.
PASS 'use strict'; delete aDeletableProperty; threw exception SyntaxError: Parse error.
PASS 'use strict'; (function (){ delete someDeclaredGlobal;}) threw exception SyntaxError: Parse error.
PASS (function (){ 'use strict'; delete someDeclaredGlobal;}) threw exception SyntaxError: Parse error.
PASS 'use strict'; if (0) { someGlobal = 'Shouldn\'t be able to assign this.'; }; true; is true
......
......@@ -85,6 +85,9 @@ shouldThrow("'use strict'; '\\007';");
shouldThrow("'\\007'; 'use strict';");
var someDeclaredGlobal;
aDeletableProperty = 'test';
shouldThrow("'use strict'; delete aDeletableProperty;");
shouldThrow("'use strict'; (function (){ delete someDeclaredGlobal;})");
shouldThrow("(function (){ 'use strict'; delete someDeclaredGlobal;})");
shouldBeTrue("'use strict'; if (0) { someGlobal = 'Shouldn\\'t be able to assign this.'; }; true;");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment