Changeset 69516 in webkit


Ignore:
Timestamp:
Oct 11, 2010 12:12:29 PM (14 years ago)
Author:
oliver@apple.com
Message:

2010-10-01 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

[ES5] Implement strict mode
https://bugs.webkit.org/show_bug.cgi?id=10701

Initial strict mode implementation. This is the simplest
implementation that could possibly work and adds (hopefully)
all of the restrictions required by strict mode. There are
a number of inefficiencies, especially in the handling of
arguments and eval as smart implementations would make this
patch more complicated.

The SyntaxChecker AST builder has become somewhat more complex
as strict mode does require more parse tree information to
validate the syntax.

Summary of major changes to the parser:

  • We track when we enter strict mode (this may come as a surprise)
  • Strict mode actually requires a degree of AST knowledge to validate so the SyntaxChecker now produces values that can be used to distinguish "node" types.
  • We now track variables that are written to. We do this to statically identify writes to global properties that don't exist and abort at that point. This should actually make it possible to optimise some other cases in the future but for now it's purely for validity checking. Currently writes are only tracked in strict mode code.
  • Labels are now tracked as it is now a syntax error to jump to a label that does not exist (or to use break, continue, or return in a context where they would be invalid).

Runtime changes:

  • In order to get correct hanlding of the Arguments object all strict mode functions that reference arguments create and tearoff the arguments object on entry. This is not strictly necessary but was the least work necessary to get the correct behaviour.
  • PutPropertySlot now tracks whether it is being used for a strict mode write, and if so Object::put will throw when a write can't be completed.
  • StrictEvalActivation was added as an "activation" object for strict mode eval (so that strict eval does not introduce new variables into the containing scope).
  • CMakeLists.txt:
  • GNUmakefile.am:
  • JavaScriptCore.exp:
  • JavaScriptCore.pro:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::isStrictMode):
  • bytecode/EvalCodeCache.h: (JSC::EvalCodeCache::get):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::createArgumentsIfNecessary): (JSC::BytecodeGenerator::emitReturn):
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::isStrictMode): (JSC::BytecodeGenerator::makeFunction):
  • debugger/Debugger.cpp: (JSC::evaluateInGlobalCallFrame):
  • debugger/DebuggerCallFrame.cpp: (JSC::DebuggerCallFrame::evaluate):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::callEval): (JSC::Interpreter::unwindCallFrame): (JSC::Interpreter::execute): (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases):
  • jit/JIT.h:
  • jit/JITOpcodes.cpp: (JSC::JIT::emit_op_get_pnames): (JSC::JIT::emit_op_convert_this_strict): (JSC::JIT::emitSlow_op_convert_this_strict):
  • jit/JITOpcodes32_64.cpp: (JSC::JIT::emit_op_get_pnames):
  • jit/JITStubs.cpp: (JSC::DEFINE_STUB_FUNCTION):
  • jit/JITStubs.h:
  • parser/ASTBuilder.h: (JSC::ASTBuilder::createFunctionBody): (JSC::ASTBuilder::isResolve):
  • parser/JSParser.cpp: (JSC::JSParser::next): (JSC::JSParser::startLoop): (JSC::JSParser::endLoop): (JSC::JSParser::startSwitch): (JSC::JSParser::endSwitch): (JSC::JSParser::setStrictMode): (JSC::JSParser::strictMode): (JSC::JSParser::isValidStrictMode): (JSC::JSParser::declareParameter): (JSC::JSParser::breakIsValid): (JSC::JSParser::pushLabel): (JSC::JSParser::popLabel): (JSC::JSParser::hasLabel): (JSC::JSParser::DepthManager::DepthManager): (JSC::JSParser::DepthManager::~DepthManager): (JSC::JSParser::Scope::Scope): (JSC::JSParser::Scope::startSwitch): (JSC::JSParser::Scope::endSwitch): (JSC::JSParser::Scope::startLoop): (JSC::JSParser::Scope::endLoop): (JSC::JSParser::Scope::inLoop): (JSC::JSParser::Scope::breakIsValid): (JSC::JSParser::Scope::pushLabel): (JSC::JSParser::Scope::popLabel): (JSC::JSParser::Scope::hasLabel): (JSC::JSParser::Scope::isFunction): (JSC::JSParser::Scope::declareVariable): (JSC::JSParser::Scope::declareWrite): (JSC::JSParser::Scope::deleteProperty): (JSC::JSParser::Scope::declareParameter): (JSC::JSParser::Scope::setNeedsFullActivation): (JSC::JSParser::Scope::collectFreeVariables): (JSC::JSParser::Scope::getUncapturedWrittenVariables): (JSC::JSParser::Scope::getDeletedVariables): (JSC::JSParser::Scope::setStrictMode): (JSC::JSParser::Scope::strictMode): (JSC::JSParser::Scope::isValidStrictMode): (JSC::JSParser::pushScope): (JSC::JSParser::popScope): (JSC::JSParser::declareVariable): (JSC::JSParser::declareWrite): (JSC::JSParser::deleteProperty): (JSC::jsParse): (JSC::JSParser::JSParser): (JSC::JSParser::parseProgram): (JSC::JSParser::parseSourceElements): (JSC::JSParser::parseDoWhileStatement): (JSC::JSParser::parseWhileStatement): (JSC::JSParser::parseVarDeclarationList): (JSC::JSParser::parseConstDeclarationList): (JSC::JSParser::parseForStatement): (JSC::JSParser::parseBreakStatement): (JSC::JSParser::parseContinueStatement): (JSC::JSParser::parseReturnStatement): (JSC::JSParser::parseWithStatement): (JSC::JSParser::parseSwitchStatement): (JSC::JSParser::parseSwitchClauses): (JSC::JSParser::parseSwitchDefaultClause): (JSC::JSParser::parseTryStatement): (JSC::JSParser::parseBlockStatement): (JSC::JSParser::parseStatement): (JSC::JSParser::parseFormalParameters): (JSC::JSParser::parseFunctionBody): (JSC::JSParser::parseFunctionInfo): (JSC::JSParser::parseFunctionDeclaration): (JSC::JSParser::parseExpressionOrLabelStatement): (JSC::JSParser::parseIfStatement): (JSC::JSParser::parseExpression): (JSC::JSParser::parseAssignmentExpression): (JSC::JSParser::parseConditionalExpression): (JSC::JSParser::parseBinaryExpression): (JSC::JSParser::parseStrictObjectLiteral): (JSC::JSParser::parsePrimaryExpression): (JSC::JSParser::parseMemberExpression): (JSC::JSParser::parseUnaryExpression):
  • parser/JSParser.h:
  • parser/Lexer.cpp: (JSC::Lexer::parseString): (JSC::Lexer::lex):
  • parser/Lexer.h: (JSC::Lexer::isReparsing):
  • parser/Nodes.cpp: (JSC::ScopeNode::ScopeNode): (JSC::FunctionBodyNode::FunctionBodyNode): (JSC::FunctionBodyNode::create):
  • parser/Nodes.h: (JSC::ScopeNode::isStrictMode):
  • parser/Parser.cpp: (JSC::Parser::parse):
  • parser/Parser.h: (JSC::Parser::parse):
  • parser/SyntaxChecker.h: (JSC::SyntaxChecker::SyntaxChecker): (JSC::SyntaxChecker::makeFunctionCallNode): (JSC::SyntaxChecker::appendToComma): (JSC::SyntaxChecker::createCommaExpr): (JSC::SyntaxChecker::makeAssignNode): (JSC::SyntaxChecker::makePrefixNode): (JSC::SyntaxChecker::makePostfixNode): (JSC::SyntaxChecker::makeTypeOfNode): (JSC::SyntaxChecker::makeDeleteNode): (JSC::SyntaxChecker::makeNegateNode): (JSC::SyntaxChecker::makeBitwiseNotNode): (JSC::SyntaxChecker::createLogicalNot): (JSC::SyntaxChecker::createUnaryPlus): (JSC::SyntaxChecker::createVoid): (JSC::SyntaxChecker::thisExpr): (JSC::SyntaxChecker::createResolve): (JSC::SyntaxChecker::createObjectLiteral): (JSC::SyntaxChecker::createArray): (JSC::SyntaxChecker::createNumberExpr): (JSC::SyntaxChecker::createString): (JSC::SyntaxChecker::createBoolean): (JSC::SyntaxChecker::createNull): (JSC::SyntaxChecker::createBracketAccess): (JSC::SyntaxChecker::createDotAccess): (JSC::SyntaxChecker::createRegex): (JSC::SyntaxChecker::createNewExpr): (JSC::SyntaxChecker::createConditionalExpr): (JSC::SyntaxChecker::createAssignResolve): (JSC::SyntaxChecker::createFunctionExpr): (JSC::SyntaxChecker::createFunctionBody): (JSC::SyntaxChecker::appendBinaryExpressionInfo): (JSC::SyntaxChecker::operatorStackPop):
  • runtime/Arguments.cpp: (JSC::Arguments::createStrictModeCallerIfNecessary): (JSC::Arguments::createStrictModeCalleeIfNecessary): (JSC::Arguments::getOwnPropertySlot): (JSC::Arguments::getOwnPropertyDescriptor): (JSC::Arguments::put): (JSC::Arguments::deleteProperty):
  • runtime/Arguments.h: (JSC::Arguments::Arguments):
  • runtime/CommonIdentifiers.cpp: (JSC::CommonIdentifiers::CommonIdentifiers):
  • runtime/CommonIdentifiers.h:
  • runtime/Error.cpp: (JSC::StrictModeTypeErrorFunction::StrictModeTypeErrorFunction): (JSC::StrictModeTypeErrorFunction::constructThrowTypeError): (JSC::StrictModeTypeErrorFunction::getConstructData): (JSC::StrictModeTypeErrorFunction::callThrowTypeError): (JSC::StrictModeTypeErrorFunction::getCallData): (JSC::createTypeErrorFunction):
  • runtime/Error.h:
  • runtime/Executable.cpp: (JSC::EvalExecutable::EvalExecutable): (JSC::ProgramExecutable::ProgramExecutable): (JSC::FunctionExecutable::FunctionExecutable): (JSC::EvalExecutable::compileInternal): (JSC::ProgramExecutable::checkSyntax): (JSC::ProgramExecutable::compileInternal): (JSC::FunctionExecutable::compileForCallInternal): (JSC::FunctionExecutable::compileForConstructInternal): (JSC::FunctionExecutable::reparseExceptionInfo): (JSC::EvalExecutable::reparseExceptionInfo): (JSC::FunctionExecutable::fromGlobalCode): (JSC::ProgramExecutable::reparseExceptionInfo):
  • runtime/Executable.h: (JSC::ScriptExecutable::ScriptExecutable): (JSC::ScriptExecutable::isStrictMode): (JSC::EvalExecutable::create): (JSC::FunctionExecutable::create):
  • runtime/JSActivation.cpp: (JSC::JSActivation::toStrictThisObject):
  • runtime/JSActivation.h:
  • runtime/JSFunction.cpp: (JSC::createDescriptorForThrowingProperty): (JSC::JSFunction::getOwnPropertySlot): (JSC::JSFunction::getOwnPropertyDescriptor): (JSC::JSFunction::put):
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
  • runtime/JSGlobalData.h:
  • runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::reset):
  • runtime/JSGlobalObject.h: (JSC::JSGlobalObject::internalFunctionStructure):
  • runtime/JSGlobalObjectFunctions.cpp: (JSC::globalFuncEval):
  • runtime/JSObject.cpp: (JSC::JSObject::put): (JSC::JSObject::toStrictThisObject): (JSC::throwTypeError):
  • runtime/JSObject.h: (JSC::JSObject::isStrictModeFunction): (JSC::JSObject::putDirectInternal): (JSC::JSObject::putDirect): (JSC::JSValue::putDirect): (JSC::JSValue::toStrictThisObject):
  • runtime/JSStaticScopeObject.cpp: (JSC::JSStaticScopeObject::toStrictThisObject):
  • runtime/JSStaticScopeObject.h:
  • runtime/JSValue.h:
  • runtime/JSZombie.h: (JSC::JSZombie::toStrictThisObject):
  • runtime/PutPropertySlot.h: (JSC::PutPropertySlot::PutPropertySlot): (JSC::PutPropertySlot::isStrictMode):
  • runtime/StrictEvalActivation.cpp: Added. (JSC::StrictEvalActivation::StrictEvalActivation): (JSC::StrictEvalActivation::deleteProperty): (JSC::StrictEvalActivation::toThisObject): (JSC::StrictEvalActivation::toStrictThisObject):
  • runtime/StrictEvalActivation.h: Added.

2010-10-01 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

[ES5] Implement strict mode
https://bugs.webkit.org/show_bug.cgi?id=10701

Tests for the many different behaviours we get in strict mode.

  • fast/js/basic-strict-mode-expected.txt: Added.
  • fast/js/basic-strict-mode.html: Added.
  • fast/js/script-tests/basic-strict-mode.js: Added. (testThis): (testGlobalAccess):

2010-10-01 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

[ES5] Implement strict mode
https://bugs.webkit.org/show_bug.cgi?id=10701

Test: fast/js/basic-strict-mode.html

Override toStrictThisObject on the domwindow so that
it correctly provides the shell object when used as this
in a strict mode function.

  • bindings/js/JSDOMWindowBase.cpp: (WebCore::JSDOMWindowBase::toStrictThisObject):
  • bindings/js/JSDOMWindowBase.h:
Location:
trunk
Files:
5 added
60 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/CMakeLists.txt

    r69132 r69516  
    158158    runtime/ScopeChain.cpp
    159159    runtime/SmallStrings.cpp
     160    runtime/StrictEvalActivation.cpp
    160161    runtime/StringConstructor.cpp
    161162    runtime/StringObject.cpp
  • trunk/JavaScriptCore/ChangeLog

    r69475 r69516  
     12010-10-01  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        [ES5] Implement strict mode
     6        https://bugs.webkit.org/show_bug.cgi?id=10701
     7
     8        Initial strict mode implementation.  This is the simplest
     9        implementation that could possibly work and adds (hopefully)
     10        all of the restrictions required by strict mode.  There are
     11        a number of inefficiencies, especially in the handling of
     12        arguments and eval as smart implementations would make this
     13        patch more complicated. 
     14
     15        The SyntaxChecker AST builder has become somewhat more complex
     16        as strict mode does require more parse tree information to
     17        validate the syntax.
     18
     19        Summary of major changes to the parser:
     20            * We track when we enter strict mode (this may come as a surprise)
     21            * Strict mode actually requires a degree of AST knowledge to validate
     22              so the SyntaxChecker now produces values that can be used to distinguish
     23              "node" types.
     24            * We now track variables that are written to.  We do this to
     25              statically identify writes to global properties that don't exist
     26              and abort at that point.  This should actually make it possible
     27              to optimise some other cases in the future but for now it's
     28              purely for validity checking.  Currently writes are only tracked
     29              in strict mode code.
     30            * Labels are now tracked as it is now a syntax error to jump to a label
     31              that does not exist (or to use break, continue, or return in a context
     32              where they would be invalid).
     33
     34        Runtime changes:
     35            * In order to get correct hanlding of the Arguments object all
     36              strict mode functions that reference arguments create and tearoff
     37              the arguments object on entry.  This is not strictly necessary
     38              but was the least work necessary to get the correct behaviour.
     39            * PutPropertySlot now tracks whether it is being used for a strict
     40              mode write, and if so Object::put will throw when a write can't be
     41              completed.
     42            * StrictEvalActivation was added as an "activation" object for strict
     43              mode eval (so that strict eval does not introduce new variables into
     44              the containing scope).
     45
     46        * CMakeLists.txt:
     47        * GNUmakefile.am:
     48        * JavaScriptCore.exp:
     49        * JavaScriptCore.pro:
     50        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     51        * JavaScriptCore.xcodeproj/project.pbxproj:
     52        * bytecode/CodeBlock.cpp:
     53        (JSC::CodeBlock::dump):
     54        (JSC::CodeBlock::CodeBlock):
     55        (JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
     56        * bytecode/CodeBlock.h:
     57        (JSC::CodeBlock::isStrictMode):
     58        * bytecode/EvalCodeCache.h:
     59        (JSC::EvalCodeCache::get):
     60        * bytecode/Opcode.h:
     61        * bytecompiler/BytecodeGenerator.cpp:
     62        (JSC::BytecodeGenerator::BytecodeGenerator):
     63        (JSC::BytecodeGenerator::createArgumentsIfNecessary):
     64        (JSC::BytecodeGenerator::emitReturn):
     65        * bytecompiler/BytecodeGenerator.h:
     66        (JSC::BytecodeGenerator::isStrictMode):
     67        (JSC::BytecodeGenerator::makeFunction):
     68        * debugger/Debugger.cpp:
     69        (JSC::evaluateInGlobalCallFrame):
     70        * debugger/DebuggerCallFrame.cpp:
     71        (JSC::DebuggerCallFrame::evaluate):
     72        * interpreter/Interpreter.cpp:
     73        (JSC::Interpreter::callEval):
     74        (JSC::Interpreter::unwindCallFrame):
     75        (JSC::Interpreter::execute):
     76        (JSC::Interpreter::privateExecute):
     77        * jit/JIT.cpp:
     78        (JSC::JIT::privateCompileMainPass):
     79        (JSC::JIT::privateCompileSlowCases):
     80        * jit/JIT.h:
     81        * jit/JITOpcodes.cpp:
     82        (JSC::JIT::emit_op_get_pnames):
     83        (JSC::JIT::emit_op_convert_this_strict):
     84        (JSC::JIT::emitSlow_op_convert_this_strict):
     85        * jit/JITOpcodes32_64.cpp:
     86        (JSC::JIT::emit_op_get_pnames):
     87        * jit/JITStubs.cpp:
     88        (JSC::DEFINE_STUB_FUNCTION):
     89        * jit/JITStubs.h:
     90        * parser/ASTBuilder.h:
     91        (JSC::ASTBuilder::createFunctionBody):
     92        (JSC::ASTBuilder::isResolve):
     93        * parser/JSParser.cpp:
     94        (JSC::JSParser::next):
     95        (JSC::JSParser::startLoop):
     96        (JSC::JSParser::endLoop):
     97        (JSC::JSParser::startSwitch):
     98        (JSC::JSParser::endSwitch):
     99        (JSC::JSParser::setStrictMode):
     100        (JSC::JSParser::strictMode):
     101        (JSC::JSParser::isValidStrictMode):
     102        (JSC::JSParser::declareParameter):
     103        (JSC::JSParser::breakIsValid):
     104        (JSC::JSParser::pushLabel):
     105        (JSC::JSParser::popLabel):
     106        (JSC::JSParser::hasLabel):
     107        (JSC::JSParser::DepthManager::DepthManager):
     108        (JSC::JSParser::DepthManager::~DepthManager):
     109        (JSC::JSParser::Scope::Scope):
     110        (JSC::JSParser::Scope::startSwitch):
     111        (JSC::JSParser::Scope::endSwitch):
     112        (JSC::JSParser::Scope::startLoop):
     113        (JSC::JSParser::Scope::endLoop):
     114        (JSC::JSParser::Scope::inLoop):
     115        (JSC::JSParser::Scope::breakIsValid):
     116        (JSC::JSParser::Scope::pushLabel):
     117        (JSC::JSParser::Scope::popLabel):
     118        (JSC::JSParser::Scope::hasLabel):
     119        (JSC::JSParser::Scope::isFunction):
     120        (JSC::JSParser::Scope::declareVariable):
     121        (JSC::JSParser::Scope::declareWrite):
     122        (JSC::JSParser::Scope::deleteProperty):
     123        (JSC::JSParser::Scope::declareParameter):
     124        (JSC::JSParser::Scope::setNeedsFullActivation):
     125        (JSC::JSParser::Scope::collectFreeVariables):
     126        (JSC::JSParser::Scope::getUncapturedWrittenVariables):
     127        (JSC::JSParser::Scope::getDeletedVariables):
     128        (JSC::JSParser::Scope::setStrictMode):
     129        (JSC::JSParser::Scope::strictMode):
     130        (JSC::JSParser::Scope::isValidStrictMode):
     131        (JSC::JSParser::pushScope):
     132        (JSC::JSParser::popScope):
     133        (JSC::JSParser::declareVariable):
     134        (JSC::JSParser::declareWrite):
     135        (JSC::JSParser::deleteProperty):
     136        (JSC::jsParse):
     137        (JSC::JSParser::JSParser):
     138        (JSC::JSParser::parseProgram):
     139        (JSC::JSParser::parseSourceElements):
     140        (JSC::JSParser::parseDoWhileStatement):
     141        (JSC::JSParser::parseWhileStatement):
     142        (JSC::JSParser::parseVarDeclarationList):
     143        (JSC::JSParser::parseConstDeclarationList):
     144        (JSC::JSParser::parseForStatement):
     145        (JSC::JSParser::parseBreakStatement):
     146        (JSC::JSParser::parseContinueStatement):
     147        (JSC::JSParser::parseReturnStatement):
     148        (JSC::JSParser::parseWithStatement):
     149        (JSC::JSParser::parseSwitchStatement):
     150        (JSC::JSParser::parseSwitchClauses):
     151        (JSC::JSParser::parseSwitchDefaultClause):
     152        (JSC::JSParser::parseTryStatement):
     153        (JSC::JSParser::parseBlockStatement):
     154        (JSC::JSParser::parseStatement):
     155        (JSC::JSParser::parseFormalParameters):
     156        (JSC::JSParser::parseFunctionBody):
     157        (JSC::JSParser::parseFunctionInfo):
     158        (JSC::JSParser::parseFunctionDeclaration):
     159        (JSC::JSParser::parseExpressionOrLabelStatement):
     160        (JSC::JSParser::parseIfStatement):
     161        (JSC::JSParser::parseExpression):
     162        (JSC::JSParser::parseAssignmentExpression):
     163        (JSC::JSParser::parseConditionalExpression):
     164        (JSC::JSParser::parseBinaryExpression):
     165        (JSC::JSParser::parseStrictObjectLiteral):
     166        (JSC::JSParser::parsePrimaryExpression):
     167        (JSC::JSParser::parseMemberExpression):
     168        (JSC::JSParser::parseUnaryExpression):
     169        * parser/JSParser.h:
     170        * parser/Lexer.cpp:
     171        (JSC::Lexer::parseString):
     172        (JSC::Lexer::lex):
     173        * parser/Lexer.h:
     174        (JSC::Lexer::isReparsing):
     175        * parser/Nodes.cpp:
     176        (JSC::ScopeNode::ScopeNode):
     177        (JSC::FunctionBodyNode::FunctionBodyNode):
     178        (JSC::FunctionBodyNode::create):
     179        * parser/Nodes.h:
     180        (JSC::ScopeNode::isStrictMode):
     181        * parser/Parser.cpp:
     182        (JSC::Parser::parse):
     183        * parser/Parser.h:
     184        (JSC::Parser::parse):
     185        * parser/SyntaxChecker.h:
     186        (JSC::SyntaxChecker::SyntaxChecker):
     187        (JSC::SyntaxChecker::makeFunctionCallNode):
     188        (JSC::SyntaxChecker::appendToComma):
     189        (JSC::SyntaxChecker::createCommaExpr):
     190        (JSC::SyntaxChecker::makeAssignNode):
     191        (JSC::SyntaxChecker::makePrefixNode):
     192        (JSC::SyntaxChecker::makePostfixNode):
     193        (JSC::SyntaxChecker::makeTypeOfNode):
     194        (JSC::SyntaxChecker::makeDeleteNode):
     195        (JSC::SyntaxChecker::makeNegateNode):
     196        (JSC::SyntaxChecker::makeBitwiseNotNode):
     197        (JSC::SyntaxChecker::createLogicalNot):
     198        (JSC::SyntaxChecker::createUnaryPlus):
     199        (JSC::SyntaxChecker::createVoid):
     200        (JSC::SyntaxChecker::thisExpr):
     201        (JSC::SyntaxChecker::createResolve):
     202        (JSC::SyntaxChecker::createObjectLiteral):
     203        (JSC::SyntaxChecker::createArray):
     204        (JSC::SyntaxChecker::createNumberExpr):
     205        (JSC::SyntaxChecker::createString):
     206        (JSC::SyntaxChecker::createBoolean):
     207        (JSC::SyntaxChecker::createNull):
     208        (JSC::SyntaxChecker::createBracketAccess):
     209        (JSC::SyntaxChecker::createDotAccess):
     210        (JSC::SyntaxChecker::createRegex):
     211        (JSC::SyntaxChecker::createNewExpr):
     212        (JSC::SyntaxChecker::createConditionalExpr):
     213        (JSC::SyntaxChecker::createAssignResolve):
     214        (JSC::SyntaxChecker::createFunctionExpr):
     215        (JSC::SyntaxChecker::createFunctionBody):
     216        (JSC::SyntaxChecker::appendBinaryExpressionInfo):
     217        (JSC::SyntaxChecker::operatorStackPop):
     218        * runtime/Arguments.cpp:
     219        (JSC::Arguments::createStrictModeCallerIfNecessary):
     220        (JSC::Arguments::createStrictModeCalleeIfNecessary):
     221        (JSC::Arguments::getOwnPropertySlot):
     222        (JSC::Arguments::getOwnPropertyDescriptor):
     223        (JSC::Arguments::put):
     224        (JSC::Arguments::deleteProperty):
     225        * runtime/Arguments.h:
     226        (JSC::Arguments::Arguments):
     227        * runtime/CommonIdentifiers.cpp:
     228        (JSC::CommonIdentifiers::CommonIdentifiers):
     229        * runtime/CommonIdentifiers.h:
     230        * runtime/Error.cpp:
     231        (JSC::StrictModeTypeErrorFunction::StrictModeTypeErrorFunction):
     232        (JSC::StrictModeTypeErrorFunction::constructThrowTypeError):
     233        (JSC::StrictModeTypeErrorFunction::getConstructData):
     234        (JSC::StrictModeTypeErrorFunction::callThrowTypeError):
     235        (JSC::StrictModeTypeErrorFunction::getCallData):
     236        (JSC::createTypeErrorFunction):
     237        * runtime/Error.h:
     238        * runtime/Executable.cpp:
     239        (JSC::EvalExecutable::EvalExecutable):
     240        (JSC::ProgramExecutable::ProgramExecutable):
     241        (JSC::FunctionExecutable::FunctionExecutable):
     242        (JSC::EvalExecutable::compileInternal):
     243        (JSC::ProgramExecutable::checkSyntax):
     244        (JSC::ProgramExecutable::compileInternal):
     245        (JSC::FunctionExecutable::compileForCallInternal):
     246        (JSC::FunctionExecutable::compileForConstructInternal):
     247        (JSC::FunctionExecutable::reparseExceptionInfo):
     248        (JSC::EvalExecutable::reparseExceptionInfo):
     249        (JSC::FunctionExecutable::fromGlobalCode):
     250        (JSC::ProgramExecutable::reparseExceptionInfo):
     251        * runtime/Executable.h:
     252        (JSC::ScriptExecutable::ScriptExecutable):
     253        (JSC::ScriptExecutable::isStrictMode):
     254        (JSC::EvalExecutable::create):
     255        (JSC::FunctionExecutable::create):
     256        * runtime/JSActivation.cpp:
     257        (JSC::JSActivation::toStrictThisObject):
     258        * runtime/JSActivation.h:
     259        * runtime/JSFunction.cpp:
     260        (JSC::createDescriptorForThrowingProperty):
     261        (JSC::JSFunction::getOwnPropertySlot):
     262        (JSC::JSFunction::getOwnPropertyDescriptor):
     263        (JSC::JSFunction::put):
     264        * runtime/JSGlobalData.cpp:
     265        (JSC::JSGlobalData::JSGlobalData):
     266        * runtime/JSGlobalData.h:
     267        * runtime/JSGlobalObject.cpp:
     268        (JSC::JSGlobalObject::reset):
     269        * runtime/JSGlobalObject.h:
     270        (JSC::JSGlobalObject::internalFunctionStructure):
     271        * runtime/JSGlobalObjectFunctions.cpp:
     272        (JSC::globalFuncEval):
     273        * runtime/JSObject.cpp:
     274        (JSC::JSObject::put):
     275        (JSC::JSObject::toStrictThisObject):
     276        (JSC::throwTypeError):
     277        * runtime/JSObject.h:
     278        (JSC::JSObject::isStrictModeFunction):
     279        (JSC::JSObject::putDirectInternal):
     280        (JSC::JSObject::putDirect):
     281        (JSC::JSValue::putDirect):
     282        (JSC::JSValue::toStrictThisObject):
     283        * runtime/JSStaticScopeObject.cpp:
     284        (JSC::JSStaticScopeObject::toStrictThisObject):
     285        * runtime/JSStaticScopeObject.h:
     286        * runtime/JSValue.h:
     287        * runtime/JSZombie.h:
     288        (JSC::JSZombie::toStrictThisObject):
     289        * runtime/PutPropertySlot.h:
     290        (JSC::PutPropertySlot::PutPropertySlot):
     291        (JSC::PutPropertySlot::isStrictMode):
     292        * runtime/StrictEvalActivation.cpp: Added.
     293        (JSC::StrictEvalActivation::StrictEvalActivation):
     294        (JSC::StrictEvalActivation::deleteProperty):
     295        (JSC::StrictEvalActivation::toThisObject):
     296        (JSC::StrictEvalActivation::toStrictThisObject):
     297        * runtime/StrictEvalActivation.h: Added.
     298
    12992010-10-10  Patrick Gansterer  <paroga@webkit.org>
    2300
  • trunk/JavaScriptCore/GNUmakefile.am

    r67963 r69516  
    389389        JavaScriptCore/runtime/SmallStrings.cpp \
    390390        JavaScriptCore/runtime/SmallStrings.h \
     391        JavaScriptCore/runtime/StrictEvalActivation.cpp\
     392        JavaScriptCore/runtime/StrictEvalActivation.h\
    391393        JavaScriptCore/runtime/StringBuilder.h \
    392394        JavaScriptCore/runtime/StringConcatenate.h \
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r69277 r69516  
    532532__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
    533533__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
     534__ZNK3JSC8JSObject18toStrictThisObjectEPNS_9ExecStateE
    534535__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
    535536__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
  • trunk/JavaScriptCore/JavaScriptCore.pro

    r67306 r69516  
    198198    runtime/ScopeChain.cpp \
    199199    runtime/SmallStrings.cpp \
     200    runtime/StrictEvalActivation.cpp \
    200201    runtime/StringConstructor.cpp \
    201202    runtime/StringObject.cpp \
  • trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r64943 r69516  
    11741174                        </File>
    11751175                        <File
     1176                                RelativePath="..\..\runtime\StrictEvalActivation.cpp"
     1177                                >
     1178                        </File>
     1179                        <File
     1180                                RelativePath="..\..\runtime\StrictEvalActivation.h"
     1181                                >
     1182                        </File>
     1183                        <File
    11761184                                RelativePath="..\..\runtime\StringConstructor.cpp"
    11771185                                >
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r69045 r69516  
    319319                A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; };
    320320                A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
     321                A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = A730B6101250068F009D25B1 /* StrictEvalActivation.h */; };
     322                A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */; };
    321323                A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386551118697B400540279 /* SpecializedThunkJIT.h */; };
    322324                A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7386552118697B400540279 /* ThunkGenerators.cpp */; };
     
    952954                A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; };
    953955                A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; };
     956                A730B6101250068F009D25B1 /* StrictEvalActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StrictEvalActivation.h; sourceTree = "<group>"; };
     957                A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StrictEvalActivation.cpp; sourceTree = "<group>"; };
    954958                A7386551118697B400540279 /* SpecializedThunkJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecializedThunkJIT.h; sourceTree = "<group>"; };
    955959                A7386552118697B400540279 /* ThunkGenerators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThunkGenerators.cpp; sourceTree = "<group>"; };
     
    18151819                                14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */,
    18161820                                1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
     1821                                A730B6101250068F009D25B1 /* StrictEvalActivation.h */,
     1822                                A730B6111250068F009D25B1 /* StrictEvalActivation.cpp */,
    18171823                        );
    18181824                        path = runtime;
     
    23152321                                9714AF60122F32070092D9F5 /* URLString.h in Headers */,
    23162322                                90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */,
     2323                                A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */,
    23172324                        );
    23182325                        runOnlyForDeploymentPostprocessing = 0;
     
    24082415                        buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
    24092416                        compatibilityVersion = "Xcode 2.4";
    2410                         developmentRegion = English;
    24112417                        hasScannedForEncodings = 1;
    24122418                        knownRegions = (
     
    27702776                                9714AF5E122F32070092D9F5 /* ParsedURL.cpp in Sources */,
    27712777                                90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */,
     2778                                A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */,
    27722779                        );
    27732780                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r69045 r69516  
    518518            break;
    519519        }
     520        case op_convert_this_strict: {
     521            int r0 = (++it)->u.operand;
     522            printf("[%4d] convert_this_strict %s\n", location, registerName(exec, r0).data());
     523            break;
     524        }
    520525        case op_new_object: {
    521526            int r0 = (++it)->u.operand;
     
    13721377    , m_usesEval(ownerExecutable->usesEval())
    13731378    , m_isNumericCompareFunction(false)
     1379    , m_isStrictMode(ownerExecutable->isStrictMode())
    13741380    , m_codeType(codeType)
    13751381    , m_source(sourceProvider)
     
    15581564    }
    15591565
    1560     m_exceptionInfo = m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this);
     1566    m_exceptionInfo = m_ownerExecutable->reparseExceptionInfo(scopeChain, this);
    15611567    return m_exceptionInfo;
    15621568}
  • trunk/JavaScriptCore/bytecode/CodeBlock.h

    r69045 r69516  
    298298#endif
    299299
     300        bool isStrictMode() const { return m_isStrictMode; }
     301
    300302        inline bool isKnownNotImmediate(int index)
    301303        {
     
    565567        bool m_usesEval;
    566568        bool m_isNumericCompareFunction;
     569        bool m_isStrictMode;
    567570
    568571        CodeType m_codeType;
  • trunk/JavaScriptCore/bytecode/EvalCodeCache.h

    r65177 r69516  
    4444    class EvalCodeCache {
    4545    public:
    46         PassRefPtr<EvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
     46        PassRefPtr<EvalExecutable> get(ExecState* exec, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
    4747        {
    4848            RefPtr<EvalExecutable> evalExecutable;
    4949
    50             if (evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
     50            if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
    5151                evalExecutable = m_cacheMap.get(evalSource.impl());
    5252
    5353            if (!evalExecutable) {
    54                 evalExecutable = EvalExecutable::create(exec, makeSource(evalSource));
     54                evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext);
    5555                exceptionValue = evalExecutable->compile(exec, scopeChain);
    5656                if (exceptionValue)
    5757                    return 0;
    5858
    59                 if (evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
     59                if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
    6060                    m_cacheMap.set(evalSource.impl(), evalExecutable);
    6161            }
  • trunk/JavaScriptCore/bytecode/Opcode.h

    r69045 r69516  
    4646        macro(op_get_callee, 2) \
    4747        macro(op_convert_this, 2) \
     48        macro(op_convert_this_strict, 2) \
    4849        \
    4950        macro(op_new_object, 2) \
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r69045 r69516  
    344344        emitInitLazyRegister(argumentsRegister);
    345345        emitInitLazyRegister(unmodifiedArgumentsRegister);
     346       
     347        if (m_codeBlock->isStrictMode()) {
     348            emitOpcode(op_create_arguments);
     349            instructions().append(argumentsRegister->index());
     350        }
    346351
    347352        // The debugger currently retrieves the arguments object from an activation rather than pulling
     
    443448        instructions().append(funcProto->index());
    444449    } else if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
    445         emitOpcode(op_convert_this);
     450        if (codeBlock->isStrictMode())
     451            emitOpcode(op_convert_this_strict);
     452        else
     453            emitOpcode(op_convert_this);
    446454        instructions().append(m_thisRegister.index());
    447455    }
     
    15581566    ASSERT(m_codeBlock->usesArguments());
    15591567
     1568    // If we're in strict mode we tear off the arguments on function
     1569    // entry, so there's no need to check if we need to create them
     1570    // now
     1571    if (m_codeBlock->isStrictMode())
     1572        return;
     1573
    15601574    emitOpcode(op_create_arguments);
    15611575    instructions().append(m_codeBlock->argumentsRegister());
     
    16751689        instructions().append(m_activationRegister->index());
    16761690        instructions().append(m_codeBlock->argumentsRegister());
    1677     } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
     1691    } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1
     1692               && !m_codeBlock->isStrictMode()) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
    16781693        emitOpcode(op_tear_off_arguments);
    16791694        instructions().append(m_codeBlock->argumentsRegister());
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r69045 r69516  
    420420
    421421        bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
     422       
     423        bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
    422424
    423425    private:
     
    500502        PassRefPtr<FunctionExecutable> makeFunction(ExecState* exec, FunctionBodyNode* body)
    501503        {
    502             return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
     504            return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
    503505        }
    504506
    505507        PassRefPtr<FunctionExecutable> makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
    506508        {
    507             return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
     509            return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
    508510        }
    509511
  • trunk/JavaScriptCore/debugger/Debugger.cpp

    r54464 r69516  
    102102    CallFrame* globalCallFrame = globalObject->globalExec();
    103103
    104     RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script));
     104    RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script), false);
    105105    JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain());
    106106    if (error)
  • trunk/JavaScriptCore/debugger/DebuggerCallFrame.cpp

    r65286 r69516  
    8989        return JSValue();
    9090
    91     RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script));
     91    RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode());
    9292    JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain());
    9393    if (error)
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r69096 r69516  
    6060#include "Register.h"
    6161#include "SamplingTool.h"
     62#include "StrictEvalActivation.h"
    6263#include <limits.h>
    6364#include <stdio.h>
     
    390391    if (callFrame->hadException())
    391392        return JSValue();
    392 
    393     LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
    394     if (JSValue parsedObject = preparser.tryLiteralParse())
    395         return parsedObject;
     393   
     394    CodeBlock* codeBlock = callFrame->codeBlock();
     395    if (!codeBlock->isStrictMode()) {
     396        // FIXME: We can use the preparser in strict mode, we just need additional logic
     397        // to prevent duplicates.
     398        LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
     399        if (JSValue parsedObject = preparser.tryLiteralParse())
     400            return parsedObject;
     401    }
    396402
    397403    ScopeChainNode* scopeChain = callFrame->scopeChain();
    398     CodeBlock* codeBlock = callFrame->codeBlock();
    399     RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
     404    RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
    400405
    401406    JSValue result = jsUndefined();
     
    562567        JSActivation* activation = asActivation(scopeChain->object);
    563568        activation->copyRegisters();
    564         if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
    565             asArguments(arguments)->setActivation(activation);
    566     } else if (oldCodeBlock->usesArguments()) {
     569        if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
     570            if (!oldCodeBlock->isStrictMode())
     571                asArguments(arguments)->setActivation(activation);
     572        }
     573    } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
    567574        if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
    568575            asArguments(arguments)->copyRegisters();
     
    10621069    EvalCodeBlock* codeBlock = &eval->generatedBytecode();
    10631070
    1064     JSVariableObject* variableObject;
     1071    JSObject* variableObject;
    10651072    for (ScopeChainNode* node = scopeChain; ; node = node->next) {
    10661073        ASSERT(node);
     
    10731080    unsigned numVariables = codeBlock->numVariables();
    10741081    int numFunctions = codeBlock->numberOfFunctionDecls();
     1082    bool pushedScope = false;
    10751083    if (numVariables || numFunctions) {
     1084        if (codeBlock->isStrictMode()) {
     1085            variableObject = new (callFrame) StrictEvalActivation(callFrame);
     1086            scopeChain = scopeChain->push(variableObject);
     1087            pushedScope = true;
     1088        }
    10761089        // Scope for BatchedTransitionOptimizer
    10771090        BatchedTransitionOptimizer optimizer(variableObject);
     
    10961109    if (!m_registerFile.grow(newEnd)) {
    10971110        *exception = createStackOverflowError(callFrame);
     1111        if (pushedScope)
     1112            scopeChain->pop();
    10981113        return jsNull();
    10991114    }
     
    11381153
    11391154    m_registerFile.shrink(oldEnd);
     1155    if (pushedScope)
     1156        scopeChain->pop();
    11401157    return result;
    11411158}
     
    29652982        JSValue baseValue = callFrame->r(base).jsValue();
    29662983        Identifier& ident = codeBlock->identifier(property);
    2967         PutPropertySlot slot;
     2984        PutPropertySlot slot(codeBlock->isStrictMode());
    29682985        if (direct) {
    29692986            baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
     
    30813098        JSValue baseValue = callFrame->r(base).jsValue();
    30823099        Identifier& ident = codeBlock->identifier(property);
    3083         PutPropertySlot slot;
     3100        PutPropertySlot slot(codeBlock->isStrictMode());
    30843101        if (direct) {
    30853102            baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
     
    31063123        JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
    31073124        Identifier& ident = codeBlock->identifier(property);
    3108         JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
     3125        bool result = baseObj->deleteProperty(callFrame, ident);
     3126        if (!result && codeBlock->isStrictMode()) {
     3127            exceptionValue = createTypeError(callFrame, "Unable to delete property.");
     3128            goto vm_throw;
     3129        }
    31093130        CHECK_FOR_EXCEPTION();
    3110         callFrame->r(dst) = result;
     3131        callFrame->r(dst) = jsBoolean(result);
    31113132        vPC += OPCODE_LENGTH(op_del_by_id);
    31123133        NEXT_INSTRUCTION();
     
    32613282            Identifier property(callFrame, subscript.toString(callFrame));
    32623283            if (!globalData->exception) { // Don't put to an object if toString threw an exception.
    3263                 PutPropertySlot slot;
     3284                PutPropertySlot slot(codeBlock->isStrictMode());
    32643285                baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
    32653286            }
     
    32853306
    32863307        JSValue subscript = callFrame->r(property).jsValue();
    3287         JSValue result;
     3308        bool result;
    32883309        uint32_t i;
    32893310        if (subscript.getUInt32(i))
    3290             result = jsBoolean(baseObj->deleteProperty(callFrame, i));
     3311            result = baseObj->deleteProperty(callFrame, i);
    32913312        else {
    32923313            CHECK_FOR_EXCEPTION();
    32933314            Identifier property(callFrame, subscript.toString(callFrame));
    32943315            CHECK_FOR_EXCEPTION();
    3295             result = jsBoolean(baseObj->deleteProperty(callFrame, property));
    3296         }
    3297 
     3316            result = baseObj->deleteProperty(callFrame, property);
     3317        }
     3318        if (!result && codeBlock->isStrictMode()) {
     3319            exceptionValue = createTypeError(callFrame, "Unable to delete property.");
     3320            goto vm_throw;
     3321        }
    32983322        CHECK_FOR_EXCEPTION();
    3299         callFrame->r(dst) = result;
     3323        callFrame->r(dst) = jsBoolean(result);
    33003324        vPC += OPCODE_LENGTH(op_del_by_val);
    33013325        NEXT_INSTRUCTION();
     
    40374061            asArguments(argumentsValue)->copyRegisters();
    40384062
     4063        if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src2)).jsValue()) {
     4064            if (!codeBlock->isStrictMode())
     4065                asArguments(arguments)->setActivation(activation);
     4066        }
     4067
    40394068        vPC += OPCODE_LENGTH(op_tear_off_activation);
    40404069        NEXT_INSTRUCTION();
     
    42244253
    42254254        vPC += OPCODE_LENGTH(op_convert_this);
     4255        NEXT_INSTRUCTION();
     4256    }
     4257    DEFINE_OPCODE(op_convert_this_strict) {
     4258        /* convert_this_strict this(r)
     4259         
     4260         Takes the value in the 'this' register, and converts it to
     4261         its "this" form if (and only if) "this" is an object with a
     4262         custom this conversion
     4263         
     4264         This opcode should only be used at the beginning of a code
     4265         block.
     4266         */
     4267       
     4268        int thisRegister = vPC[1].u.operand;
     4269        JSValue thisVal = callFrame->r(thisRegister).jsValue();
     4270        if (thisVal.isObject() && thisVal.needsThisConversion())
     4271            callFrame->r(thisRegister) = JSValue(thisVal.toStrictThisObject(callFrame));
     4272       
     4273        vPC += OPCODE_LENGTH(op_convert_this_strict);
    42264274        NEXT_INSTRUCTION();
    42274275    }
  • trunk/JavaScriptCore/jit/JIT.cpp

    r69045 r69516  
    226226        DEFINE_OP(op_create_this)
    227227        DEFINE_OP(op_convert_this)
     228        DEFINE_OP(op_convert_this_strict)
    228229        DEFINE_OP(op_init_lazy_reg)
    229230        DEFINE_OP(op_create_arguments)
     
    397398        DEFINE_SLOWCASE_OP(op_construct)
    398399        DEFINE_SLOWCASE_OP(op_convert_this)
     400        DEFINE_SLOWCASE_OP(op_convert_this_strict)
    399401#if !USE(JSVALUE32)
    400402        DEFINE_SLOWCASE_OP(op_div)
  • trunk/JavaScriptCore/jit/JIT.h

    r69045 r69516  
    739739        void emit_op_create_this(Instruction*);
    740740        void emit_op_convert_this(Instruction*);
     741        void emit_op_convert_this_strict(Instruction*);
    741742        void emit_op_create_arguments(Instruction*);
    742743        void emit_op_debug(Instruction*);
     
    846847        void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
    847848        void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
     849        void emitSlow_op_convert_this_strict(Instruction*, Vector<SlowCaseEntry>::iterator&);
    848850        void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
    849851        void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
  • trunk/JavaScriptCore/jit/JITOpcodes.cpp

    r69045 r69516  
    896896    if (!m_codeBlock->isKnownNotImmediate(base))
    897897        isNotObject.append(emitJumpIfNotJSCell(regT0));
    898     if (base != m_codeBlock->thisRegister()) {
     898    if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
    899899        loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
    900900        isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
     
    12561256}
    12571257
     1258void JIT::emit_op_convert_this_strict(Instruction* currentInstruction)
     1259{
     1260    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
     1261    Jump notNull = branchTestPtr(NonZero, regT0);
     1262    move(ImmPtr(JSValue::encode(jsNull())), regT0);
     1263    emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
     1264    Jump setThis = jump();
     1265    notNull.link(this);
     1266    Jump isImmediate = emitJumpIfNotJSCell(regT0);
     1267    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
     1268    Jump notAnObject = branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType));
     1269    addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
     1270    isImmediate.link(this);
     1271    notAnObject.link(this);
     1272    setThis.link(this);
     1273}
     1274
    12581275void JIT::emit_op_get_callee(Instruction* currentInstruction)
    12591276{
     
    13011318    linkSlowCase(iter);
    13021319    JITStubCall stubCall(this, cti_op_convert_this);
     1320    stubCall.addArgument(regT0);
     1321    stubCall.call(currentInstruction[1].u.operand);
     1322}
     1323
     1324void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1325{
     1326    linkSlowCase(iter);
     1327    JITStubCall stubCall(this, cti_op_convert_this_strict);
    13031328    stubCall.addArgument(regT0);
    13041329    stubCall.call(currentInstruction[1].u.operand);
  • trunk/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r69045 r69516  
    12401240    if (!m_codeBlock->isKnownNotImmediate(base))
    12411241        isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
    1242     if (base != m_codeBlock->thisRegister()) {
     1242    if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
    12431243        loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
    12441244        isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
     
    15551555}
    15561556
     1557void JIT::emit_op_convert_this_strict(Instruction* currentInstruction)
     1558{
     1559    unsigned thisRegister = currentInstruction[1].u.operand;
     1560   
     1561    emitLoad(thisRegister, regT1, regT0);
     1562   
     1563    Jump notNull = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag));
     1564    emitStore(thisRegister, jsNull());
     1565    Jump setThis = jump();
     1566    notNull.link(this);
     1567    Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
     1568    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
     1569    Jump notAnObject = branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType));
     1570    addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
     1571    isImmediate.link(this);
     1572    notAnObject.link(this);
     1573    setThis.link(this);
     1574    map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
     1575}
     1576
    15571577void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    15581578{
     
    15631583
    15641584    JITStubCall stubCall(this, cti_op_convert_this);
     1585    stubCall.addArgument(regT1, regT0);
     1586    stubCall.call(thisRegister);
     1587}
     1588
     1589void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1590{
     1591    unsigned thisRegister = currentInstruction[1].u.operand;
     1592   
     1593    linkSlowCase(iter);
     1594   
     1595    JITStubCall stubCall(this, cti_op_convert_this_strict);
    15651596    stubCall.addArgument(regT1, regT0);
    15661597    stubCall.call(thisRegister);
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r69045 r69516  
    10661066    } while (0)
    10671067#define VM_THROW_EXCEPTION_AT_END() \
    1068     returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
     1068    do {\
     1069        returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
     1070    } while (0)
    10691071
    10701072#define CHECK_FOR_EXCEPTION() \
     
    13021304}
    13031305
     1306DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict)
     1307{
     1308    STUB_INIT_STACK_FRAME(stackFrame);
     1309   
     1310    JSValue v1 = stackFrame.args[0].jsValue();
     1311    CallFrame* callFrame = stackFrame.callFrame;
     1312
     1313    JSValue result = v1.toStrictThisObject(callFrame);
     1314    CHECK_FOR_EXCEPTION_AT_END();
     1315    return JSValue::encode(result);
     1316}
     1317
    13041318DEFINE_STUB_FUNCTION(void, op_end)
    13051319{
     
    14051419    STUB_INIT_STACK_FRAME(stackFrame);
    14061420
    1407     PutPropertySlot slot;
     1421    PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
    14081422    stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
    14091423    CHECK_FOR_EXCEPTION_AT_END();
     
    14141428    STUB_INIT_STACK_FRAME(stackFrame);
    14151429   
    1416     PutPropertySlot slot;
     1430    PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
    14171431    stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
    14181432    CHECK_FOR_EXCEPTION_AT_END();
     
    14421456    Identifier& ident = stackFrame.args[1].identifier();
    14431457   
    1444     PutPropertySlot slot;
     1458    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
    14451459    stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    14461460   
     
    14611475    Identifier& ident = stackFrame.args[1].identifier();
    14621476   
    1463     PutPropertySlot slot;
     1477    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
    14641478    stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    14651479   
     
    14801494    CallFrame* callFrame = stackFrame.callFrame;
    14811495    Identifier& ident = stackFrame.args[1].identifier();
    1482 
    1483     PutPropertySlot slot;
     1496   
     1497    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
    14841498    stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    14851499
     
    14941508    Identifier& ident = stackFrame.args[1].identifier();
    14951509   
    1496     PutPropertySlot slot;
     1510    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
    14971511    stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    14981512   
     
    18811895    JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
    18821896
    1883     JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier()));
     1897    bool couldDelete = baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier());
     1898    JSValue result = jsBoolean(couldDelete);
     1899    if (!couldDelete && callFrame->codeBlock()->isStrictMode())
     1900        stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
     1901
    18841902    CHECK_FOR_EXCEPTION_AT_END();
    18851903    return JSValue::encode(result);
     
    22232241    JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
    22242242    activation->copyRegisters();
    2225     if (JSValue v = stackFrame.args[1].jsValue())
    2226         asArguments(v)->setActivation(activation);
     2243    if (JSValue v = stackFrame.args[1].jsValue()) {
     2244        if (!stackFrame.callFrame->codeBlock()->isStrictMode())
     2245            asArguments(v)->setActivation(activation);
     2246    }
    22272247}
    22282248
     
    25042524        Identifier property(callFrame, subscript.toString(callFrame));
    25052525        if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
    2506             PutPropertySlot slot;
     2526            PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
    25072527            baseValue.put(callFrame, property, value, slot);
    25082528        }
     
    25472567        Identifier property(callFrame, subscript.toString(callFrame));
    25482568        if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
    2549             PutPropertySlot slot;
     2569            PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
    25502570            baseValue.put(callFrame, property, value, slot);
    25512571        }
     
    35023522
    35033523    JSValue subscript = stackFrame.args[1].jsValue();
    3504     JSValue result;
     3524    bool result;
    35053525    uint32_t i;
    35063526    if (subscript.getUInt32(i))
    3507         result = jsBoolean(baseObj->deleteProperty(callFrame, i));
     3527        result = baseObj->deleteProperty(callFrame, i);
    35083528    else {
    35093529        CHECK_FOR_EXCEPTION();
    35103530        Identifier property(callFrame, subscript.toString(callFrame));
    35113531        CHECK_FOR_EXCEPTION();
    3512         result = jsBoolean(baseObj->deleteProperty(callFrame, property));
    3513     }
    3514 
    3515     CHECK_FOR_EXCEPTION_AT_END();
    3516     return JSValue::encode(result);
     3532        result = baseObj->deleteProperty(callFrame, property);
     3533    }
     3534
     3535    if (!result && callFrame->codeBlock()->isStrictMode())
     3536        stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
     3537
     3538    CHECK_FOR_EXCEPTION_AT_END();
     3539    return JSValue::encode(jsBoolean(result));
    35173540}
    35183541
  • trunk/JavaScriptCore/jit/JITStubs.h

    r67943 r69516  
    297297    EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION);
    298298    EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
     299    EncodedJSValue JIT_STUB cti_op_convert_this_strict(STUB_ARGS_DECLARATION);
    299300    EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
    300301    EncodedJSValue JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
  • trunk/JavaScriptCore/parser/ASTBuilder.h

    r67583 r69516  
    250250    }
    251251
    252     FunctionBodyNode* createFunctionBody()
     252    FunctionBodyNode* createFunctionBody(bool inStrictContext)
    253253    {
    254254        usesClosures();
    255         return FunctionBodyNode::create(m_globalData);
     255        return FunctionBodyNode::create(m_globalData, inStrictContext);
    256256    }
    257257   
     
    579579    const Identifier& getName(Property property) { return property->name(); }
    580580    PropertyNode::Type getType(Property property) { return property->type(); }
     581
     582    bool isResolve(ExpressionNode* expr) { return expr->isResolveNode(); }
     583
    581584private:
    582585    struct Scope {
  • trunk/JavaScriptCore/parser/JSParser.cpp

    r68288 r69516  
    3030using namespace JSC;
    3131
     32#include "CodeBlock.h"
    3233#include "JSGlobalData.h"
    3334#include "NodeInfo.h"
     
    4344#define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
    4445#define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
     46#define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
     47#define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
    4548#define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0)
    4649#define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0)
     
    6871class JSParser {
    6972public:
    70     JSParser(Lexer*, JSGlobalData*, FunctionParameters*, SourceProvider*);
    71     bool parseProgram();
     73    JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*);
     74    bool parseProgram(JSGlobalObject*);
    7275private:
    7376    struct AllowInOverride {
     
    9194        m_lastTokenEnd = m_token.m_info.endOffset;
    9295        m_lexer->setLastLineNumber(m_lastLine);
    93         m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType);
     96        m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType, strictMode());
    9497        m_tokenCount++;
    9598    }
     
    122125        return m_token.m_info.endOffset;
    123126    }
    124 
    125     template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
    126     template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&);
     127   
     128    void startLoop() { currentScope()->startLoop(); }
     129    void endLoop() { currentScope()->endLoop(); }
     130    void startSwitch() { currentScope()->startSwitch(); }
     131    void endSwitch() { currentScope()->endSwitch(); }
     132    void setStrictMode() { currentScope()->setStrictMode(); }
     133    bool strictMode() { return currentScope()->strictMode(); }
     134    bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
     135    bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
     136    bool breakIsValid() { return currentScope()->breakIsValid(); }
     137    void pushLabel(const Identifier* label) { currentScope()->pushLabel(label); }
     138    void popLabel() { currentScope()->popLabel(); }
     139    bool hasLabel(const Identifier* label) { return currentScope()->hasLabel(label); }
     140
     141    enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
     142    template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
     143    template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive);
    127144    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
    128145    template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
     
    200217    int m_nonLHSCount;
    201218    bool m_syntaxAlreadyValidated;
     219    int m_statementDepth;
     220    int m_nonTrivialExpressionCount;
     221    const Identifier* m_lastIdentifier;
     222
     223    struct DepthManager {
     224        DepthManager(int* depth)
     225            : m_originalDepth(*depth)
     226            , m_depth(depth)
     227        {
     228        }
     229       
     230        ~DepthManager()
     231        {
     232            *m_depth = m_originalDepth;
     233        }
     234       
     235    private:
     236        int m_originalDepth;
     237        int* m_depth;
     238    };
    202239
    203240    struct Scope {
    204         Scope()
    205             : m_usesEval(false)
     241        Scope(JSGlobalData* globalData, bool isFunction, bool strictMode)
     242            : m_globalData(globalData)
     243            , m_usesEval(false)
    206244            , m_needsFullActivation(false)
    207245            , m_allowsNewDecls(true)
     246            , m_strictMode(strictMode)
     247            , m_isFunction(isFunction)
     248            , m_isValidStrictMode(true)
     249            , m_loopDepth(0)
     250            , m_switchDepth(0)
     251            , m_labels(0)
    208252        {
    209253        }
    210254       
    211         void declareVariable(const Identifier* ident)
     255        void startSwitch() { m_switchDepth++; }
     256        void endSwitch() { m_switchDepth--; }
     257        void startLoop() { m_loopDepth++; }
     258        void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; }
     259        bool inLoop() { return !!m_loopDepth; }
     260        bool breakIsValid() { return m_loopDepth || m_switchDepth; }
     261
     262        void pushLabel(const Identifier* label)
    212263        {
     264            if (!m_labels)
     265                m_labels = new LabelStack;
     266            m_labels->append(label->impl());
     267        }
     268
     269        void popLabel()
     270        {
     271            ASSERT(m_labels);
     272            ASSERT(m_labels->size());
     273            m_labels->removeLast();
     274        }
     275
     276        bool hasLabel(const Identifier* label)
     277        {
     278            if (!m_labels)
     279                return false;
     280            for (int i = m_labels->size(); i > 0; i--) {
     281                if (m_labels->at(i - 1) == label->impl())
     282                    return true;
     283            }
     284            return false;
     285        }
     286
     287        void setIsFunction() { m_isFunction = true; }
     288        bool isFunction() { return m_isFunction; }
     289       
     290        bool declareVariable(const Identifier* ident)
     291        {
     292            bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident;
     293            m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
    213294            m_declaredVariables.add(ident->ustring().impl());
     295            return isValidStrictMode;
     296        }
     297       
     298        void declareWrite(const Identifier* ident)
     299        {
     300            ASSERT(m_strictMode);
     301            m_writtenVariables.add(ident->impl());
     302        }
     303       
     304        bool deleteProperty(const Identifier* ident)
     305        {
     306            if (m_declaredVariables.contains(ident->impl()))
     307                return false;
     308            m_deletedVariables.add(ident->impl());
     309            return true;
    214310        }
    215311       
     
    217313        bool allowsNewDecls() const { return m_allowsNewDecls; }
    218314
     315        bool declareParameter(const Identifier* ident)
     316        {
     317            bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident;
     318            m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
     319            return isValidStrictMode;
     320        }
     321       
    219322        void useVariable(const Identifier* ident, bool isEval)
    220323        {
     
    223326        }
    224327       
    225         void needsFullActivation() { m_needsFullActivation = true; }
     328        void setNeedsFullActivation() { m_needsFullActivation = true; }
    226329       
    227         void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
     330        bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
    228331        {
    229332            if (nestedScope->m_usesEval)
     
    237340                    m_closedVariables.add(*ptr);
    238341            }
     342            if (nestedScope->m_writtenVariables.size()) {
     343                IdentifierSet::iterator end = nestedScope->m_writtenVariables.end();
     344                for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) {
     345                    if (nestedScope->m_declaredVariables.contains(*ptr))
     346                        continue;
     347                    m_writtenVariables.add(*ptr);
     348                }
     349            }
     350            if (nestedScope->m_deletedVariables.size()) {
     351                IdentifierSet::iterator end = nestedScope->m_deletedVariables.end();
     352                for (IdentifierSet::iterator ptr = nestedScope->m_deletedVariables.begin(); ptr != end; ++ptr) {
     353                    if (nestedScope->m_declaredVariables.contains(*ptr))
     354                        return false;
     355                    if (m_declaredVariables.contains(*ptr))
     356                        return false;
     357                    m_deletedVariables.add(*ptr);
     358                }
     359            }
     360            return true;
     361        }
     362
     363        void getUncapturedWrittenVariables(IdentifierSet& writtenVariables)
     364        {
     365            IdentifierSet::iterator end = m_writtenVariables.end();
     366            for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) {
     367                if (!m_declaredVariables.contains(*ptr))
     368                    writtenVariables.add(*ptr);
     369            }
     370        }
     371
     372        bool getDeletedVariables(IdentifierSet& deletedVariables)
     373        {
     374            IdentifierSet::iterator end = m_deletedVariables.end();
     375            for (IdentifierSet::iterator ptr = m_deletedVariables.begin(); ptr != end; ++ptr) {
     376                if (m_declaredVariables.contains(*ptr))
     377                    return false;
     378            }
     379            deletedVariables.swap(m_deletedVariables);
     380            return true;
    239381        }
    240382
     
    251393            }
    252394        }
     395        void setStrictMode() { m_strictMode = true; }
     396        bool strictMode() const { return m_strictMode; }
     397        bool isValidStrictMode() const { return m_isValidStrictMode; }
     398
    253399    private:
    254         bool m_usesEval;
    255         bool m_needsFullActivation;
    256         bool m_allowsNewDecls;
     400        JSGlobalData* m_globalData;
     401        bool m_usesEval : 1;
     402        bool m_needsFullActivation : 1;
     403        bool m_allowsNewDecls : 1;
     404        bool m_strictMode : 1;
     405        bool m_isFunction : 1;
     406        bool m_isValidStrictMode : 1;
     407        int m_loopDepth;
     408        int m_switchDepth;
     409        typedef Vector<StringImpl*, 2> LabelStack;
     410        LabelStack* m_labels;
    257411        IdentifierSet m_declaredVariables;
    258412        IdentifierSet m_usedVariables;
    259413        IdentifierSet m_closedVariables;
     414        IdentifierSet m_writtenVariables;
     415        IdentifierSet m_deletedVariables;
    260416    };
    261417   
     
    282438    ScopeRef pushScope()
    283439    {
    284         m_scopeStack.append(Scope());
     440        bool isFunction = false;
     441        bool isStrict = false;
     442        if (!m_scopeStack.isEmpty()) {
     443            isStrict = m_scopeStack.last().strictMode();
     444            isFunction = m_scopeStack.last().isFunction();
     445        }
     446        m_scopeStack.append(Scope(m_globalData, isFunction, isStrict));
    285447        return currentScope();
    286448    }
    287449
    288     void popScope(ScopeRef scope, bool shouldTrackClosedVariables)
     450    bool popScope(ScopeRef scope, bool shouldTrackClosedVariables)
    289451    {
    290452        ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
    291453        ASSERT(m_scopeStack.size() > 1);
    292         m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
     454        bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
    293455        m_scopeStack.removeLast();
     456        return result;
    294457    }
    295458   
    296     void declareVariable(const Identifier* ident)
     459    bool declareVariable(const Identifier* ident)
    297460    {
    298461        unsigned i = m_scopeStack.size() - 1;
     
    302465            ASSERT(i < m_scopeStack.size());
    303466        }
    304         m_scopeStack[i].declareVariable(ident);
    305     }
    306 
     467        return m_scopeStack[i].declareVariable(ident);
     468    }
     469   
     470    void declareWrite(const Identifier* ident)
     471    {
     472        if (!m_syntaxAlreadyValidated)
     473            m_scopeStack.last().declareWrite(ident);
     474    }
     475
     476    bool deleteProperty(const Identifier* ident)
     477    {
     478        if (!m_syntaxAlreadyValidated)
     479            return m_scopeStack.last().deleteProperty(ident);
     480        return true;
     481    }
     482   
    307483    ScopeStack m_scopeStack;
    308484};
    309485
    310 int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, const SourceCode* source)
    311 {
    312     JSParser parser(globalData->lexer, globalData, parameters, source->provider());
    313     return parser.parseProgram();
    314 }
    315 
    316 JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, SourceProvider* provider)
     486int jsParse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
     487{
     488    JSParser parser(lexicalGlobalObject->globalData()->lexer, lexicalGlobalObject->globalData(), parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider());
     489    return parser.parseProgram(lexicalGlobalObject);
     490}
     491
     492JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider)
    317493    : m_lexer(lexer)
    318494    , m_endAddress(0)
     
    326502    , m_nonLHSCount(0)
    327503    , m_syntaxAlreadyValidated(provider->isValid())
     504    , m_statementDepth(0)
     505    , m_nonTrivialExpressionCount(0)
     506    , m_lastIdentifier(0)
    328507{
    329508    m_endAddress = wtfThreadData().approximatedStackStart() - kMaxParserStackUsage;
    330     next();
    331     m_lexer->setLastLineNumber(tokenLine());
    332509    ScopeRef scope = pushScope();
     510    if (isFunction)
     511        scope->setIsFunction();
     512    if (inStrictContext)
     513        scope->setStrictMode();
    333514    if (parameters) {
    334515        for (unsigned i = 0; i < parameters->size(); i++)
    335             scope->declareVariable(&parameters->at(i));
    336     }
    337 }
    338 
    339 bool JSParser::parseProgram()
     516            scope->declareParameter(&parameters->at(i));
     517    }
     518    next();
     519    m_lexer->setLastLineNumber(tokenLine());
     520}
     521
     522bool JSParser::parseProgram(JSGlobalObject* lexicalGlobalObject)
    340523{
    341524    ASTBuilder context(m_globalData, m_lexer);
     525    if (m_lexer->isReparsing())
     526        m_statementDepth--;
    342527    ScopeRef scope = currentScope();
    343     SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context);
     528    SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
    344529    if (!sourceElements || !consume(EOFTOK))
    345530        return true;
     531    if (!m_syntaxAlreadyValidated) {
     532        IdentifierSet writtenVariables;
     533        scope->getUncapturedWrittenVariables(writtenVariables);
     534        IdentifierSet::const_iterator end = writtenVariables.end();
     535        for (IdentifierSet::const_iterator ptr = writtenVariables.begin(); ptr != end; ++ptr) {
     536            PropertySlot slot(lexicalGlobalObject);
     537            if (!lexicalGlobalObject->getPropertySlot(lexicalGlobalObject->globalExec(), Identifier(m_globalData, *ptr), slot))
     538                return true;
     539        }
     540        IdentifierSet deletedVariables;
     541        if (!scope->getDeletedVariables(deletedVariables))
     542            return true;
     543        end = deletedVariables.end();
     544        SymbolTable& globalEnvRecord = lexicalGlobalObject->symbolTable();
     545        for (IdentifierSet::const_iterator ptr = deletedVariables.begin(); ptr != end; ++ptr) {
     546            if (!globalEnvRecord.get(*ptr).isNull())
     547                return true;
     548        }
     549    }
    346550    IdentifierSet capturedVariables;
    347551    scope->getCapturedVariables(capturedVariables);
    348     m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(),
    349                                           m_lastLine, context.numConstants(), capturedVariables);
     552    m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features() | (scope->strictMode() ? StrictModeFeature : 0),
     553                                           m_lastLine, context.numConstants(), capturedVariables);
    350554    return false;
    351555}
     
    356560}
    357561
    358 template <class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
     562template <JSParser::SourceElementsMode mode, class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
    359563{
    360564    TreeSourceElements sourceElements = context.createSourceElements();
    361     while (TreeStatement statement = parseStatement(context))
     565    bool seenNonDirective = false;
     566    const Identifier* directive = 0;
     567    unsigned startOffset = m_token.m_info.startOffset;
     568    bool hasSetStrict = false;
     569    while (TreeStatement statement = parseStatement(context, directive)) {
     570        if (mode == CheckForStrictMode && !seenNonDirective) {
     571            if (directive) {
     572                if (!hasSetStrict && m_globalData->propertyNames->useStrictIdentifier == *directive) {
     573                    setStrictMode();
     574                    hasSetStrict = true;
     575                    failIfFalse(isValidStrictMode());
     576                    m_lexer->setOffset(startOffset);
     577                    next();
     578                    failIfTrue(m_error);
     579                    continue;
     580                }
     581            } else
     582                seenNonDirective = true;
     583        }
    362584        context.appendStatement(sourceElements, statement);
     585    }
    363586
    364587    if (m_error)
     
    400623    int startLine = tokenLine();
    401624    next();
    402     TreeStatement statement = parseStatement(context);
     625    const Identifier* unused = 0;
     626    startLoop();
     627    TreeStatement statement = parseStatement(context, unused);
     628    endLoop();
    403629    failIfFalse(statement);
    404630    int endLine = tokenLine();
     
    423649    int endLine = tokenLine();
    424650    consumeOrFail(CLOSEPAREN);
    425     TreeStatement statement = parseStatement(context);
     651    const Identifier* unused = 0;
     652    startLoop();
     653    TreeStatement statement = parseStatement(context, unused);
     654    endLoop();
    426655    failIfFalse(statement);
    427656    return context.createWhileStatement(expr, statement, startLine, endLine);
     
    442671        next();
    443672        bool hasInitializer = match(EQUAL);
    444         declareVariable(name);
     673        failIfFalseIfStrict(declareVariable(name));
    445674        context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
    446675        if (hasInitializer) {
     
    466695template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationList(TreeBuilder& context)
    467696{
     697    failIfTrue(strictMode());
    468698    TreeConstDeclList constDecls = 0;
    469699    TreeConstDeclList tail = 0;
     
    533763        consumeOrFail(CLOSEPAREN);
    534764
    535         TreeStatement statement = parseStatement(context);
     765        const Identifier* unused = 0;
     766        startLoop();
     767        TreeStatement statement = parseStatement(context, unused);
     768        endLoop();
    536769        failIfFalse(statement);
    537770
     
    567800        int endLine = tokenLine();
    568801        consumeOrFail(CLOSEPAREN);
    569         TreeStatement statement = parseStatement(context);
     802        const Identifier* unused = 0;
     803        startLoop();
     804        TreeStatement statement = parseStatement(context, unused);
     805        endLoop();
    570806        failIfFalse(statement);
    571807        return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
     
    580816    int endLine = tokenLine();
    581817    consumeOrFail(CLOSEPAREN);
    582     TreeStatement statement = parseStatement(context);
     818    const Identifier* unused = 0;
     819    startLoop();
     820    TreeStatement statement = parseStatement(context, unused);
     821    endLoop();
    583822    failIfFalse(statement);
    584823   
     
    595834    next();
    596835
    597     if (autoSemiColon())
     836    if (autoSemiColon()) {
     837        failIfFalseIfStrict(breakIsValid());
    598838        return context.createBreakStatement(startCol, endCol, startLine, endLine);
     839    }
    599840    matchOrFail(IDENT);
    600841    const Identifier* ident = m_token.m_data.ident;
     842    failIfFalseIfStrict(hasLabel(ident));
    601843    endCol = tokenEnd();
    602844    endLine = tokenLine();
     
    615857    next();
    616858
    617     if (autoSemiColon())
     859    if (autoSemiColon()) {
     860        failIfFalseIfStrict(breakIsValid());
    618861        return context.createContinueStatement(startCol, endCol, startLine, endLine);
     862    }
    619863    matchOrFail(IDENT);
    620864    const Identifier* ident = m_token.m_data.ident;
     865    failIfFalseIfStrict(hasLabel(ident));
    621866    endCol = tokenEnd();
    622867    endLine = tokenLine();
     
    629874{
    630875    ASSERT(match(RETURN));
     876    failIfFalseIfStrict(currentScope()->isFunction());
    631877    int startLine = tokenLine();
    632878    int endLine = startLine;
     
    669915{
    670916    ASSERT(match(WITH));
    671     currentScope()->needsFullActivation();
     917    failIfTrue(strictMode());
     918    currentScope()->setNeedsFullActivation();
    672919    int startLine = tokenLine();
    673920    next();
     
    680927    int endLine = tokenLine();
    681928    consumeOrFail(CLOSEPAREN);
    682    
    683     TreeStatement statement = parseStatement(context);
     929    const Identifier* unused = 0;
     930    TreeStatement statement = parseStatement(context, unused);
    684931    failIfFalse(statement);
    685932
     
    698945    consumeOrFail(CLOSEPAREN);
    699946    consumeOrFail(OPENBRACE);
    700 
     947    startSwitch();
    701948    TreeClauseList firstClauses = parseSwitchClauses(context);
    702949    failIfTrue(m_error);
     
    707954    TreeClauseList secondClauses = parseSwitchClauses(context);
    708955    failIfTrue(m_error);
     956    endSwitch();
    709957    consumeOrFail(CLOSEBRACE);
    710958
     
    721969    failIfFalse(condition);
    722970    consumeOrFail(COLON);
    723     TreeSourceElements statements = parseSourceElements(context);
     971    TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
    724972    failIfFalse(statements);
    725973    TreeClause clause = context.createClause(condition, statements);
     
    732980        failIfFalse(condition);
    733981        consumeOrFail(COLON);
    734         TreeSourceElements statements = parseSourceElements(context);
     982        TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
    735983        failIfFalse(statements);
    736984        clause = context.createClause(condition, statements);
     
    746994    next();
    747995    consumeOrFail(COLON);
    748     TreeSourceElements statements = parseSourceElements(context);
     996    TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
    749997    failIfFalse(statements);
    750998    return context.createClause(0, statements);
     
    7681016
    7691017    if (match(CATCH)) {
    770         currentScope()->needsFullActivation();
     1018        currentScope()->setNeedsFullActivation();
    7711019        next();
    7721020        consumeOrFail(OPENPAREN);
     
    7751023        next();
    7761024        ScopeRef catchScope = pushScope();
    777         catchScope->declareVariable(ident);
     1025        failIfFalseIfStrict(catchScope->declareVariable(ident));
    7781026        catchScope->preventNewDecls();
    7791027        consumeOrFail(CLOSEPAREN);
     
    7831031        failIfFalse(catchBlock);
    7841032        catchHasEval = initialEvalCount != context.evalCount();
    785         popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
     1033        failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
    7861034    }
    7871035
     
    8171065        return context.createBlockStatement(0, start, m_lastLine);
    8181066    }
    819     TreeSourceElements subtree = parseSourceElements(context);
     1067    TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
    8201068    failIfFalse(subtree);
    8211069    matchOrFail(CLOSEBRACE);
     
    8241072}
    8251073
    826 template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context)
    827 {
     1074template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context, const Identifier*& directive)
     1075{
     1076    DepthManager statementDepth(&m_statementDepth);
     1077    m_statementDepth++;
     1078    directive = 0;
     1079    int nonTrivialExpressionCount = 0;
    8281080    failIfStackOverflow();
    8291081    switch (m_token.m_type) {
     
    8351087        return parseConstDeclaration(context);
    8361088    case FUNCTION:
     1089        failIfFalseIfStrict(m_statementDepth == 1);
    8371090        return parseFunctionDeclaration(context);
    8381091    case SEMICOLON:
     
    8711124    case IDENT:
    8721125        return parseExpressionOrLabelStatement(context);
     1126    case STRING:
     1127        directive = m_token.m_data.ident;
     1128        nonTrivialExpressionCount = m_nonTrivialExpressionCount;
    8731129    default:
    874         return parseExpressionStatement(context);
     1130        TreeStatement exprStatement = parseExpressionStatement(context);
     1131        if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
     1132            directive = 0;
     1133        return exprStatement;
    8751134    }
    8761135}
     
    8801139    matchOrFail(IDENT);
    8811140    usesArguments = m_globalData->propertyNames->arguments == *m_token.m_data.ident;
    882     declareVariable(m_token.m_data.ident);
     1141    failIfFalseIfStrict(declareParameter(m_token.m_data.ident));
    8831142    TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident);
    8841143    TreeFormalParameterList tail = list;
     
    8881147        matchOrFail(IDENT);
    8891148        const Identifier* ident = m_token.m_data.ident;
    890         declareVariable(ident);
     1149        usesArguments |= m_globalData->propertyNames->arguments == *m_token.m_data.ident;
     1150        failIfFalseIfStrict(declareParameter(ident));
    8911151        next();
    8921152        usesArguments = usesArguments || m_globalData->propertyNames->arguments == *ident;
     
    8991159{
    9001160    if (match(CLOSEBRACE))
    901         return context.createFunctionBody();
     1161        return context.createFunctionBody(strictMode());
     1162    DepthManager statementDepth(&m_statementDepth);
     1163    m_statementDepth = 0;
    9021164    typename TreeBuilder::FunctionBodyBuilder bodyBuilder(m_globalData, m_lexer);
    903     failIfFalse(parseSourceElements(bodyBuilder));
    904     return context.createFunctionBody();
     1165    failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
     1166    return context.createFunctionBody(strictMode());
    9051167}
    9061168
     
    9081170{
    9091171    ScopeRef functionScope = pushScope();
     1172    functionScope->setIsFunction();
    9101173    if (match(IDENT)) {
    9111174        name = m_token.m_data.ident;
    9121175        next();
    9131176        if (!nameIsInContainingScope)
    914             functionScope->declareVariable(name);
     1177            failIfFalseIfStrict(functionScope->declareVariable(name));
    9151178    } else if (requirements == FunctionNeedsName)
    9161179        return false;
     
    9321195    if (usesArguments)
    9331196        context.setUsesArguments(body);
    934     popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
     1197    if (functionScope->strictMode() && name) {
     1198        failIfTrue(m_globalData->propertyNames->arguments == *name);
     1199        failIfTrue(m_globalData->propertyNames->eval == *name);
     1200    }
     1201    failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
    9351202    matchOrFail(CLOSEBRACE);
    9361203    closeBracePos = m_token.m_data.intValue;
     
    9511218    failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
    9521219    failIfFalse(name);
    953     declareVariable(name);
     1220    failIfFalseIfStrict(declareVariable(name));
    9541221    return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
    9551222}
     
    9741241    int end = tokenEnd();
    9751242    consumeOrFail(COLON);
    976     TreeStatement statement = parseStatement(context);
     1243    const Identifier* unused = 0;
     1244    if (strictMode() && !m_syntaxAlreadyValidated)
     1245        pushLabel(ident);
     1246    TreeStatement statement = parseStatement(context, unused);
     1247    if (strictMode() && !m_syntaxAlreadyValidated)
     1248        popLabel();
    9771249    failIfFalse(statement);
    9781250    return context.createLabelStatement(ident, statement, start, end);
     
    10021274    consumeOrFail(CLOSEPAREN);
    10031275
    1004     TreeStatement trueBlock = parseStatement(context);
     1276    const Identifier* unused = 0;
     1277    TreeStatement trueBlock = parseStatement(context, unused);
    10051278    failIfFalse(trueBlock);
    10061279
     
    10151288        next();
    10161289        if (!match(IF)) {
    1017             TreeStatement block = parseStatement(context);
     1290            const Identifier* unused = 0;
     1291            TreeStatement block = parseStatement(context, unused);
    10181292            failIfFalse(block);
    10191293            statementStack.append(block);
     
    10301304        int innerEnd = tokenLine();
    10311305        consumeOrFail(CLOSEPAREN);
    1032        
    1033         TreeStatement innerTrueBlock = parseStatement(context);
     1306        const Identifier* unused = 0;
     1307        TreeStatement innerTrueBlock = parseStatement(context, unused);
    10341308        failIfFalse(innerTrueBlock);     
    10351309        exprStack.append(innerCondition);
     
    10711345        return node;
    10721346    next();
     1347    m_nonTrivialExpressionCount++;
    10731348    m_nonLHSCount++;
    10741349    TreeExpression right = parseAssignmentExpression(context);
     
    11161391            goto end;
    11171392        }
     1393        m_nonTrivialExpressionCount++;
    11181394        hadAssignment = true;
    11191395        context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op);
     
    11211397        m_assignmentCount++;
    11221398        next();
     1399        if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
     1400            failIfTrueIfStrict(m_globalData->propertyNames->eval == *m_lastIdentifier);
     1401            declareWrite(m_lastIdentifier);
     1402            m_lastIdentifier = 0;
     1403        }
    11231404        lhs = parseConditionalExpression(context);
    11241405        failIfFalse(lhs);
     
    11451426    if (!match(QUESTION))
    11461427        return cond;
     1428    m_nonTrivialExpressionCount++;
    11471429    m_nonLHSCount++;
    11481430    next();
     
    11821464        if (!precedence)
    11831465            break;
     1466        m_nonTrivialExpressionCount++;
    11841467        m_nonLHSCount++;
    11851468        int operatorToken = m_token.m_type;
     
    11971480        context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
    11981481    }
    1199 
    12001482    while (operatorStackDepth) {
    12011483        ASSERT(operandStackDepth > 1);
     
    13281610            std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).impl(), context.getType(property));
    13291611            if (!propertyEntryIter.second) {
     1612                failIfTrue(strictMode());
    13301613                if ((context.getType(property) & propertyEntryIter.first->second) != PropertyNode::Constant) {
    13311614                    // Can't have multiple getters or setters with the same name, nor can we define
     
    13901673    switch (m_token.m_type) {
    13911674    case OPENBRACE:
     1675        if (strictMode())
     1676            return parseStrictObjectLiteral(context);
    13921677        return parseObjectLiteral(context);
    13931678    case OPENBRACKET:
     
    14111696        next();
    14121697        currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident);
     1698        m_lastIdentifier = ident;
    14131699        return context.createResolve(ident, start);
    14141700    }
     
    14861772        newCount++;
    14871773    }
     1774
    14881775    if (match(FUNCTION)) {
    14891776        const Identifier* name = &m_globalData->propertyNames->nullIdentifier;
     
    15031790        switch (m_token.m_type) {
    15041791        case OPENBRACKET: {
     1792            m_nonTrivialExpressionCount++;
    15051793            int expressionEnd = lastTokenEnd();
    15061794            next();
     
    15161804        }
    15171805        case OPENPAREN: {
     1806            m_nonTrivialExpressionCount++;
    15181807            if (newCount) {
    15191808                newCount--;
     
    15361825        }
    15371826        case DOT: {
     1827            m_nonTrivialExpressionCount++;
    15381828            int expressionEnd = lastTokenEnd();
    15391829            next(Lexer::IgnoreReservedWords);
     
    15571847    AllowInOverride allowInOverride(this);
    15581848    int tokenStackDepth = 0;
     1849    bool modifiesExpr = false;
     1850    bool requiresLExpr = false;
    15591851    while (isUnaryOp(m_token.m_type)) {
     1852        if (strictMode()) {
     1853            switch (m_token.m_type) {
     1854            case PLUSPLUS:
     1855            case MINUSMINUS:
     1856            case AUTOPLUSPLUS:
     1857            case AUTOMINUSMINUS:
     1858                failIfTrue(requiresLExpr);
     1859                modifiesExpr = true;
     1860                requiresLExpr = true;
     1861                break;
     1862            case DELETETOKEN:
     1863                failIfTrue(requiresLExpr);
     1864                requiresLExpr = true;
     1865                break;
     1866            default:
     1867                failIfTrue(requiresLExpr);
     1868                break;
     1869            }
     1870        }
    15601871        m_nonLHSCount++;
    15611872        context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart());
    15621873        next();
     1874        m_nonTrivialExpressionCount++;
    15631875    }
    15641876    int subExprStart = tokenStart();
    15651877    TreeExpression expr = parseMemberExpression(context);
    15661878    failIfFalse(expr);
     1879    bool isEval = false;
     1880    if (strictMode() && !m_syntaxAlreadyValidated) {
     1881        if (context.isResolve(expr))
     1882            isEval = m_globalData->propertyNames->eval == *m_lastIdentifier;
     1883    }
     1884    failIfTrueIfStrict(isEval && modifiesExpr);
    15671885    switch (m_token.m_type) {
    15681886    case PLUSPLUS:
     1887        m_nonTrivialExpressionCount++;
    15691888        m_nonLHSCount++;
    15701889        expr = context.makePostfixNode(expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
    15711890        m_assignmentCount++;
     1891        failIfTrueIfStrict(isEval);
     1892        failIfTrueIfStrict(requiresLExpr);
    15721893        next();
    15731894        break;
    15741895    case MINUSMINUS:
     1896        m_nonTrivialExpressionCount++;
    15751897        m_nonLHSCount++;
    15761898        expr = context.makePostfixNode(expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
    15771899        m_assignmentCount++;
     1900        failIfTrueIfStrict(isEval);
     1901        failIfTrueIfStrict(requiresLExpr);
    15781902        next();
    15791903        break;
     
    15841908    int end = lastTokenEnd();
    15851909
    1586     if (!TreeBuilder::CreatesAST)
     1910    if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
    15871911        return expr;
    15881912
     
    16181942            break;
    16191943        case DELETETOKEN:
     1944            if (strictMode() && context.isResolve(expr))
     1945                failIfFalse(deleteProperty(m_lastIdentifier));
    16201946            expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
    16211947            break;
  • trunk/JavaScriptCore/parser/JSParser.h

    r67769 r69516  
    2929namespace JSC {
    3030
     31class ExecState;
    3132class FunctionParameters;
    3233class Identifier;
    33 class JSGlobalData;
     34class JSGlobalObject;
    3435class SourceCode;
    3536
     
    156157};
    157158
    158 int jsParse(JSGlobalData*, FunctionParameters*, const SourceCode*);
     159enum JSParserStrictness { JSParseNormal, JSParseStrict };
     160enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
     161
     162int jsParse(JSGlobalObject*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*);
    159163}
    160164#endif // JSParser_h
  • trunk/JavaScriptCore/parser/Lexer.cpp

    r67066 r69516  
    454454}
    455455
    456 ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp)
     456ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp, bool strictMode)
    457457{
    458458    int stringQuoteCharacter = m_current;
     
    495495            } else if (isASCIIOctalDigit(m_current)) {
    496496                // Octal character sequences
     497                if (strictMode)
     498                    return false;
    497499                int character1 = m_current;
    498500                shift();
     
    697699}
    698700
    699 JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType lexType)
     701JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType lexType, bool strictMode)
    700702{
    701703    ASSERT(!m_error);
     
    977979            record8('0');
    978980            if (isASCIIOctalDigit(m_current)) {
    979                 if (parseOctal(lvalp->doubleValue))
     981                if (parseOctal(lvalp->doubleValue)) {
     982                    if (strictMode)
     983                        goto returnError;
    980984                    token = NUMBER;
     985                }
    981986            }
    982987        }
     
    10071012        break;
    10081013    case CharacterQuote:
    1009         if (UNLIKELY(!parseString(lvalp)))
     1014        if (UNLIKELY(!parseString(lvalp, strictMode)))
    10101015            goto returnError;
    10111016        shift();
  • trunk/JavaScriptCore/parser/Lexer.h

    r66962 r69516  
    4949        void setCode(const SourceCode&, ParserArena&);
    5050        void setIsReparsing() { m_isReparsing = true; }
     51        bool isReparsing() const { return m_isReparsing; }
    5152
    5253        // Functions for the parser itself.
    5354        enum LexType { IdentifyReservedWords, IgnoreReservedWords };
    54         JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType);
     55        JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType, bool strictMode);
    5556        int lineNumber() const { return m_lineNumber; }
    5657        void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
     
    9697
    9798        ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, LexType);
    98         ALWAYS_INLINE bool parseString(JSTokenData* lvalp);
     99        ALWAYS_INLINE bool parseString(JSTokenData* lvalp, bool strictMode);
    99100        ALWAYS_INLINE void parseHex(double& returnValue);
    100101        ALWAYS_INLINE bool parseOctal(double& returnValue);
  • trunk/JavaScriptCore/parser/Nodes.cpp

    r67583 r69516  
    9090// ------------------------------ ScopeNode -----------------------------
    9191
    92 ScopeNode::ScopeNode(JSGlobalData* globalData)
     92ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext)
    9393    : StatementNode(globalData)
    9494    , ParserArenaRefCounted(globalData)
    95     , m_features(NoFeatures)
     95    , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
    9696{
    9797}
     
    155155}
    156156
    157 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
    158     : ScopeNode(globalData)
     157inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, bool inStrictContext)
     158    : ScopeNode(globalData, inStrictContext)
    159159{
    160160}
     
    178178}
    179179
    180 FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
     180FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, bool inStrictContext)
    181181{
    182     return new FunctionBodyNode(globalData);
     182    return new FunctionBodyNode(globalData, inStrictContext);
    183183}
    184184
  • trunk/JavaScriptCore/parser/Nodes.h

    r68281 r69516  
    5858    const CodeFeatures CatchFeature = 1 << 5;
    5959    const CodeFeatures ThisFeature = 1 << 6;
     60    const CodeFeatures StrictModeFeature = 1 << 7;
    6061    const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature;
    6162
     
    13941395        typedef DeclarationStacks::FunctionStack FunctionStack;
    13951396
    1396         ScopeNode(JSGlobalData*);
     1397        ScopeNode(JSGlobalData*, bool inStrictContext);
    13971398        ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
    13981399
     
    14111412        bool usesEval() const { return m_features & EvalFeature; }
    14121413        bool usesArguments() const { return m_features & ArgumentsFeature; }
     1414        bool isStrictMode() const { return m_features & StrictModeFeature; }
    14131415        void setUsesArguments() { m_features |= ArgumentsFeature; }
    14141416        bool usesThis() const { return m_features & ThisFeature; }
     
    14451447    class ProgramNode : public ScopeNode {
    14461448    public:
     1449        static const bool isFunctionNode = false;
    14471450        static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
    14481451
     
    14571460    class EvalNode : public ScopeNode {
    14581461    public:
     1462        static const bool isFunctionNode = false;
    14591463        static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
    14601464
     
    14771481    class FunctionBodyNode : public ScopeNode {
    14781482    public:
    1479         static FunctionBodyNode* create(JSGlobalData*);
     1483        static const bool isFunctionNode = true;
     1484        static FunctionBodyNode* create(JSGlobalData*, bool isStrictMode);
    14801485        static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
    14811486
     
    14931498
    14941499    private:
    1495         FunctionBodyNode(JSGlobalData*);
     1500        FunctionBodyNode(JSGlobalData*, bool inStrictContext);
    14961501        FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
    14971502
  • trunk/JavaScriptCore/parser/Parser.cpp

    r67769 r69516  
    3636namespace JSC {
    3737
    38 void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, int* errLine, UString* errMsg)
     38void Parser::parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg)
    3939{
     40    ASSERT(lexicalGlobalObject);
    4041    m_sourceElements = 0;
    4142
     
    5152    *errMsg = UString();
    5253
    53     Lexer& lexer = *globalData->lexer;
     54    Lexer& lexer = *lexicalGlobalObject->globalData()->lexer;
    5455    lexer.setCode(*m_source, m_arena);
    5556
    56     int parseError = jsParse(globalData, parameters, m_source);
     57    int parseError = jsParse(lexicalGlobalObject, parameters, strictness, mode, m_source);
    5758    int lineNumber = lexer.lineNumber();
    5859    bool lexError = lexer.sawError();
  • trunk/JavaScriptCore/parser/Parser.h

    r67769 r69516  
    4949    public:
    5050        template <class ParsedNode>
    51         PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, FunctionParameters*, JSObject** exception);
     51        PassRefPtr<ParsedNode> parse(JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, FunctionParameters*, JSParserStrictness strictness, JSObject** exception);
    5252
    5353        void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*,
     
    5858
    5959    private:
    60         void parse(JSGlobalData*, FunctionParameters*, int* errLine, UString* errMsg);
     60        void parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg);
    6161
    6262        // Used to determine type of error to report.
     
    7676
    7777    template <class ParsedNode>
    78     PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, FunctionParameters* parameters, JSObject** exception)
     78    PassRefPtr<ParsedNode> Parser::parse(JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSObject** exception)
    7979    {
     80        ASSERT(lexicalGlobalObject);
    8081        ASSERT(exception && !*exception);
    8182        int errLine;
     
    8485        m_source = &source;
    8586        if (ParsedNode::scopeIsFunction)
    86             globalData->lexer->setIsReparsing();
    87         parse(globalData, parameters, &errLine, &errMsg);
     87            lexicalGlobalObject->globalData()->lexer->setIsReparsing();
     88        parse(lexicalGlobalObject, parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg);
    8889
    8990        RefPtr<ParsedNode> result;
    9091        if (m_sourceElements) {
    91             result = ParsedNode::create(globalData,
     92            result = ParsedNode::create(lexicalGlobalObject->globalData(),
    9293                m_sourceElements,
    9394                m_varDeclarations ? &m_varDeclarations->data : 0,
     
    108109                *exception = createStackOverflowError(lexicalGlobalObject);
    109110            else
    110                 *exception = addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, source);
     111                *exception = addErrorInfo(lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, source);
    111112        }
    112113
  • trunk/JavaScriptCore/parser/SyntaxChecker.h

    r67583 r69516  
    3131public:
    3232    SyntaxChecker(JSGlobalData* , Lexer*)
     33        : m_topBinaryExpr(0)
    3334    {
    3435    }
    3536
    3637    typedef SyntaxChecker FunctionBodyBuilder;
    37 
    38     typedef int Expression;
     38    enum { NoneExpr = 0,
     39        ResolveEvalExpr, ResolveExpr, NumberExpr, StringExpr,
     40        ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
     41        FunctionExpr, BracketExpr, DotExpr, CallExpr,
     42        NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
     43        ConditionalExpr, AssignmentExpr, TypeofExpr,
     44        DeleteExpr, ArrayLiteralExpr };
     45    typedef int ExpressionType;
     46
     47    typedef ExpressionType Expression;
    3948    typedef int SourceElements;
    4049    typedef int Arguments;
    41     typedef int Comma;
     50    typedef ExpressionType Comma;
    4251    struct Property {
    4352        ALWAYS_INLINE Property(void* = 0)
     
    7483
    7584    int createSourceElements() { return 1; }
    76     int makeFunctionCallNode(int, int, int, int, int) { return 1; }
    77     void appendToComma(int, int) { }
    78     int createCommaExpr(int, int) { return 1; }
    79     int makeAssignNode(int, Operator, int, bool, bool, int, int, int) { return 1; }
    80     int makePrefixNode(int, Operator, int, int, int) { return 1; }
    81     int makePostfixNode(int, Operator, int, int, int) { return 1; }
    82     int makeTypeOfNode(int) { return 1; }
    83     int makeDeleteNode(int, int, int, int) { return 1; }
    84     int makeNegateNode(int) { return 1; }
    85     int makeBitwiseNotNode(int) { return 1; }
    86     int createLogicalNot(int) { return 1; }
    87     int createUnaryPlus(int) { return 1; }
    88     int createVoid(int) { return 1; }
    89     int thisExpr() { return 1; }
    90     int createResolve(const Identifier*, int) { return 1; }
    91     int createObjectLiteral() { return 1; }
    92     int createObjectLiteral(int) { return 1; }
    93     int createArray(int) { return 1; }
    94     int createArray(int, int) { return 1; }
    95     int createNumberExpr(double) { return 1; }
    96     int createString(const Identifier*) { return 1; }
    97     int createBoolean(bool) { return 1; }
    98     int createNull() { return 1; }
    99     int createBracketAccess(int, int, bool, int, int, int) { return 1; }
    100     int createDotAccess(int, const Identifier&, int, int, int) { return 1; }
    101     int createRegex(const Identifier&, const Identifier&, int) { return 1; }
    102     int createNewExpr(int, int, int, int, int) { return 1; }
    103     int createNewExpr(int, int, int) { return 1; }
    104     int createConditionalExpr(int, int, int) { return 1; }
    105     int createAssignResolve(const Identifier&, int, bool, int, int, int) { return 1; }
    106     int createFunctionExpr(const Identifier*, int, int, int, int, int, int) { return 1; }
    107     int createFunctionBody() { return 1; }
     85    ExpressionType makeFunctionCallNode(int, int, int, int, int) { return CallExpr; }
     86    void appendToComma(ExpressionType& base, ExpressionType right) { base = right; }
     87    ExpressionType createCommaExpr(ExpressionType, ExpressionType right) { return right; }
     88    ExpressionType makeAssignNode(ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; }
     89    ExpressionType makePrefixNode(ExpressionType, Operator, int, int, int) { return PreExpr; }
     90    ExpressionType makePostfixNode(ExpressionType, Operator, int, int, int) { return PostExpr; }
     91    ExpressionType makeTypeOfNode(ExpressionType) { return TypeofExpr; }
     92    ExpressionType makeDeleteNode(ExpressionType, int, int, int) { return DeleteExpr; }
     93    ExpressionType makeNegateNode(ExpressionType) { return UnaryExpr; }
     94    ExpressionType makeBitwiseNotNode(ExpressionType) { return UnaryExpr; }
     95    ExpressionType createLogicalNot(ExpressionType) { return UnaryExpr; }
     96    ExpressionType createUnaryPlus(ExpressionType) { return UnaryExpr; }
     97    ExpressionType createVoid(ExpressionType) { return UnaryExpr; }
     98    ExpressionType thisExpr() { return ThisExpr; }
     99    ExpressionType createResolve(const Identifier*, int) { return ResolveExpr; }
     100    ExpressionType createObjectLiteral() { return ObjectLiteralExpr; }
     101    ExpressionType createObjectLiteral(int) { return ObjectLiteralExpr; }
     102    ExpressionType createArray(int) { return ArrayLiteralExpr; }
     103    ExpressionType createArray(int, int) { return ArrayLiteralExpr; }
     104    ExpressionType createNumberExpr(double) { return NumberExpr; }
     105    ExpressionType createString(const Identifier*) { return StringExpr; }
     106    ExpressionType createBoolean(bool) { return BoolExpr; }
     107    ExpressionType createNull() { return NullExpr; }
     108    ExpressionType createBracketAccess(ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; }
     109    ExpressionType createDotAccess(ExpressionType, const Identifier&, int, int, int) { return DotExpr; }
     110    ExpressionType createRegex(const Identifier&, const Identifier&, int) { return RegExpExpr; }
     111    ExpressionType createNewExpr(ExpressionType, int, int, int, int) { return NewExpr; }
     112    ExpressionType createNewExpr(ExpressionType, int, int) { return NewExpr; }
     113    ExpressionType createConditionalExpr(ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
     114    ExpressionType createAssignResolve(const Identifier&, ExpressionType, bool, int, int, int) { return AssignmentExpr; }
     115    ExpressionType createFunctionExpr(const Identifier*, int, int, int, int, int, int) { return FunctionExpr; }
     116    int createFunctionBody(bool) { return 1; }
    108117    int createArguments() { return 1; }
    109118    int createArguments(int) { return 1; }
     
    170179    int combineCommaNodes(int, int) { return 1; }
    171180    int evalCount() const { return 0; }
    172     void appendBinaryExpressionInfo(int& operandStackDepth, int, int, int, int, bool) { operandStackDepth++; }
     181    void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool)
     182    {
     183        if (!m_topBinaryExpr)
     184            m_topBinaryExpr = expr;
     185        else
     186            m_topBinaryExpr = BinaryExpr;
     187        operandStackDepth++;
     188    }
    173189   
    174190    // Logic to handle datastructures used during parsing of binary expressions
    175191    void operatorStackPop(int& operatorStackDepth) { operatorStackDepth--; }
    176192    bool operatorStackHasHigherPrecedence(int&, int) { return true; }
    177     BinaryOperand getFromOperandStack(int) { return 1; }
     193    BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; }
    178194    void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; }
    179195    void appendBinaryOperation(int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; }
    180196    void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; }
    181     int popOperandStack(int&) { return 1; }
    182    
    183     void appendUnaryToken(int&, int, int) { }
    184     int unaryTokenStackLastType(int&) { ASSERT_NOT_REACHED(); return 1; }
    185     int unaryTokenStackLastStart(int&) { ASSERT_NOT_REACHED(); return 1; }
    186     void unaryTokenStackRemoveLast(int&) { }
     197    int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; }
     198   
     199    void appendUnaryToken(int& stackDepth, int tok, int) { stackDepth = 1; m_topUnaryToken = tok; }
     200    int unaryTokenStackLastType(int&) { return m_topUnaryToken; }
     201    int unaryTokenStackLastStart(int&) { return 0; }
     202    void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; }
    187203   
    188204    void assignmentStackAppend(int, int, int, int, int, Operator) { }
     
    190206    const Identifier& getName(const Property& property) { ASSERT(property.name); return *property.name; }
    191207    PropertyNode::Type getType(const Property& property) { return property.type; }
     208    bool isResolve(ExpressionType expr) { return expr == ResolveExpr || expr == ResolveEvalExpr; }
     209   
     210private:
     211    int m_topBinaryExpr;
     212    int m_topUnaryToken;
    192213};
    193214
  • trunk/JavaScriptCore/runtime/Arguments.cpp

    r65588 r69516  
    154154    return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot);
    155155}
     156   
     157void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
     158{
     159    if (d->overrodeCaller)
     160        return;
     161
     162    d->overrodeCaller = true;
     163    PropertyDescriptor descriptor;
     164    JSValue thrower = createTypeErrorFunction(exec, "Unable to access caller of strict mode function");
     165    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
     166    defineOwnProperty(exec, exec->propertyNames().caller, descriptor, false);
     167}
     168
     169void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
     170{
     171    if (d->overrodeCallee)
     172        return;
     173   
     174    d->overrodeCallee = true;
     175    PropertyDescriptor descriptor;
     176    JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function");
     177    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
     178    defineOwnProperty(exec, exec->propertyNames().callee, descriptor, false);
     179}
    156180
    157181bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
     
    173197
    174198    if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
    175         slot.setValue(d->callee);
    176         return true;
    177     }
     199        if (!d->isStrictMode) {
     200            slot.setValue(d->callee);
     201            return true;
     202        }
     203        createStrictModeCalleeIfNecessary(exec);
     204    }
     205
     206    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
     207        createStrictModeCallerIfNecessary(exec);
    178208
    179209    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
     
    198228   
    199229    if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
    200         descriptor.setDescriptor(d->callee, DontEnum);
    201         return true;
    202     }
     230        if (!d->isStrictMode) {
     231            descriptor.setDescriptor(d->callee, DontEnum);
     232            return true;
     233        }
     234        createStrictModeCalleeIfNecessary(exec);
     235    }
     236
     237    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
     238        createStrictModeCallerIfNecessary(exec);
    203239   
    204240    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     
    250286
    251287    if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
    252         d->overrodeCallee = true;
    253         putDirect(propertyName, value, DontEnum);
    254         return;
    255     }
     288        if (!d->isStrictMode) {
     289            d->overrodeCallee = true;
     290            putDirect(propertyName, value, DontEnum);
     291            return;
     292        }
     293        createStrictModeCalleeIfNecessary(exec);
     294    }
     295
     296    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
     297        createStrictModeCallerIfNecessary(exec);
    256298
    257299    JSObject::put(exec, propertyName, value, slot);
     
    295337
    296338    if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
    297         d->overrodeCallee = true;
    298         return true;
    299     }
     339        if (!d->isStrictMode) {
     340            d->overrodeCallee = true;
     341            return true;
     342        }
     343        createStrictModeCalleeIfNecessary(exec);
     344    }
     345   
     346    if (propertyName == exec->propertyNames().caller && !d->isStrictMode)
     347        createStrictModeCallerIfNecessary(exec);
    300348
    301349    return JSObject::deleteProperty(exec, propertyName);
  • trunk/JavaScriptCore/runtime/Arguments.h

    r68171 r69516  
    5151        bool overrodeLength : 1;
    5252        bool overrodeCallee : 1;
     53        bool overrodeCaller : 1;
     54        bool isStrictMode : 1;
    5355    };
    5456
     
    106108        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
    107109        virtual bool deleteProperty(ExecState*, unsigned propertyName);
     110        void createStrictModeCallerIfNecessary(ExecState*);
     111        void createStrictModeCalleeIfNecessary(ExecState*);
    108112
    109113        virtual const ClassInfo* classInfo() const { return &info; }
     
    173177        d->overrodeLength = false;
    174178        d->overrodeCallee = false;
     179        d->overrodeCaller = false;
     180        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
     181        if (d->isStrictMode)
     182            copyRegisters();
    175183    }
    176184
     
    202210        d->overrodeLength = false;
    203211        d->overrodeCallee = false;
     212        d->overrodeCaller = false;
     213        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
     214        if (d->isStrictMode)
     215            copyRegisters();
    204216    }
    205217
  • trunk/JavaScriptCore/runtime/CommonIdentifiers.cpp

    r55751 r69516  
    3333    , underscoreProto(globalData, "__proto__")
    3434    , thisIdentifier(globalData, "this")
     35    , useStrictIdentifier(globalData, "use strict")
    3536    JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
    3637{
  • trunk/JavaScriptCore/runtime/CommonIdentifiers.h

    r55751 r69516  
    9595        const Identifier underscoreProto;
    9696        const Identifier thisIdentifier;
     97        const Identifier useStrictIdentifier;
    9798
    9899#define JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name;
  • trunk/JavaScriptCore/runtime/Error.cpp

    r60762 r69516  
    196196}
    197197
     198class StrictModeTypeErrorFunction : public InternalFunction {
     199public:
     200    StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& message)
     201        : InternalFunction(&exec->globalData(), globalObject, structure, exec->globalData().propertyNames->emptyIdentifier)
     202        , m_message(message)
     203    {
     204    }
     205   
     206    static EncodedJSValue JSC_HOST_CALL constructThrowTypeError(ExecState* exec)
     207    {
     208        throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message);
     209        return JSValue::encode(jsNull());
     210    }
     211   
     212    ConstructType getConstructData(ConstructData& constructData)
     213    {
     214        constructData.native.function = constructThrowTypeError;
     215        return ConstructTypeHost;
     216    }
     217   
     218    static EncodedJSValue JSC_HOST_CALL callThrowTypeError(ExecState* exec)
     219    {
     220        throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message);
     221        return JSValue::encode(jsNull());
     222    }
     223
     224    CallType getCallData(CallData& callData)
     225    {
     226        callData.native.function = callThrowTypeError;
     227        return CallTypeHost;
     228    }
     229
     230private:
     231    UString m_message;
     232};
     233
     234COMPILE_ASSERT(sizeof(StrictModeTypeErrorFunction) <= sizeof(CollectorCell), sizeof_StrictModeTypeErrorFunction_must_be_less_than_CollectorCell);
     235
     236JSValue createTypeErrorFunction(ExecState* exec, const UString& message)
     237{
     238    return new (exec) StrictModeTypeErrorFunction(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->internalFunctionStructure(), message);
     239}
     240
    198241} // namespace JSC
  • trunk/JavaScriptCore/runtime/Error.h

    r60762 r69516  
    7474    inline EncodedJSValue throwVMTypeError(ExecState* exec) { return JSValue::encode(throwTypeError(exec)); }
    7575
     76    JSValue createTypeErrorFunction(ExecState* exec, const UString& message);
     77   
    7678} // namespace JSC
    7779
  • trunk/JavaScriptCore/runtime/Executable.cpp

    r68171 r69516  
    4646}
    4747
    48 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source)
    49     : ScriptExecutable(exec, source)
     48EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
     49    : ScriptExecutable(exec, source, inStrictContext)
    5050{
    5151}
     
    5656
    5757ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
    58     : ScriptExecutable(exec, source)
     58    : ScriptExecutable(exec, source, false)
    5959{
    6060}
     
    6464}
    6565
    66 FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
    67     : ScriptExecutable(globalData, source)
     66FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
     67    : ScriptExecutable(globalData, source, inStrictContext)
    6868    , m_numCapturedVariables(0)
    6969    , m_forceUsesArguments(forceUsesArguments)
     
    7676}
    7777
    78 FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
    79     : ScriptExecutable(exec, source)
     78FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
     79    : ScriptExecutable(exec, source, inStrictContext)
    8080    , m_numCapturedVariables(0)
    8181    , m_forceUsesArguments(forceUsesArguments)
     
    9797    JSGlobalData* globalData = &exec->globalData();
    9898    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    99     RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception);
     99    RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
    100100    if (!evalNode) {
    101101        ASSERT(exception);
     
    132132    JSGlobalData* globalData = &exec->globalData();
    133133    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    134     RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception);
     134    RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, JSParseNormal, &exception);
    135135    if (programNode)
    136136        return 0;
     
    146146    JSGlobalData* globalData = &exec->globalData();
    147147    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    148     RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, &exception);
     148    RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
    149149    if (!programNode) {
    150150        ASSERT(exception);
     
    179179    JSObject* exception = 0;
    180180    JSGlobalData* globalData = scopeChainNode->globalData;
    181     RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception);
     181    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
    182182    if (!body) {
    183183        ASSERT(exception);
     
    220220    JSObject* exception = 0;
    221221    JSGlobalData* globalData = scopeChainNode->globalData;
    222     RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), &exception);
     222    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
    223223    if (!body) {
    224224        ASSERT(exception);
     
    265265}
    266266
    267 PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
    268 {
    269     JSObject* exception = 0;
    270     RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, m_parameters.get(), &exception);
     267PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
     268{
     269    JSObject* exception = 0;
     270    JSGlobalData* globalData = scopeChainNode->globalData;
     271    RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(scopeChainNode->globalObject, 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
    271272    if (!newFunctionBody)
    272273        return PassOwnPtr<ExceptionInfo>();
     274    ASSERT(newFunctionBody->isStrictMode() == isStrictMode());
    273275    if (m_forceUsesArguments)
    274276        newFunctionBody->setUsesArguments();
     
    299301}
    300302
    301 PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
    302 {
    303     JSObject* exception = 0;
    304     RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, 0, &exception);
     303PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
     304{
     305    JSObject* exception = 0;
     306    JSGlobalData* globalData = scopeChainNode->globalData;
     307    RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(scopeChainNode->globalObject, 0, 0, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
     308    ASSERT(newEvalBody->isStrictMode() == isStrictMode());
    305309    if (!newEvalBody)
    306310        return PassOwnPtr<ExceptionInfo>();
     
    342346{
    343347    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    344     RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, 0, exception);
     348    RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception);
    345349    if (!program) {
    346350        ASSERT(*exception);
     
    358362    ASSERT(body);
    359363
    360     return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
     364    return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), false, body->lineNo(), body->lastLine());
    361365}
    362366
     
    373377}
    374378
    375 PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*)
     379PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(ScopeChainNode*, CodeBlock*)
    376380{
    377381    // CodeBlocks for program code are transient and therefore do not gain from from throwing out their exception information.
  • trunk/JavaScriptCore/runtime/Executable.h

    r68171 r69516  
    139139    class ScriptExecutable : public ExecutableBase {
    140140    public:
    141         ScriptExecutable(JSGlobalData* globalData, const SourceCode& source)
     141        ScriptExecutable(JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext)
    142142            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
    143143            , m_source(source)
    144             , m_features(0)
     144            , m_features(isInStrictContext ? StrictModeFeature : 0)
    145145        {
    146146#if ENABLE(CODEBLOCK_SAMPLING)
     
    153153        }
    154154
    155         ScriptExecutable(ExecState* exec, const SourceCode& source)
     155        ScriptExecutable(ExecState* exec, const SourceCode& source, bool isInStrictContext)
    156156            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
    157157            , m_source(source)
    158             , m_features(0)
     158            , m_features(isInStrictContext ? StrictModeFeature : 0)
    159159        {
    160160#if ENABLE(CODEBLOCK_SAMPLING)
     
    176176        bool usesArguments() const { return m_features & ArgumentsFeature; }
    177177        bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
    178 
    179         virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;
     178        bool isStrictMode() const { return m_features & StrictModeFeature; }
     179
     180        virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*) = 0;
    180181
    181182    protected:
     
    215216        }
    216217
    217         static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
     218        static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return adoptRef(new EvalExecutable(exec, source, isInStrictContext)); }
    218219
    219220#if ENABLE(JIT)
     
    225226
    226227    private:
    227         EvalExecutable(ExecState*, const SourceCode&);
     228        EvalExecutable(ExecState*, const SourceCode&, bool);
    228229
    229230        JSObject* compileInternal(ExecState*, ScopeChainNode*);
    230231
    231         virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
     232        virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*);
    232233
    233234        OwnPtr<EvalCodeBlock> m_evalCodeBlock;
     
    272273        JSObject* compileInternal(ExecState*, ScopeChainNode*);
    273274
    274         virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
     275        virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*);
    275276
    276277        OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     
    280281        friend class JIT;
    281282    public:
    282         static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
    283         {
    284             return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine));
    285         }
    286 
    287         static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
    288         {
    289             return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine));
     283        static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
     284        {
     285            return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine));
     286        }
     287
     288        static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
     289        {
     290            return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine));
    290291        }
    291292
     
    359360
    360361    private:
    361         FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine);
    362         FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine);
     362        FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
     363        FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
    363364
    364365        JSObject* compileForCallInternal(ExecState*, ScopeChainNode*);
    365366        JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*);
    366367
    367         virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
     368        virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(ScopeChainNode*, CodeBlock*);
    368369
    369370        unsigned m_numCapturedVariables : 31;
  • trunk/JavaScriptCore/runtime/JSActivation.cpp

    r68171 r69516  
    187187}
    188188
     189JSValue JSActivation::toStrictThisObject(ExecState*) const
     190{
     191    return jsNull();
     192}
     193   
    189194bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
    190195{
  • trunk/JavaScriptCore/runtime/JSActivation.h

    r68171 r69516  
    6161
    6262        virtual JSObject* toThisObject(ExecState*) const;
     63        virtual JSValue toStrictThisObject(ExecState*) const;
    6364
    6465        void copyRegisters();
  • trunk/JavaScriptCore/runtime/JSFunction.cpp

    r65104 r69516  
    123123}
    124124
     125static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function";
     126static const char* StrictModeArgumentsAccessError = "Cannot access arguments property of a strict mode function";
     127
     128static void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message)
     129{
     130    JSValue thrower = createTypeErrorFunction(exec, message);
     131    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
     132}
     133
    125134const UString& JSFunction::name(ExecState* exec)
    126135{
     
    210219
    211220    if (propertyName == exec->propertyNames().arguments) {
     221        if (jsExecutable()->isStrictMode()) {
     222            throwTypeError(exec, "Can't access arguments object of a strict mode function");
     223            slot.setValue(jsNull());
     224            return true;
     225        }
     226   
    212227        slot.setCacheableCustom(this, argumentsGetter);
    213228        return true;
     
    220235
    221236    if (propertyName == exec->propertyNames().caller) {
     237        if (jsExecutable()->isStrictMode()) {
     238            throwTypeError(exec, StrictModeCallerAccessError);
     239            slot.setValue(jsNull());
     240            return true;
     241        }
    222242        slot.setCacheableCustom(this, callerGetter);
    223243        return true;
     
    227247}
    228248
    229     bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
    230     {
    231         if (isHostFunction())
    232             return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
    233        
    234         if (propertyName == exec->propertyNames().prototype) {
    235             PropertySlot slot;
    236             getOwnPropertySlot(exec, propertyName, slot);
    237             return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
    238         }
    239        
    240         if (propertyName == exec->propertyNames().arguments) {
     249bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     250{
     251    if (isHostFunction())
     252        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     253   
     254    if (propertyName == exec->propertyNames().prototype) {
     255        PropertySlot slot;
     256        getOwnPropertySlot(exec, propertyName, slot);
     257        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     258    }
     259   
     260    if (propertyName == exec->propertyNames().arguments) {
     261        if (jsExecutable()->isStrictMode())
     262            createDescriptorForThrowingProperty(exec, descriptor, StrictModeArgumentsAccessError);
     263        else
    241264            descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
    242             return true;
    243         }
    244        
    245         if (propertyName == exec->propertyNames().length) {
    246             descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
    247             return true;
    248         }
    249        
    250         if (propertyName == exec->propertyNames().caller) {
     265        return true;
     266    }
     267   
     268    if (propertyName == exec->propertyNames().length) {
     269        descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
     270        return true;
     271    }
     272   
     273    if (propertyName == exec->propertyNames().caller) {
     274        if (jsExecutable()->isStrictMode())
     275            createDescriptorForThrowingProperty(exec, descriptor, StrictModeCallerAccessError);
     276        else
    251277            descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
    252             return true;
    253         }
    254        
    255         return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
    256     }
    257    
     278        return true;
     279    }
     280   
     281    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     282}
     283
    258284void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
    259285{
     
    273299        return;
    274300    }
     301    if (jsExecutable()->isStrictMode()) {
     302        if (propertyName == exec->propertyNames().arguments) {
     303            throwTypeError(exec, StrictModeArgumentsAccessError);
     304            return;
     305        }
     306        if (propertyName == exec->propertyNames().caller) {
     307            throwTypeError(exec, StrictModeCallerAccessError);
     308            return;
     309        }
     310    }
    275311    if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
    276312        return;
  • trunk/JavaScriptCore/runtime/JSGlobalData.cpp

    r67146 r69516  
    5151#include "Parser.h"
    5252#include "RegExpCache.h"
     53#include "StrictEvalActivation.h"
    5354#include <wtf/WTFThreadData.h>
    5455#if ENABLE(REGEXP_TRACING)
     
    125126    , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull()))
    126127    , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
     128    , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull()))
    127129    , stringStructure(JSString::createStructure(jsNull()))
    128130    , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
  • trunk/JavaScriptCore/runtime/JSGlobalData.h

    r67146 r69516  
    146146        RefPtr<Structure> terminatedExecutionErrorStructure;
    147147        RefPtr<Structure> staticScopeStructure;
     148        RefPtr<Structure> strictEvalActivationStructure;
    148149        RefPtr<Structure> stringStructure;
    149150        RefPtr<Structure> notAnObjectErrorStubStructure;
  • trunk/JavaScriptCore/runtime/JSGlobalObject.cpp

    r66019 r69516  
    205205    d()->functionPrototype = new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created.
    206206    d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype);
     207    d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype);
    207208    NativeFunctionWrapper* callFunction = 0;
    208209    NativeFunctionWrapper* applyFunction = 0;
  • trunk/JavaScriptCore/runtime/JSGlobalObject.h

    r66019 r69516  
    149149            RefPtr<Structure> regExpStructure;
    150150            RefPtr<Structure> stringObjectStructure;
     151            RefPtr<Structure> internalFunctionStructure;
    151152
    152153            SymbolTable symbolTable;
     
    244245        Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
    245246        Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
     247        Structure* internalFunctionStructure() const { return d()->internalFunctionStructure.get(); }
    246248        Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
    247249        Structure* regExpStructure() const { return d()->regExpStructure.get(); }
  • trunk/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r65593 r69516  
    451451        return JSValue::encode(parsedObject);
    452452
    453     RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s));
     453    RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false);
    454454    JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
    455455    if (error)
  • trunk/JavaScriptCore/runtime/JSObject.cpp

    r60762 r69516  
    4444ASSERT_CLASS_FITS_IN_CELL(JSObject);
    4545
     46const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
     47
    4648static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
    4749{
     
    115117        prototype = obj->prototype();
    116118        if (prototype.isNull()) {
    117             putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
     119            if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
     120                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
    118121            return;
    119122        }
     
    122125    unsigned attributes;
    123126    JSCell* specificValue;
    124     if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly)
     127    if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) {
     128        if (slot.isStrictMode())
     129            throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
    125130        return;
     131    }
    126132
    127133    for (JSObject* obj = this; ; obj = asObject(prototype)) {
     
    152158    }
    153159
    154     putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
     160    if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
     161        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
    155162    return;
    156163}
     
    486493
    487494JSObject* JSObject::toThisObject(ExecState*) const
     495{
     496    return const_cast<JSObject*>(this);
     497}
     498
     499JSValue JSObject::toStrictThisObject(ExecState*) const
    488500{
    489501    return const_cast<JSObject*>(this);
     
    703715}
    704716
     717JSObject* throwTypeError(ExecState* exec, const UString& message)
     718{
     719    return throwError(exec, createTypeError(exec, message));
     720}
     721
    705722} // namespace JSC
  • trunk/JavaScriptCore/runtime/JSObject.h

    r64684 r69516  
    5656    struct HashTable;
    5757
     58    JSObject* throwTypeError(ExecState*, const UString&);
     59    extern const char* StrictModeReadonlyPropertyWriteError;
     60
    5861    // ECMA 262-3 8.6.1
    5962    // Property attributes
     
    141144
    142145        virtual JSObject* toThisObject(ExecState*) const;
     146        virtual JSValue toStrictThisObject(ExecState*) const;
    143147        virtual JSObject* unwrappedObject();
    144148
     
    176180        bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
    177181
    178         void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
     182        bool putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
    179183        void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0);
    180         void putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&);
     184        bool putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&);
    181185
    182186        void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
     
    206210        virtual bool isActivationObject() const { return false; }
    207211        virtual bool isNotAnObjectErrorStub() const { return false; }
     212        virtual bool isStrictModeFunction() const { return false; }
    208213
    209214        virtual ComplType exceptionType() const { return Throw; }
     
    266271        }
    267272
    268         void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*);
    269         void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
     273        bool putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*);
     274        bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
    270275        void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0);
    271276
     
    451456}
    452457
    453 inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
     458inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
    454459{
    455460    ASSERT(value);
     
    466471                m_structure->despecifyDictionaryFunction(propertyName);
    467472            if (checkReadOnly && currentAttributes & ReadOnly)
    468                 return;
     473                return false;
     474
    469475            putDirectOffset(offset, value);
    470476            // At this point, the objects structure only has a specific value set if previously there
     
    476482            if (!currentSpecificFunction || (specificFunction != currentSpecificFunction))
    477483                slot.setExistingProperty(this, offset);
    478             return;
     484            return true;
    479485        }
    480486
     
    489495        if (!specificFunction)
    490496            slot.setNewProperty(this, offset);
    491         return;
     497        return true;
    492498    }
    493499
     
    505511        if (!specificFunction)
    506512            slot.setNewProperty(this, offset);
    507         return;
     513        return true;
    508514    }
    509515
     
    513519    if (offset != WTF::notFound) {
    514520        if (checkReadOnly && currentAttributes & ReadOnly)
    515             return;
     521            return false;
    516522
    517523        // There are three possibilities here:
     
    528534            if (specificFunction == currentSpecificFunction) {
    529535                putDirectOffset(offset, value);
    530                 return;
     536                return true;
    531537            }
    532538            // case (2) Despecify, fall through to (3).
     
    537543        slot.setExistingProperty(this, offset);
    538544        putDirectOffset(offset, value);
    539         return;
     545        return true;
    540546    }
    541547
     
    562568    if (!specificFunction)
    563569        slot.setNewProperty(this, offset);
    564 }
    565 
    566 inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
     570    return true;
     571}
     572
     573inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
    567574{
    568575    ASSERT(value);
    569576    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
    570577
    571     putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
     578    return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
    572579}
    573580
     
    578585}
    579586
    580 inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
     587inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
    581588{
    582589    ASSERT(value);
    583590    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
    584591
    585     putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0);
     592    return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0);
    586593}
    587594
     
    592599}
    593600
    594 inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    595 {
    596     putDirectInternal(propertyName, value, 0, false, slot, 0);
     601inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
     602{
     603    return putDirectInternal(propertyName, value, 0, false, slot, 0);
    597604}
    598605
     
    699706}
    700707
    701 inline void JSValue::putDirect(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
     708inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    702709{
    703710    ASSERT(isCell() && isObject());
    704     asObject(asCell())->putDirect(propertyName, value, slot);
     711    if (!asObject(asCell())->putDirect(propertyName, value, slot) && slot.isStrictMode())
     712        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
    705713}
    706714
     
    757765}
    758766
     767inline JSValue JSValue::toStrictThisObject(ExecState* exec) const
     768{
     769    if (!isObject())
     770        return *this;
     771    return asObject(asCell())->toStrictThisObject(exec);
     772}
     773
    759774} // namespace JSC
    760775
  • trunk/JavaScriptCore/runtime/JSStaticScopeObject.cpp

    r64684 r69516  
    4343}
    4444
     45JSValue JSStaticScopeObject::toStrictThisObject(ExecState*) const
     46{
     47    return jsNull();
     48}
     49
    4550void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&)
    4651{
  • trunk/JavaScriptCore/runtime/JSStaticScopeObject.h

    r65104 r69516  
    5454        bool isDynamicScope(bool& requiresDynamicChecks) const;
    5555        virtual JSObject* toThisObject(ExecState*) const;
     56        virtual JSValue toStrictThisObject(ExecState*) const;
    5657        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
    5758        virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
  • trunk/JavaScriptCore/runtime/JSValue.h

    r67825 r69516  
    194194        bool needsThisConversion() const;
    195195        JSObject* toThisObject(ExecState*) const;
     196        JSValue toStrictThisObject(ExecState*) const;
    196197        UString toThisString(ExecState*) const;
    197198        JSString* toThisJSString(ExecState*) const;
  • trunk/JavaScriptCore/runtime/JSZombie.h

    r57019 r69516  
    6161    virtual bool deleteProperty(ExecState*, unsigned) { ASSERT_NOT_REACHED(); return false; }
    6262    virtual JSObject* toThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; }
     63    virtual JSValue toStrictThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return JSValue(); }
    6364    virtual JSValue getJSNumber() { ASSERT_NOT_REACHED(); return jsNull(); }
    6465    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
  • trunk/JavaScriptCore/runtime/PutPropertySlot.h

    r44076 r69516  
    3939        enum Type { Uncachable, ExistingProperty, NewProperty };
    4040
    41         PutPropertySlot()
     41        PutPropertySlot(bool isStrictMode = false)
    4242            : m_type(Uncachable)
    4343            , m_base(0)
     44            , m_isStrictMode(isStrictMode)
    4445        {
    4546        }
     
    6263        JSObject* base() const { return m_base; }
    6364
     65        bool isStrictMode() const { return m_isStrictMode; }
    6466        bool isCacheable() const { return m_type != Uncachable; }
    6567        size_t cachedOffset() const {
     
    7173        JSObject* m_base;
    7274        size_t m_offset;
     75        bool m_isStrictMode;
    7376    };
    7477
  • trunk/LayoutTests/ChangeLog

    r69515 r69516  
     12010-10-01  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        [ES5] Implement strict mode
     6        https://bugs.webkit.org/show_bug.cgi?id=10701
     7
     8        Tests for the many different behaviours we get in strict mode.
     9
     10        * fast/js/basic-strict-mode-expected.txt: Added.
     11        * fast/js/basic-strict-mode.html: Added.
     12        * fast/js/script-tests/basic-strict-mode.js: Added.
     13        (testThis):
     14        (testGlobalAccess):
     15
    1162010-10-10  Antonio Gomes  <agomes@rim.com>
    217
  • trunk/WebCore/ChangeLog

    r69514 r69516  
     12010-10-01  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        [ES5] Implement strict mode
     6        https://bugs.webkit.org/show_bug.cgi?id=10701
     7
     8        Test: fast/js/basic-strict-mode.html
     9
     10        Override toStrictThisObject on the domwindow so that
     11        it correctly provides the shell object when used as this
     12        in a strict mode function.
     13
     14        * bindings/js/JSDOMWindowBase.cpp:
     15        (WebCore::JSDOMWindowBase::toStrictThisObject):
     16        * bindings/js/JSDOMWindowBase.h:
     17
    1182010-10-11  Joseph Pecoraro  <joepeck@webkit.org>
    219
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r69284 r69516  
    2115121151                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
    2115221152                        compatibilityVersion = "Xcode 2.4";
    21153                         developmentRegion = English;
    2115421153                        hasScannedForEncodings = 1;
    2115521154                        knownRegions = (
  • trunk/WebCore/bindings/js/JSDOMWindowBase.cpp

    r58012 r69516  
    147147}
    148148
     149JSValue JSDOMWindowBase::toStrictThisObject(ExecState*) const
     150{
     151    return shell();
     152}
     153
    149154JSDOMWindowShell* JSDOMWindowBase::shell() const
    150155{
  • trunk/WebCore/bindings/js/JSDOMWindowBase.h

    r65021 r69516  
    7070        // Don't call this version of allowsAccessFrom -- it's a slightly incorrect implementation used only by WebScriptObject
    7171        virtual bool allowsAccessFrom(const JSC::JSGlobalObject*) const;
    72 
     72       
    7373        virtual JSC::JSObject* toThisObject(JSC::ExecState*) const;
     74        virtual JSC::JSValue toStrictThisObject(JSC::ExecState*) const;
    7475        JSDOMWindowShell* shell() const;
    7576
Note: See TracChangeset for help on using the changeset viewer.