WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
patch
c-backup.diff (text/plain), 182.67 KB, created by
Saam Barati
on 2015-07-18 18:25:37 PDT
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2015-07-18 18:25:37 PDT
Size:
182.67 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 187003) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,199 @@ >+2015-07-18 Saam barati <saambarati1@gmail.com> >+ >+ [ES6] Add support for block scope const >+ https://bugs.webkit.org/show_bug.cgi?id=31813 >+ >+ Reviewed by Filip Pizlo. >+ >+ 'const' is now implemented in an ES6 spec compliant manner. >+ 'const' variables are always block scoped and always live >+ either on the stack or in a JSLexicalEnvironment. 'const' >+ variables never live on the global object. >+ >+ Inside the BytecodeGenerator, when assigning to a stack >+ 'const' variable or a LocalClosureVar 'const' variable, >+ we will emit code that just throws a type error. >+ When assigning to a ClosureVar const variable, CodeBlock linking >+ will ensure that we perform a dynamic lookup of that variable so >+ that put_to_scope's slow path throws a type error. >+ >+ The old 'const' implementation has been removed in this patch. >+ >+ * bytecode/BytecodeList.json: >+ * bytecode/BytecodeUseDef.h: >+ (JSC::computeUsesForBytecodeOffset): >+ (JSC::computeDefsForBytecodeOffset): >+ * bytecode/CodeBlock.cpp: >+ (JSC::CodeBlock::dumpBytecode): >+ (JSC::CodeBlock::CodeBlock): >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::BytecodeGenerator): >+ (JSC::BytecodeGenerator::pushLexicalScope): >+ (JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration): >+ (JSC::BytecodeGenerator::resolveVariable): >+ (JSC::BytecodeGenerator::variable): >+ (JSC::BytecodeGenerator::isConstVariable): >+ (JSC::BytecodeGenerator::variableForLocalEntry): >+ (JSC::BytecodeGenerator::createVariable): >+ (JSC::BytecodeGenerator::emitResolveScope): >+ (JSC::BytecodeGenerator::emitInstanceOf): >+ (JSC::BytecodeGenerator::emitGetById): >+ (JSC::BytecodeGenerator::isArgumentNumber): >+ (JSC::BytecodeGenerator::emitReadOnlyExceptionIfNeeded): >+ (JSC::BytecodeGenerator::emitEnumeration): >+ (JSC::BytecodeGenerator::variablePerSymbolTable): Deleted. >+ (JSC::BytecodeGenerator::emitInitGlobalConst): Deleted. >+ * bytecompiler/BytecodeGenerator.h: >+ (JSC::BytecodeGenerator::thisRegister): >+ (JSC::BytecodeGenerator::emitTypeOf): >+ (JSC::BytecodeGenerator::emitIn): >+ * bytecompiler/NodesCodegen.cpp: >+ (JSC::PostfixNode::emitResolve): >+ (JSC::PrefixNode::emitResolve): >+ (JSC::ReadModifyResolveNode::emitBytecode): >+ (JSC::AssignResolveNode::emitBytecode): >+ (JSC::CommaNode::emitBytecode): >+ (JSC::BindingNode::bindValue): >+ (JSC::ConstDeclNode::emitCodeSingle): Deleted. >+ (JSC::ConstDeclNode::emitBytecode): Deleted. >+ (JSC::ConstStatementNode::emitBytecode): Deleted. >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ * dfg/DFGCapabilities.cpp: >+ (JSC::DFG::capabilityLevel): >+ * jit/JIT.cpp: >+ (JSC::JIT::privateCompileMainPass): >+ * jit/JIT.h: >+ * jit/JITPropertyAccess.cpp: >+ (JSC::JIT::emit_op_put_to_arguments): >+ (JSC::JIT::emit_op_init_global_const): Deleted. >+ * jit/JITPropertyAccess32_64.cpp: >+ (JSC::JIT::emit_op_put_to_arguments): >+ (JSC::JIT::emit_op_init_global_const): Deleted. >+ * llint/LowLevelInterpreter.asm: >+ * llint/LowLevelInterpreter32_64.asm: >+ * llint/LowLevelInterpreter64.asm: >+ * parser/ASTBuilder.h: >+ (JSC::ASTBuilder::createDebugger): >+ (JSC::ASTBuilder::appendStatement): >+ (JSC::ASTBuilder::createConstStatement): Deleted. >+ (JSC::ASTBuilder::appendConstDecl): Deleted. >+ * parser/NodeConstructors.h: >+ (JSC::CommaNode::CommaNode): >+ (JSC::SourceElements::SourceElements): >+ (JSC::SwitchNode::SwitchNode): >+ (JSC::BlockNode::BlockNode): >+ (JSC::ConstStatementNode::ConstStatementNode): Deleted. >+ (JSC::ConstDeclNode::ConstDeclNode): Deleted. >+ * parser/Nodes.h: >+ (JSC::ConstDeclNode::hasInitializer): Deleted. >+ (JSC::ConstDeclNode::ident): Deleted. >+ * parser/Parser.cpp: >+ (JSC::Parser<LexerType>::parseStatementListItem): >+ (JSC::Parser<LexerType>::parseVariableDeclaration): >+ (JSC::Parser<LexerType>::parseWhileStatement): >+ (JSC::Parser<LexerType>::parseVariableDeclarationList): >+ (JSC::Parser<LexerType>::createBindingPattern): >+ (JSC::Parser<LexerType>::parseDestructuringPattern): >+ (JSC::Parser<LexerType>::parseDefaultValueForDestructuringPattern): >+ (JSC::Parser<LexerType>::parseForStatement): >+ (JSC::Parser<LexerType>::parseTryStatement): >+ (JSC::Parser<LexerType>::parseFunctionInfo): >+ (JSC::Parser<LexerType>::parseFunctionDeclaration): >+ (JSC::Parser<LexerType>::parseClass): >+ (JSC::Parser<LexerType>::parseConstDeclaration): Deleted. >+ (JSC::Parser<LexerType>::parseConstDeclarationList): Deleted. >+ * parser/Parser.h: >+ (JSC::isEvalNode): >+ (JSC::isEvalNode<EvalNode>): >+ (JSC::isArguments): >+ (JSC::isEval): >+ (JSC::isEvalOrArgumentsIdentifier): >+ (JSC::Scope::Scope): >+ (JSC::Scope::declareCallee): >+ (JSC::Scope::declareVariable): >+ (JSC::Scope::declareLexicalVariable): >+ (JSC::Scope::hasDeclaredVariable): >+ (JSC::Scope::allowsVarDeclarations): >+ (JSC::Scope::allowsLexicalDeclarations): >+ (JSC::Scope::declareParameter): >+ (JSC::Scope::declareBoundParameter): >+ (JSC::Parser::destructuringKindFromDeclarationType): >+ (JSC::Parser::assignmentContextFromDeclarationType): >+ (JSC::Parser::isEvalOrArguments): >+ (JSC::Parser::currentScope): >+ (JSC::Parser::popScope): >+ (JSC::Parser::declareVariable): >+ (JSC::Parser::hasDeclaredVariable): >+ (JSC::Parser::setStrictMode): >+ (JSC::Parser::strictMode): >+ (JSC::Parser::isValidStrictMode): >+ (JSC::Parser::declareParameter): >+ (JSC::Parser::declareBoundParameter): >+ (JSC::Parser::breakIsValid): >+ * parser/SyntaxChecker.h: >+ (JSC::SyntaxChecker::createForInLoop): >+ (JSC::SyntaxChecker::createForOfLoop): >+ (JSC::SyntaxChecker::createEmptyStatement): >+ (JSC::SyntaxChecker::createDeclarationStatement): >+ (JSC::SyntaxChecker::createLetStatement): >+ (JSC::SyntaxChecker::createReturnStatement): >+ (JSC::SyntaxChecker::createBreakStatement): >+ (JSC::SyntaxChecker::createVarStatement): Deleted. >+ * parser/VariableEnvironment.h: >+ (JSC::VariableEnvironmentEntry::isCaptured): >+ (JSC::VariableEnvironmentEntry::isConst): >+ (JSC::VariableEnvironmentEntry::isVar): >+ (JSC::VariableEnvironmentEntry::isLet): >+ (JSC::VariableEnvironmentEntry::setIsCaptured): >+ (JSC::VariableEnvironmentEntry::setIsConst): >+ (JSC::VariableEnvironmentEntry::setIsVar): >+ (JSC::VariableEnvironmentEntry::setIsLet): >+ (JSC::VariableEnvironmentEntry::isConstant): Deleted. >+ (JSC::VariableEnvironmentEntry::setIsConstant): Deleted. >+ * runtime/Executable.cpp: >+ (JSC::ProgramExecutable::initializeGlobalProperties): >+ * runtime/JSGlobalObject.cpp: >+ (JSC::JSGlobalObject::defineOwnProperty): >+ (JSC::JSGlobalObject::addGlobalVar): >+ (JSC::JSGlobalObject::addFunction): >+ (JSC::lastInPrototypeChain): >+ * runtime/JSGlobalObject.h: >+ (JSC::JSGlobalObject::finishCreation): >+ (JSC::JSGlobalObject::addVar): >+ (JSC::JSGlobalObject::addConst): Deleted. >+ * runtime/JSLexicalEnvironment.cpp: >+ (JSC::JSLexicalEnvironment::symbolTablePut): >+ * tests/stress/const-and-with-statement.js: Added. >+ (truth): >+ (assert): >+ (shouldThrowInvalidConstAssignment): >+ (.): >+ * tests/stress/const-exception-handling.js: Added. >+ (truth): >+ (assert): >+ (.): >+ * tests/stress/const-loop-semantics.js: Added. >+ (truth): >+ (assert): >+ (shouldThrowInvalidConstAssignment): >+ (.): >+ * tests/stress/const-not-strict-mode.js: Added. >+ (truth): >+ (assert): >+ (shouldThrowTDZ): >+ (.): >+ * tests/stress/const-semantics.js: Added. >+ (truth): >+ (assert): >+ (shouldThrowInvalidConstAssignment): >+ (.): >+ * tests/stress/const-tdz.js: Added. >+ (truth): >+ (assert): >+ (shouldThrowTDZ): >+ (.): >+ > 2015-07-18 Saam barati <saambarati1@gmail.com> > > lexical scoping is broken with respect to "break" and "continue" >Index: Source/JavaScriptCore/bytecode/BytecodeList.json >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeList.json (revision 187003) >+++ Source/JavaScriptCore/bytecode/BytecodeList.json (working copy) >@@ -56,8 +56,6 @@ > { "name" : "op_is_object_or_null", "length" : 3 }, > { "name" : "op_is_function", "length" : 3 }, > { "name" : "op_in", "length" : 4 }, >- { "name" : "op_init_global_const_nop", "length" : 5 }, >- { "name" : "op_init_global_const", "length" : 5 }, > { "name" : "op_get_by_id", "length" : 9 }, > { "name" : "op_get_by_id_out_of_line", "length" : 9 }, > { "name" : "op_get_array_length", "length" : 9 }, >Index: Source/JavaScriptCore/bytecode/BytecodeUseDef.h >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeUseDef.h (revision 187003) >+++ Source/JavaScriptCore/bytecode/BytecodeUseDef.h (working copy) >@@ -116,8 +116,6 @@ void computeUsesForBytecodeOffset( > case op_get_enumerable_length: > case op_new_func_exp: > case op_to_index_string: >- case op_init_global_const_nop: >- case op_init_global_const: > case op_push_name_scope: > case op_push_with_scope: > case op_create_lexical_environment: >@@ -240,8 +238,6 @@ void computeDefsForBytecodeOffset(CodeBl > OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode); > switch (opcodeID) { > // These don't define anything. >- case op_init_global_const: >- case op_init_global_const_nop: > case op_put_to_scope: > case op_end: > case op_profile_will_call: >Index: Source/JavaScriptCore/bytecode/CodeBlock.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.cpp (revision 187003) >+++ Source/JavaScriptCore/bytecode/CodeBlock.cpp (working copy) >@@ -1052,23 +1052,6 @@ void CodeBlock::dumpBytecode( > printBinaryOp(out, exec, location, it, "in"); > break; > } >- case op_init_global_const_nop: { >- printLocationAndOp(out, exec, location, it, "init_global_const_nop"); >- it++; >- it++; >- it++; >- it++; >- break; >- } >- case op_init_global_const: { >- WriteBarrier<Unknown>* variablePointer = (++it)->u.variablePointer; >- int r0 = (++it)->u.operand; >- printLocationAndOp(out, exec, location, it, "init_global_const"); >- out.printf("g%d(%p), %s", m_globalObject->findVariableIndex(variablePointer).offset(), variablePointer, registerName(r0).data()); >- it++; >- it++; >- break; >- } > case op_get_by_id: > case op_get_by_id_out_of_line: > case op_get_array_length: { >@@ -1979,18 +1962,6 @@ CodeBlock::CodeBlock(ScriptExecutable* o > case op_get_array_length: > CRASH(); > >- case op_init_global_const_nop: { >- ASSERT(codeType() == GlobalCode); >- Identifier ident = identifier(pc[4].u.operand); >- SymbolTableEntry entry = m_globalObject->symbolTable()->get(ident.impl()); >- if (entry.isNull()) >- break; >- >- instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const); >- instructions[i + 1] = &m_globalObject->variableAt(entry.varOffset().scopeOffset()); >- break; >- } >- > case op_resolve_scope: { > const Identifier& ident = identifier(pc[3].u.operand); > ResolveType type = static_cast<ResolveType>(pc[4].u.operand); >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (revision 187003) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (working copy) >@@ -190,10 +190,8 @@ BytecodeGenerator::BytecodeGenerator(VM& > m_functionsToInitialize.append(std::make_pair(function, GlobalFunctionVariable)); > } > if (Options::validateBytecode()) { >- for (auto& entry : programNode->varDeclarations()) { >- // FIXME: When supporting ES6 spec compliant const, this should only check isVar(). >- RELEASE_ASSERT(entry.value.isVar() || entry.value.isConstant()); >- } >+ for (auto& entry : programNode->varDeclarations()) >+ RELEASE_ASSERT(entry.value.isVar()); > } > codeBlock->setVariableDeclarations(programNode->varDeclarations()); > } >@@ -411,20 +409,18 @@ BytecodeGenerator::BytecodeGenerator(VM& > > // Now declare all variables. > for (const Identifier& ident : boundParameterProperties) >- createVariable(ident, varKind(ident.impl()), IsVariable); >+ createVariable(ident, varKind(ident.impl())); > for (FunctionBodyNode* function : functionNode->functionStack()) { > const Identifier& ident = function->ident(); >- createVariable(ident, varKind(ident.impl()), IsVariable); >+ createVariable(ident, varKind(ident.impl())); > m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable)); > } > for (auto& entry : functionNode->varDeclarations()) { >- if (!entry.value.isVar()) >+ ASSERT(!entry.value.isLet() && !entry.value.isConst()); >+ if (!entry.value.isVar()) // This is either a parameter or callee. > continue; >- ConstantMode constantMode = modeForIsConstant(entry.value.isConstant()); > // Variables named "arguments" are never const. >- if (Identifier::fromUid(m_vm, entry.key.get()) == propertyNames().arguments) >- constantMode = IsVariable; >- createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), constantMode, IgnoreExisting); >+ createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), IgnoreExisting); > } > > // There are some variables that need to be preinitialized to something other than Undefined: >@@ -500,7 +496,7 @@ BytecodeGenerator::BytecodeGenerator(VM& > > if (!haveParameterNamedArguments) { > createVariable( >- propertyNames().arguments, varKind(propertyNames().arguments.impl()), IsVariable); >+ propertyNames().arguments, varKind(propertyNames().arguments.impl())); > m_needToInitializeArguments = true; > } > } >@@ -559,7 +555,7 @@ BytecodeGenerator::BytecodeGenerator(VM& > Vector<Identifier, 0, UnsafeVectorOverflow> variables; > variables.reserveCapacity(numVariables); > for (auto& entry : varDeclarations) { >- ASSERT(entry.value.isVar() || entry.value.isConstant()); // FIXME: When supporting ES6 spec compliant const, this should only check isVar(). >+ ASSERT(entry.value.isVar()); > ASSERT(entry.key->isAtomic() || entry.key->isSymbol()); > variables.append(Identifier::fromUid(m_vm, entry.key.get())); > } >@@ -1281,7 +1277,8 @@ void BytecodeGenerator::pushLexicalScope > { > ConcurrentJITLocker locker(symbolTable->m_lock); > for (auto entry : environment) { >- ASSERT(entry.value.isLet() && !entry.value.isVar()); >+ ASSERT(entry.value.isLet() || entry.value.isConst()); >+ ASSERT(!entry.value.isVar()); > SymbolTableEntry symbolTableEntry = symbolTable->get(locker, entry.key.get()); > ASSERT(symbolTableEntry.isNull()); > >@@ -1296,8 +1293,8 @@ void BytecodeGenerator::pushLexicalScope > local->ref(); > varOffset = VarOffset(local->virtualRegister()); > } >- // FIXME: Make this work with 'const' variables: https://bugs.webkit.org/show_bug.cgi?id=31813 >- SymbolTableEntry newEntry(varOffset, 0); >+ >+ SymbolTableEntry newEntry(varOffset, entry.value.isConst() ? ReadOnly : 0); > symbolTable->add(locker, entry.key.get(), newEntry); > } > } >@@ -1416,7 +1413,7 @@ void BytecodeGenerator::prepareLexicalSc > > RegisterID* transitionValue = newBlockScopeVariable(); > transitionValue->ref(); >- emitGetFromScope(transitionValue, loopScope, variableForLocalEntry(identifier, ptr->value, loopSymbolTable->index()), DoNotThrowIfNotFound); >+ emitGetFromScope(transitionValue, loopScope, variableForLocalEntry(identifier, ptr->value, loopSymbolTable->index(), true), DoNotThrowIfNotFound); > activationValuesToCopyOver.uncheckedAppend(std::make_pair(transitionValue, identifier)); > } > } >@@ -1445,7 +1442,7 @@ void BytecodeGenerator::prepareLexicalSc > SymbolTableEntry entry = symbolTable->get(locker, identifier.impl()); > RELEASE_ASSERT(!entry.isNull()); > RegisterID* transitionValue = pair.first; >- emitPutToScope(loopScope, variableForLocalEntry(identifier, entry, loopSymbolTable->index()), transitionValue, DoNotThrowIfNotFound); >+ emitPutToScope(loopScope, variableForLocalEntry(identifier, entry, loopSymbolTable->index(), true), transitionValue, DoNotThrowIfNotFound); > transitionValue->deref(); > } > } >@@ -1454,9 +1451,8 @@ void BytecodeGenerator::prepareLexicalSc > Variable BytecodeGenerator::variable(const Identifier& property) > { > if (property == propertyNames().thisIdentifier) { >- return Variable( >- property, VarOffset(thisRegister()->virtualRegister()), thisRegister(), >- ReadOnly, Variable::SpecialVariable, 0); >+ return Variable(property, VarOffset(thisRegister()->virtualRegister()), thisRegister(), >+ ReadOnly, Variable::SpecialVariable, 0, false); > } > > // We can optimize lookups if the lexical variable is found before a "with" or "catch" >@@ -1481,31 +1477,20 @@ Variable BytecodeGenerator::variable(con > for (unsigned i = m_symbolTableStack.size(); i--; ) { > SymbolTableStackEntry& stackEntry = m_symbolTableStack[i]; > if (stackEntry.m_isWithOrCatch) >- return Variable(property); >+ Variable(property); > Strong<SymbolTable>& symbolTable = stackEntry.m_symbolTable; > SymbolTableEntry symbolTableEntry = symbolTable->get(property.impl()); > if (symbolTableEntry.isNull()) > continue; > >- return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex); >+ return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable->correspondsToLexicalScope()); > } > > return Variable(property); > } > >-Variable BytecodeGenerator::variablePerSymbolTable(const Identifier& property) >-{ >- RELEASE_ASSERT(m_symbolTableStack.size()); >- SymbolTableStackEntry& baseActivationEntry = m_symbolTableStack.first(); >- SymbolTableEntry entry = baseActivationEntry.m_symbolTable->get(property.impl()); >- if (entry.isNull()) >- return Variable(property); >- >- return variableForLocalEntry(property, entry, baseActivationEntry.m_symbolTableConstantIndex); >-} >- > Variable BytecodeGenerator::variableForLocalEntry( >- const Identifier& property, const SymbolTableEntry& entry, int symbolTableConstantIndex) >+ const Identifier& property, const SymbolTableEntry& entry, int symbolTableConstantIndex, bool isLexicallyScoped) > { > VarOffset offset = entry.varOffset(); > >@@ -1515,12 +1500,11 @@ Variable BytecodeGenerator::variableForL > else > local = nullptr; > >- return Variable(property, offset, local, entry.getAttributes(), Variable::NormalVariable, symbolTableConstantIndex); >+ return Variable(property, offset, local, entry.getAttributes(), Variable::NormalVariable, symbolTableConstantIndex, isLexicallyScoped); > } > > void BytecodeGenerator::createVariable( >- const Identifier& property, VarKind varKind, ConstantMode constantMode, >- ExistingVariableMode existingVariableMode) >+ const Identifier& property, VarKind varKind, ExistingVariableMode existingVariableMode) > { > ASSERT(property != propertyNames().thisIdentifier); > ConcurrentJITLocker locker(symbolTable().m_lock); >@@ -1536,10 +1520,10 @@ void BytecodeGenerator::createVariable( > VarOffset offset = entry.varOffset(); > > // We can't change our minds about whether it's captured. >- if (offset.kind() != varKind || constantMode != entry.constantMode()) { >+ if (offset.kind() != varKind) { > dataLog( >- "Trying to add variable called ", property, " as ", varKind, "/", constantMode, >- " but it was already added as ", offset, "/", entry.constantMode(), ".\n"); >+ "Trying to add variable called ", property, " as ", varKind, >+ " but it was already added as ", offset, ".\n"); > RELEASE_ASSERT_NOT_REACHED(); > } > >@@ -1553,7 +1537,7 @@ void BytecodeGenerator::createVariable( > ASSERT(varKind == VarKind::Stack); > varOffset = VarOffset(virtualRegisterForLocal(m_calleeRegisters.size())); > } >- SymbolTableEntry newEntry(varOffset, constantMode == IsConstant ? ReadOnly : 0); >+ SymbolTableEntry newEntry(varOffset, 0); > symbolTable().add(locker, property.impl(), newEntry); > > if (varKind == VarKind::Stack) { >@@ -1606,18 +1590,12 @@ RegisterID* BytecodeGenerator::emitResol > SymbolTableStackEntry& stackEntry = m_symbolTableStack[i]; > // We should not resolve a variable to VarKind::Scope if a "with" or "catch" scope lies in between the current > // scope and the resolved scope. >- // We'd like to say: RELEASE_ASSERT(!stackEntry.m_isWithOrCatch); >- // But, our current implementation 'const' is a pile of crap and uses variablePerSymbolTable >- // which recklessly ignores the scope stack. >- // FIXME: When implementing const the proper way ensure we add this assert in. >- // https://bugs.webkit.org/show_bug.cgi?id=143654 >- if (stackEntry.m_isWithOrCatch) >- continue; >+ RELEASE_ASSERT(!stackEntry.m_isWithOrCatch); > > if (stackEntry.m_symbolTable->get(variable.ident().impl()).isNull()) > continue; > >- RegisterID* scope = stackEntry.m_scope; >+ RegisterID* scope = stackEntry.m_scope; > RELEASE_ASSERT(scope); > return scope; > } >@@ -1738,17 +1716,6 @@ RegisterID* BytecodeGenerator::emitInsta > return dst; > } > >-RegisterID* BytecodeGenerator::emitInitGlobalConst(const Identifier& identifier, RegisterID* value) >-{ >- ASSERT(m_codeType == GlobalCode); >- emitOpcode(op_init_global_const_nop); >- instructions().append(0); >- instructions().append(value->index()); >- instructions().append(0); >- instructions().append(addConstant(identifier)); >- return value; >-} >- > RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property) > { > m_codeBlock->addPropertyAccessInstruction(instructions().size()); >@@ -3085,13 +3052,15 @@ bool BytecodeGenerator::isArgumentNumber > return registerID->index() == CallFrame::argumentOffset(argumentNumber); > } > >-void BytecodeGenerator::emitReadOnlyExceptionIfNeeded() >+bool BytecodeGenerator::emitReadOnlyExceptionIfNeeded(const Variable& variable) > { >- if (!isStrictMode()) >- return; >- emitOpcode(op_throw_static_error); >- instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, StrictModeReadonlyPropertyWriteError)))->index()); >- instructions().append(false); >+ if (isStrictMode() || variable.isConst()) { >+ emitOpcode(op_throw_static_error); >+ instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, StrictModeReadonlyPropertyWriteError)))->index()); >+ instructions().append(false); >+ return true; >+ } >+ return false; > } > > void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, VariableEnvironmentNode* forLoopNode, RegisterID* forLoopSymbolTable) >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (revision 187003) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (working copy) >@@ -194,6 +194,7 @@ namespace JSC { > , m_attributes(0) > , m_kind(NormalVariable) > , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable. >+ , m_isLexicallyScoped(false) > { > } > >@@ -203,16 +204,18 @@ namespace JSC { > , m_attributes(0) > , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable. > , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable. >+ , m_isLexicallyScoped(false) > { > } > >- Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind, int symbolTableConstantIndex) >+ Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind, int symbolTableConstantIndex, bool isLexicallyScoped) > : m_ident(ident) > , m_offset(offset) > , m_local(local) > , m_attributes(attributes) > , m_kind(kind) > , m_symbolTableConstantIndex(symbolTableConstantIndex) >+ , m_isLexicallyScoped(isLexicallyScoped) > { > } > >@@ -230,6 +233,7 @@ namespace JSC { > > bool isReadOnly() const { return m_attributes & ReadOnly; } > bool isSpecial() const { return m_kind != NormalVariable; } >+ bool isConst() const { return isReadOnly() && m_isLexicallyScoped; } > > private: > Identifier m_ident; >@@ -238,6 +242,7 @@ namespace JSC { > unsigned m_attributes; > VariableKind m_kind; > int m_symbolTableConstantIndex; >+ bool m_isLexicallyScoped; > }; > > struct TryRange { >@@ -286,11 +291,8 @@ namespace JSC { > > Variable variable(const Identifier&); > >- // Ignores the possibility of intervening scopes. >- Variable variablePerSymbolTable(const Identifier&); >- > enum ExistingVariableMode { VerifyExisting, IgnoreExisting }; >- void createVariable(const Identifier&, VarKind, ConstantMode, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible. >+ void createVariable(const Identifier&, VarKind, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible. > > // Returns the register storing "this" > RegisterID* thisRegister() { return &m_thisRegister; } >@@ -488,8 +490,6 @@ namespace JSC { > RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); } > RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); } > >- RegisterID* emitInitGlobalConst(const Identifier&, RegisterID* value); >- > RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property); > RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value); > RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType); >@@ -564,7 +564,7 @@ namespace JSC { > RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node); > void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node); > >- void emitReadOnlyExceptionIfNeeded(); >+ bool emitReadOnlyExceptionIfNeeded(const Variable&); > > // Start a try block. 'start' must have been emitted. > TryData* pushTry(Label* start); >@@ -628,7 +628,7 @@ namespace JSC { > > private: > void reclaimFreeRegisters(); >- Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&, int); >+ Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&, int symbolTableConstantIndex, bool isLexicallyScoped); > > void emitOpcode(OpcodeID); > UnlinkedArrayAllocationProfile newArrayAllocationProfile(); >Index: Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (revision 187003) >+++ Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (working copy) >@@ -1065,7 +1065,7 @@ RegisterID* PostfixNode::emitResolve(Byt > generator.emitTDZCheckIfNecessary(var, local, nullptr); > RefPtr<RegisterID> localReg = local; > if (var.isReadOnly()) { >- generator.emitReadOnlyExceptionIfNeeded(); >+ generator.emitReadOnlyExceptionIfNeeded(var); > localReg = generator.emitMove(generator.tempDestination(dst), local); > } else if (generator.vm()->typeProfiler()) { > RefPtr<RegisterID> tempDst = generator.finalDestination(dst); >@@ -1086,6 +1086,11 @@ RegisterID* PostfixNode::emitResolve(Byt > RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); > RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); > generator.emitTDZCheckIfNecessary(var, value.get(), nullptr); >+ if (var.isReadOnly()) { >+ bool threwException = generator.emitReadOnlyExceptionIfNeeded(var); >+ if (threwException) >+ return value.get(); >+ } > RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); > generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound); > if (generator.vm()->typeProfiler()) { >@@ -1269,7 +1274,7 @@ RegisterID* PrefixNode::emitResolve(Byte > generator.emitTDZCheckIfNecessary(var, local, nullptr); > RefPtr<RegisterID> localReg = local; > if (var.isReadOnly()) { >- generator.emitReadOnlyExceptionIfNeeded(); >+ generator.emitReadOnlyExceptionIfNeeded(var); > localReg = generator.emitMove(generator.tempDestination(dst), localReg.get()); > } else if (generator.vm()->typeProfiler()) { > RefPtr<RegisterID> tempDst = generator.tempDestination(dst); >@@ -1288,6 +1293,11 @@ RegisterID* PrefixNode::emitResolve(Byte > RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var); > RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); > generator.emitTDZCheckIfNecessary(var, value.get(), nullptr); >+ if (var.isReadOnly()) { >+ bool threwException = generator.emitReadOnlyExceptionIfNeeded(var); >+ if (threwException) >+ return value.get(); >+ } > > emitIncOrDec(generator, value.get(), m_operator); > generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound); >@@ -1788,7 +1798,7 @@ RegisterID* ReadModifyResolveNode::emitB > if (RegisterID* local = var.local()) { > generator.emitTDZCheckIfNecessary(var, local, nullptr); > if (var.isReadOnly()) { >- generator.emitReadOnlyExceptionIfNeeded(); >+ generator.emitReadOnlyExceptionIfNeeded(var); > return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); > } > >@@ -1813,6 +1823,11 @@ RegisterID* ReadModifyResolveNode::emitB > RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); > RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound); > generator.emitTDZCheckIfNecessary(var, value.get(), nullptr); >+ if (var.isReadOnly()) { >+ bool threwException = generator.emitReadOnlyExceptionIfNeeded(var); >+ if (threwException) >+ return value.get(); >+ } > RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); > RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound); > if (generator.vm()->typeProfiler()) { >@@ -1831,8 +1846,9 @@ RegisterID* AssignResolveNode::emitBytec > RegisterID* result = nullptr; > if (m_assignmentContext == AssignmentContext::AssignmentExpression) > generator.emitTDZCheckIfNecessary(var, local, nullptr); >- if (var.isReadOnly()) { >- generator.emitReadOnlyExceptionIfNeeded(); >+ >+ if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) { >+ generator.emitReadOnlyExceptionIfNeeded(var); > result = generator.emitNode(dst, m_right); > } else if (var.isSpecial() || generator.vm()->typeProfiler()) { > RefPtr<RegisterID> tempDst = generator.tempDestination(dst); >@@ -1848,7 +1864,7 @@ RegisterID* AssignResolveNode::emitBytec > result = generator.moveToDestinationIfNeeded(dst, right); > } > >- if (m_assignmentContext == AssignmentContext::DeclarationStatement) >+ if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement) > generator.liftTDZCheckIfPossible(var); > return result; > } >@@ -1861,6 +1877,11 @@ RegisterID* AssignResolveNode::emitBytec > if (dst == generator.ignoredResult()) > dst = 0; > RefPtr<RegisterID> result = generator.emitNode(dst, m_right); >+ if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) { >+ bool threwException = generator.emitReadOnlyExceptionIfNeeded(var); >+ if (threwException) >+ return generator.emitNode(dst, m_right); >+ } > generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); > RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); > if (generator.vm()->typeProfiler()) { >@@ -1868,7 +1889,7 @@ RegisterID* AssignResolveNode::emitBytec > generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); > } > >- if (m_assignmentContext == AssignmentContext::DeclarationStatement) >+ if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement) > generator.liftTDZCheckIfPossible(var); > return returnResult; > } >@@ -1971,68 +1992,6 @@ RegisterID* CommaNode::emitBytecode(Byte > return generator.emitNode(dst, node->m_expr); > } > >-// ------------------------------ ConstDeclNode ------------------------------------ >- >-RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) >-{ >- // FIXME: This code does not match the behavior of const in Firefox. >- Variable var = generator.variable(m_ident); >- if (RegisterID* local = var.local()) { >- if (!m_init) >- return local; >- >- // FIXME: Maybe call emitExpressionInfo here. >- if (var.isSpecial() || generator.vm()->typeProfiler()) { >- RefPtr<RegisterID> tempDst = generator.newTemporary(); >- generator.emitNode(tempDst.get(), m_init); >- return generator.emitMove(local, tempDst.get()); >- } >- >- return generator.emitNode(local, m_init); >- } >- >- RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); >- >- if (generator.codeType() == GlobalCode) >- return generator.emitInitGlobalConst(m_ident, value.get()); >- >- if (generator.codeType() != EvalCode) { >- // Do a special kind of resolution. If anything fails, then don't perform the assignment. This is >- // pretty shady - particularly how negligent it is with inteleaving scopes - but it's the >- // behavior that JSC has had for a long time. >- >- ASSERT(generator.codeType() == FunctionCode); >- >- var = generator.variablePerSymbolTable(m_ident); >- if (!var.isResolved()) >- return value.get(); >- >- RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), var); >- return generator.emitPutToScope(scope.get(), var, value.get(), DoNotThrowIfNotFound); >- } >- >- // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope. >- RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); >- return generator.emitPutToScope(scope.get(), var, value.get(), DoNotThrowIfNotFound); >-} >- >-RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) >-{ >- RegisterID* result = 0; >- for (ConstDeclNode* n = this; n; n = n->m_next) >- result = n->emitCodeSingle(generator); >- >- return result; >-} >- >-// ------------------------------ ConstStatementNode ----------------------------- >- >-void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) >-{ >- generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset()); >- generator.emitNode(m_next); >-} >- > // ------------------------------ SourceElements ------------------------------- > > >@@ -3391,14 +3350,15 @@ void BindingNode::bindValue(BytecodeGene > if (RegisterID* local = var.local()) { > if (m_bindingContext == AssignmentContext::AssignmentExpression) > generator.emitTDZCheckIfNecessary(var, local, nullptr); >- if (var.isReadOnly()) { >- generator.emitReadOnlyExceptionIfNeeded(); >- return; >+ if (var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement) { >+ bool threwException = generator.emitReadOnlyExceptionIfNeeded(var); >+ if (threwException) >+ return; > } > generator.emitMove(local, value); > if (generator.vm()->typeProfiler()) > generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); >- if (m_bindingContext == AssignmentContext::DeclarationStatement) >+ if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement) > generator.liftTDZCheckIfPossible(var); > return; > } >@@ -3408,12 +3368,17 @@ void BindingNode::bindValue(BytecodeGene > generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd()); > if (m_bindingContext == AssignmentContext::AssignmentExpression) > generator.emitTDZCheckIfNecessary(var, nullptr, scope); >+ if (var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement) { >+ bool threwException = generator.emitReadOnlyExceptionIfNeeded(var); >+ if (threwException) >+ return; >+ } > generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); > if (generator.vm()->typeProfiler()) { > generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty); > generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); > } >- if (m_bindingContext == AssignmentContext::DeclarationStatement) >+ if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement) > generator.liftTDZCheckIfPossible(var); > return; > } >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 187003) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -3152,20 +3152,6 @@ bool ByteCodeParser::parseBlock(unsigned > NEXT_OPCODE(op_put_by_id); > } > >- case op_init_global_const_nop: { >- NEXT_OPCODE(op_init_global_const_nop); >- } >- >- case op_init_global_const: { >- Node* value = get(VirtualRegister(currentInstruction[2].u.operand)); >- JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject(); >- addToGraph( >- PutGlobalVar, >- OpInfo(globalObject->assertVariableIsInThisObject(currentInstruction[1].u.variablePointer)), >- weakJSConstant(globalObject), value); >- NEXT_OPCODE(op_init_global_const); >- } >- > case op_profile_type: { > Node* valueToProfile = get(VirtualRegister(currentInstruction[1].u.operand)); > addToGraph(ProfileType, OpInfo(currentInstruction[2].u.location), valueToProfile); >Index: Source/JavaScriptCore/dfg/DFGCapabilities.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCapabilities.cpp (revision 187003) >+++ Source/JavaScriptCore/dfg/DFGCapabilities.cpp (working copy) >@@ -152,8 +152,6 @@ CapabilityLevel capabilityLevel(OpcodeID > case op_put_by_id_transition_direct_out_of_line: > case op_put_by_id_transition_normal: > case op_put_by_id_transition_normal_out_of_line: >- case op_init_global_const_nop: >- case op_init_global_const: > case op_jmp: > case op_jtrue: > case op_jfalse: >Index: Source/JavaScriptCore/jit/JIT.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JIT.cpp (revision 187003) >+++ Source/JavaScriptCore/jit/JIT.cpp (working copy) >@@ -285,9 +285,6 @@ void JIT::privateCompileMainPass() > DEFINE_OP(op_put_getter_by_id) > DEFINE_OP(op_put_setter_by_id) > DEFINE_OP(op_put_getter_setter) >- case op_init_global_const_nop: >- NEXT_OPCODE(op_init_global_const_nop); >- DEFINE_OP(op_init_global_const) > > DEFINE_OP(op_ret) > DEFINE_OP(op_rshift) >Index: Source/JavaScriptCore/jit/JIT.h >=================================================================== >--- Source/JavaScriptCore/jit/JIT.h (revision 187003) >+++ Source/JavaScriptCore/jit/JIT.h (working copy) >@@ -540,7 +540,6 @@ namespace JSC { > void emit_op_put_getter_by_id(Instruction*); > void emit_op_put_setter_by_id(Instruction*); > void emit_op_put_getter_setter(Instruction*); >- void emit_op_init_global_const(Instruction*); > void emit_op_ret(Instruction*); > void emit_op_rshift(Instruction*); > void emit_op_strcat(Instruction*); >Index: Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (revision 187003) >+++ Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (working copy) >@@ -861,21 +861,6 @@ void JIT::emit_op_put_to_arguments(Instr > store32(regT2, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset)); > } > >-void JIT::emit_op_init_global_const(Instruction* currentInstruction) >-{ >- WriteBarrier<Unknown>* variablePointer = currentInstruction[1].u.variablePointer; >- int value = currentInstruction[2].u.operand; >- >- JSGlobalObject* globalObject = m_codeBlock->globalObject(); >- >- emitWriteBarrier(globalObject, value, ShouldFilterValue); >- >- emitLoad(value, regT1, regT0); >- >- store32(regT1, variablePointer->tagPointer()); >- store32(regT0, variablePointer->payloadPointer()); >-} >- > } // namespace JSC > > #endif // USE(JSVALUE32_64) >Index: Source/JavaScriptCore/jit/JITPropertyAccess.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITPropertyAccess.cpp (revision 187003) >+++ Source/JavaScriptCore/jit/JITPropertyAccess.cpp (working copy) >@@ -828,14 +828,6 @@ void JIT::emit_op_put_to_arguments(Instr > store64(regT1, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>))); > } > >-void JIT::emit_op_init_global_const(Instruction* currentInstruction) >-{ >- JSGlobalObject* globalObject = m_codeBlock->globalObject(); >- emitWriteBarrier(globalObject, currentInstruction[2].u.operand, ShouldFilterValue); >- emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); >- store64(regT0, currentInstruction[1].u.variablePointer); >-} >- > #endif // USE(JSVALUE64) > > #if USE(JSVALUE64) >Index: Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (revision 187003) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (working copy) >@@ -1369,17 +1369,6 @@ macro storePropertyAtVariableOffset(prop > end > > >-_llint_op_init_global_const: >- traceExecution() >- writeBarrierOnGlobalObject(2) >- loadi 8[PC], t1 >- loadi 4[PC], t0 >- loadConstantOrVariable(t1, t2, t3) >- storei t2, TagOffset[t0] >- storei t3, PayloadOffset[t0] >- dispatch(5) >- >- > # We only do monomorphic get_by_id caching for now, and we do not modify the > # opcode. We do, however, allow for the cache to change anytime if fails, since > # ping-ponging is free. At best we get lucky and the get_by_id will continue >Index: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (revision 187003) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (working copy) >@@ -1236,16 +1236,6 @@ macro storePropertyAtVariableOffset(prop > storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8] > end > >-_llint_op_init_global_const: >- traceExecution() >- writeBarrierOnGlobalObject(2) >- loadisFromInstruction(2, t1) >- loadpFromInstruction(1, t0) >- loadConstantOrVariable(t1, t2) >- storeq t2, [t0] >- dispatch(5) >- >- > macro getById(getPropertyStorage) > traceExecution() > # We only do monomorphic get_by_id caching for now, and we do not modify the >Index: Source/JavaScriptCore/llint/LowLevelInterpreter.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter.asm (revision 187003) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter.asm (working copy) >@@ -1418,6 +1418,3 @@ macro notSupported() > break > end > end >- >-_llint_op_init_global_const_nop: >- dispatch(5) >Index: Source/JavaScriptCore/parser/ASTBuilder.h >=================================================================== >--- Source/JavaScriptCore/parser/ASTBuilder.h (revision 187003) >+++ Source/JavaScriptCore/parser/ASTBuilder.h (working copy) >@@ -116,7 +116,6 @@ public: > typedef StatementNode* Statement; > typedef ClauseListNode* ClauseList; > typedef CaseClauseNode* Clause; >- typedef ConstDeclNode* ConstDeclList; > typedef std::pair<ExpressionNode*, BinaryOpInfo> BinaryOperand; > typedef DestructuringPatternNode* DestructuringPattern; > typedef ArrayPatternNode* ArrayPattern; >@@ -515,16 +514,6 @@ public: > return result; > } > >- StatementNode* createVarStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) >- { >- return createDeclarationStatement(location, expr, start, end); >- } >- >- StatementNode* createLetStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) >- { >- return createDeclarationStatement(location, expr, start, end); >- } >- > ExpressionNode* createEmptyVarExpression(const JSTokenLocation& location, const Identifier& identifier) > { > return new (m_parserArena) EmptyVarExpression(location, identifier); >@@ -620,21 +609,6 @@ public: > return result; > } > >- StatementNode* createConstStatement(const JSTokenLocation& location, ConstDeclNode* decls, int startLine, int endLine) >- { >- ConstStatementNode* result = new (m_parserArena) ConstStatementNode(location, decls); >- result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); >- return result; >- } >- >- ConstDeclNode* appendConstDecl(const JSTokenLocation& location, ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer) >- { >- ConstDeclNode* result = new (m_parserArena) ConstDeclNode(location, *name, initializer); >- if (tail) >- tail->m_next = result; >- return result; >- } >- > void appendStatement(JSC::SourceElements* elements, JSC::StatementNode* statement) > { > elements->append(statement); >Index: Source/JavaScriptCore/parser/NodeConstructors.h >=================================================================== >--- Source/JavaScriptCore/parser/NodeConstructors.h (revision 187003) >+++ Source/JavaScriptCore/parser/NodeConstructors.h (working copy) >@@ -700,12 +700,6 @@ namespace JSC { > { > } > >- inline ConstStatementNode::ConstStatementNode(const JSTokenLocation& location, ConstDeclNode* next) >- : StatementNode(location) >- , m_next(next) >- { >- } >- > inline SourceElements::SourceElements() > : m_head(nullptr) > , m_tail(nullptr) >@@ -898,14 +892,6 @@ namespace JSC { > { > } > >- inline ConstDeclNode::ConstDeclNode(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* init) >- : ExpressionNode(location) >- , m_ident(ident) >- , m_next(0) >- , m_init(init) >- { >- } >- > inline BlockNode::BlockNode(const JSTokenLocation& location, SourceElements* statements, VariableEnvironment& lexicalVariables) > : StatementNode(location) > , VariableEnvironmentNode(lexicalVariables) >Index: Source/JavaScriptCore/parser/Nodes.h >=================================================================== >--- Source/JavaScriptCore/parser/Nodes.h (revision 187003) >+++ Source/JavaScriptCore/parser/Nodes.h (working copy) >@@ -90,7 +90,11 @@ namespace JSC { > SwitchType switchType; > }; > >- enum class AssignmentContext { DeclarationStatement, AssignmentExpression }; >+ enum class AssignmentContext { >+ DeclarationStatement, >+ ConstDeclarationStatement, >+ AssignmentExpression >+ }; > > class ParserArenaFreeable { > public: >@@ -1254,36 +1258,6 @@ namespace JSC { > CommaNode* m_next; > }; > >- class ConstDeclNode : public ExpressionNode { >- public: >- ConstDeclNode(const JSTokenLocation&, const Identifier&, ExpressionNode*); >- >- bool hasInitializer() const { return m_init; } >- const Identifier& ident() { return m_ident; } >- >- private: >- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; >- virtual RegisterID* emitCodeSingle(BytecodeGenerator&); >- >- const Identifier& m_ident; >- >- public: >- ConstDeclNode* m_next; >- >- private: >- ExpressionNode* m_init; >- }; >- >- class ConstStatementNode : public StatementNode { >- public: >- ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next); >- >- private: >- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; >- >- ConstDeclNode* m_next; >- }; >- > class SourceElements final : public ParserArenaFreeable { > public: > SourceElements(); >@@ -1958,11 +1932,6 @@ namespace JSC { > ArgumentListNode* tail; > }; > >- struct ConstDeclList { >- ConstDeclNode* head; >- ConstDeclNode* tail; >- }; >- > struct ClauseList { > ClauseListNode* head; > ClauseListNode* tail; >Index: Source/JavaScriptCore/parser/Parser.cpp >=================================================================== >--- Source/JavaScriptCore/parser/Parser.cpp (revision 187003) >+++ Source/JavaScriptCore/parser/Parser.cpp (working copy) >@@ -414,7 +414,7 @@ template <class TreeBuilder> TreeStateme > bool shouldSetEndOffset = true; > switch (m_token.m_type) { > case CONSTTOKEN: >- result = parseConstDeclaration(context); >+ result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration); > break; > case LET: { > bool shouldParseVariableDeclaration = true; >@@ -426,7 +426,7 @@ template <class TreeBuilder> TreeStateme > restoreSavePoint(savePoint); > } > if (shouldParseVariableDeclaration) >- result = parseVariableDeclaration(context, DeclarationType::LexicalDeclaration); >+ result = parseVariableDeclaration(context, DeclarationType::LetDeclaration); > else > result = parseExpressionOrLabelStatement(context); // Treat this as an IDENT. This is how ::parseStatement() handles IDENT. > >@@ -453,7 +453,7 @@ template <class TreeBuilder> TreeStateme > template <typename LexerType> > template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType) > { >- ASSERT(match(VAR) || match(LET)); >+ ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN)); > JSTokenLocation location(tokenLocation()); > int start = tokenLine(); > int end = 0; >@@ -461,28 +461,12 @@ template <class TreeBuilder> TreeStateme > TreeDestructuringPattern scratch1 = 0; > TreeExpression scratch2 = 0; > JSTextPosition scratch3; >- TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType); >+ bool scratchBool; >+ TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, scratchBool); > propagateError(); >- failIfFalse(autoSemiColon(), "Expected ';' after var declaration"); >+ failIfFalse(autoSemiColon(), "Expected ';' after variable declaration"); > >- if (declarationType == DeclarationType::VarDeclaration) >- return context.createVarStatement(location, variableDecls, start, end); >- ASSERT(declarationType == DeclarationType::LexicalDeclaration); >- return context.createLetStatement(location, variableDecls, start, end); >-} >- >-template <typename LexerType> >-template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context) >-{ >- ASSERT(match(CONSTTOKEN)); >- JSTokenLocation location(tokenLocation()); >- int start = tokenLine(); >- int end = 0; >- TreeConstDeclList constDecls = parseConstDeclarationList(context); >- propagateError(); >- failIfFalse(autoSemiColon(), "Expected ';' after const declaration"); >- >- return context.createConstStatement(location, constDecls, start, end); >+ return context.createDeclarationStatement(location, variableDecls, start, end); > } > > template <typename LexerType> >@@ -533,13 +517,14 @@ template <class TreeBuilder> TreeStateme > } > > template <typename LexerType> >-template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVariableDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext, DeclarationType declarationType) >+template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVariableDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext, DeclarationType declarationType, bool& forLoopConstDoesNotHaveInitializer) > { >- ASSERT(declarationType == DeclarationType::LexicalDeclaration || declarationType == DeclarationType::VarDeclaration); >+ ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration); > TreeExpression head = 0; > TreeExpression tail = 0; > const Identifier* lastIdent; > JSToken lastIdentToken; >+ AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType); > do { > lastIdent = 0; > lastPattern = TreeDestructuringPattern(0); >@@ -549,7 +534,8 @@ template <class TreeBuilder> TreeExpress > declarations++; > bool hasInitializer = false; > if (match(IDENT) || isLETMaskedAsIDENT()) { >- failIfTrue(isLETMaskedAsIDENT() && declarationType == DeclarationType::LexicalDeclaration, "Can't use 'let' as an identifier name for a LexicalDeclaration"); >+ failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration), >+ "Can't use 'let' as an identifier name for a LexicalDeclaration"); > JSTextPosition varStart = tokenStartPosition(); > JSTokenLocation varStartLocation(tokenLocation()); > identStart = varStart; >@@ -558,11 +544,16 @@ template <class TreeBuilder> TreeExpress > lastIdentToken = m_token; > next(); > hasInitializer = match(EQUAL); >- if (!declareVariable(name, declarationType)) { >- if (declarationType == DeclarationType::LexicalDeclaration) >- internalFailWithMessage(false, "Cannot declare a lexical variable twice: '", name->impl(), "'"); >- else if (strictMode()) >- internalFailWithMessage(false, "Cannot declare a variable named ", name->impl(), " in strict mode"); >+ DeclarationResultMask declarationResult = declareVariable(name, declarationType); >+ if (declarationResult != DeclarationResult::Valid) { >+ failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode"); >+ if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) { >+ if (declarationType == DeclarationType::LetDeclaration) >+ internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'"); >+ if (declarationType == DeclarationType::ConstDeclaration) >+ internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'"); >+ RELEASE_ASSERT_NOT_REACHED(); >+ } > } > if (hasInitializer) { > JSTextPosition varDivot = tokenStartPosition() + 1; >@@ -573,8 +564,11 @@ template <class TreeBuilder> TreeExpress > lastInitializer = initializer; > failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'"); > >- node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), AssignmentContext::DeclarationStatement); >+ node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext); > } else { >+ if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration) >+ forLoopConstDoesNotHaveInitializer = true; >+ failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer"); > if (declarationType == DeclarationType::VarDeclaration) > node = context.createEmptyVarExpression(varStartLocation, *name); > else >@@ -582,7 +576,7 @@ template <class TreeBuilder> TreeExpress > } > } else { > lastIdent = 0; >- auto pattern = parseDestructuringPattern(context, declarationType == DeclarationType::VarDeclaration ? DestructureToVariables : DestructureToLexicalVariables, AssignmentContext::DeclarationStatement); >+ auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), assignmentContext); > failIfFalse(pattern, "Cannot parse this destructuring pattern"); > hasInitializer = match(EQUAL); > failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration"); >@@ -604,7 +598,7 @@ template <class TreeBuilder> TreeExpress > tail = context.appendToCommaExpr(location, head, tail, node); > } while (match(COMMA)); > if (lastIdent) >- lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, AssignmentContext::DeclarationStatement); >+ lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext); > > return head; > } >@@ -617,13 +611,17 @@ template <class TreeBuilder> TreeDestruc > ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol()); > if (depth) { > if (kind == DestructureToVariables) >- failIfFalseIfStrict(declareVariable(&name), "Cannot deconstruct to a variable named '", name.impl(), "' in strict mode"); >- else if (kind == DestructureToLexicalVariables) >- semanticFailIfFalse(declareVariable(&name, DeclarationType::LexicalDeclaration), "Cannot declare a lexical variable twice: '", name.impl(), "'"); >- else if (kind == DestructureToParameters) { >+ failIfTrueIfStrict(declareVariable(&name) & DeclarationResult::InvalidStrictMode, "Cannot deconstruct to a variable named '", name.impl(), "' in strict mode"); >+ else if (kind == DestructureToLet || kind == DestructureToConst) { >+ DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructureToLet ? DeclarationType::LetDeclaration : DeclarationType::ConstDeclaration); >+ if (declarationResult != DeclarationResult::Valid) { >+ failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode"); >+ failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'"); >+ } >+ } else if (kind == DestructureToParameters) { > auto bindingResult = declareBoundParameter(&name); > if (bindingResult == Scope::StrictBindingFailed && strictMode()) { >- semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode"); >+ semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode"); > if (m_lastFunctionName && name == *m_lastFunctionName) > semanticFail("Cannot destructure to '", name.impl(), "' as it shadows the name of a strict mode function"); > semanticFailureDueToKeyword("bound parameter name"); >@@ -641,13 +639,17 @@ template <class TreeBuilder> TreeDestruc > > } else { > if (kind == DestructureToVariables) >- failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode"); >- else if (kind == DestructureToLexicalVariables) >- semanticFailIfFalse(declareVariable(&name, DeclarationType::LexicalDeclaration), "Cannot declare a lexical variable twice: '", name.impl(), "'"); >- else if (kind == DestructureToParameters) { >- bool declarationResult = declareParameter(&name); >- if (!declarationResult && strictMode()) { >- semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode"); >+ failIfTrueIfStrict(declareVariable(&name) & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode"); >+ else if (kind == DestructureToLet || kind == DestructureToConst) { >+ DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructureToLet ? DeclarationType::LetDeclaration : DeclarationType::ConstDeclaration); >+ if (declarationResult != DeclarationResult::Valid) { >+ failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode"); >+ failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'"); >+ } >+ } else if (kind == DestructureToParameters) { >+ DeclarationResultMask declarationResult = declareParameter(&name); >+ if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) { >+ semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode"); > if (m_lastFunctionName && name == *m_lastFunctionName) > semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function"); > semanticFailureDueToKeyword("parameter name"); >@@ -765,7 +767,7 @@ template <class TreeBuilder> TreeDestruc > TreeDestructuringPattern innerPattern = 0; > JSTokenLocation location = m_token.m_location; > if (match(IDENT) || isLETMaskedAsIDENT()) { >- failIfTrue(isLETMaskedAsIDENT() && kind == DestructureToLexicalVariables, "Can't use 'let' as an identifier name for a LexicalDeclaration"); >+ failIfTrue(match(LET) && (kind == DestructureToLet || kind == DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration"); > propertyName = *m_token.m_data.ident; > JSToken identifierToken = m_token; > next(); >@@ -827,7 +829,7 @@ template <class TreeBuilder> TreeDestruc > semanticFailureDueToKeyword("variable name"); > failWithMessage("Expected a parameter pattern or a ')' in parameter list"); > } >- failIfTrue(isLETMaskedAsIDENT() && kind == DestructureToLexicalVariables, "Can't use 'let' as an identifier name for a LexicalDeclaration"); >+ failIfTrue(match(LET) && (kind == DestructureToLet || kind == DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration"); > pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token, bindingContext); > next(); > break; >@@ -848,34 +850,6 @@ template <class TreeBuilder> TreeExpress > } > > template <typename LexerType> >-template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDeclarationList(TreeBuilder& context) >-{ >- failIfTrue(strictMode(), "Const declarations are not supported in strict mode"); >- TreeConstDeclList constDecls = 0; >- TreeConstDeclList tail = 0; >- do { >- JSTokenLocation location(tokenLocation()); >- next(); >- failIfFalse(match(IDENT), "Expected an identifier name in const declaration"); >- const Identifier* name = m_token.m_data.ident; >- next(); >- bool hasInitializer = match(EQUAL); >- // FIXME: This should be LexicalVariable when we support proper ES6 const semantics. >- declareVariable(name, DeclarationType::VarDeclaration, true); >- TreeExpression initializer = 0; >- if (hasInitializer) { >- next(TreeBuilder::DontBuildStrings); // consume '=' >- initializer = parseAssignmentExpression(context); >- failIfFalse(!!initializer, "Unable to parse initializer"); >- } >- tail = context.appendConstDecl(location, tail, name, initializer); >- if (!constDecls) >- constDecls = tail; >- } while (match(COMMA)); >- return constDecls; >-} >- >-template <typename LexerType> > template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context) > { > ASSERT(match(FOR)); >@@ -891,13 +865,15 @@ template <class TreeBuilder> TreeStateme > TreeDestructuringPattern pattern = 0; > bool isVarDeclaraton = match(VAR); > bool isLetDeclaration = match(LET); >+ bool isConstDeclaration = match(CONSTTOKEN); >+ bool forLoopConstDoesNotHaveInitializer = false; > > VariableEnvironment dummySet; > VariableEnvironment* lexicalVariables = nullptr; > AutoCleanupLexicalScope lexicalScope; > > auto gatherLexicalVariablesIfNecessary = [&] { >- if (isLetDeclaration) { >+ if (isLetDeclaration || isConstDeclaration) { > ScopeRef scope = lexicalScope.scope(); > lexicalVariables = &scope->finalizeLexicalEnvironment(); > } else >@@ -905,16 +881,16 @@ template <class TreeBuilder> TreeStateme > }; > > auto popLexicalScopeIfNecessary = [&] { >- if (isLetDeclaration) >+ if (isLetDeclaration || isConstDeclaration) > popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo); > }; > >- if (isVarDeclaraton || isLetDeclaration) { >+ if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) { > /* >- for (var/let IDENT in expression) statement >- for (var/let varDeclarationList; expressionOpt; expressionOpt) >+ for (var/let/const IDENT in/of expression) statement >+ for (var/let/const varDeclarationList; expressionOpt; expressionOpt) > */ >- if (isLetDeclaration) { >+ if (isLetDeclaration || isConstDeclaration) { > ScopeRef newScope = pushScope(); > newScope->setIsLexicalScope(); > newScope->preventVarDeclarations(); >@@ -926,7 +902,16 @@ template <class TreeBuilder> TreeStateme > m_allowsIn = false; > JSTextPosition initStart; > JSTextPosition initEnd; >- decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, isVarDeclaraton ? DeclarationType::VarDeclaration : DeclarationType::LexicalDeclaration); >+ DeclarationType declarationType; >+ if (isVarDeclaraton) >+ declarationType = DeclarationType::VarDeclaration; >+ else if (isLetDeclaration) >+ declarationType = DeclarationType::LetDeclaration; >+ else if (isConstDeclaration) >+ declarationType = DeclarationType::ConstDeclaration; >+ else >+ RELEASE_ASSERT_NOT_REACHED(); >+ decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, forLoopConstDoesNotHaveInitializer); > m_allowsIn = true; > propagateError(); > >@@ -996,6 +981,7 @@ template <class TreeBuilder> TreeStateme > // Standard for loop > next(); > TreeExpression condition = 0; >+ failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers"); > > if (!match(SEMICOLON)) { > condition = parseExpression(context); >@@ -1286,7 +1272,7 @@ template <class TreeBuilder> TreeStateme > ident = m_token.m_data.ident; > next(); > AutoPopScopeRef catchScope(this, pushScope()); >- failIfFalseIfStrict(declareVariable(ident), "Cannot declare a catch variable named '", ident->impl(), "' in strict mode"); >+ failIfTrueIfStrict(declareVariable(ident) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode"); > catchScope->preventAllVariableDeclarations(); > handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target"); > matchOrFail(OPENBRACE, "Expected exception handler to be a block statement"); >@@ -1600,7 +1586,7 @@ template <class TreeBuilder> bool Parser > m_lastFunctionName = functionInfo.name; > next(); > if (!nameIsInContainingScope) >- failIfFalseIfStrict(functionScope->declareVariable(functionInfo.name), "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode"); >+ failIfTrueIfStrict(functionScope->declareVariable(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode"); > } else if (requirements == FunctionNeedsName) { > if (match(OPENPAREN) && mode == NormalFunctionMode) > semanticFail("Function statements must have a name"); >@@ -1796,7 +1782,7 @@ template <class TreeBuilder> TreeStateme > failIfFalse((parseFunctionInfo(context, FunctionNeedsName, NormalFunctionMode, true, ConstructorKind::None, SuperBinding::NotNeeded, > functionKeywordStart, functionInfo, StandardFunctionParseType)), "Cannot parse this function"); > failIfFalse(functionInfo.name, "Function statements must have a name"); >- failIfFalseIfStrict(declareVariable(functionInfo.name), "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode"); >+ failIfTrueIfStrict(declareVariable(functionInfo.name) & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode"); > return context.createFuncDeclStatement(location, functionInfo); > } > >@@ -1836,7 +1822,7 @@ template <class TreeBuilder> TreeClassEx > className = m_token.m_data.ident; > info.className = className; > next(); >- failIfFalse(classScope->declareVariable(className), "'", className->impl(), "' is not a valid class name"); >+ failIfTrue(classScope->declareVariable(className) & DeclarationResult::InvalidStrictMode, "'", className->impl(), "' is not a valid class name"); > } else if (requirements == FunctionNeedsName) { > if (match(OPENBRACE)) > semanticFail("Class statements must have a name"); >@@ -1912,7 +1898,7 @@ template <class TreeBuilder> TreeClassEx > ParserFunctionInfo<TreeBuilder> methodInfo; > bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor; > failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, isStaticMethod ? NormalFunctionMode : MethodMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, StandardFunctionParseType)), "Cannot parse this method"); >- failIfFalse(ident && declareVariable(ident), "Cannot declare a method named '", methodInfo.name->impl(), "'"); >+ failIfTrue(!ident || (declareVariable(ident) & DeclarationResult::InvalidStrictMode), "Cannot declare a method named '", methodInfo.name->impl(), "'"); > methodInfo.name = isConstructor ? className : ident; > > TreeExpression method = context.createFunctionExpr(methodLocation, methodInfo); >Index: Source/JavaScriptCore/parser/Parser.h >=================================================================== >--- Source/JavaScriptCore/parser/Parser.h (revision 187003) >+++ Source/JavaScriptCore/parser/Parser.h (working copy) >@@ -67,7 +67,6 @@ class SourceCode; > #define TreeSourceElements typename TreeBuilder::SourceElements > #define TreeClause typename TreeBuilder::Clause > #define TreeClauseList typename TreeBuilder::ClauseList >-#define TreeConstDeclList typename TreeBuilder::ConstDeclList > #define TreeArguments typename TreeBuilder::Arguments > #define TreeArgumentsList typename TreeBuilder::ArgumentsList > #define TreeFunctionBody typename TreeBuilder::FunctionBody >@@ -84,13 +83,30 @@ enum SourceElementsMode { CheckForStrict > enum FunctionParseType { StandardFunctionParseType, ArrowFunctionParseType }; > enum FunctionBodyType { ArrowFunctionBodyExpression, ArrowFunctionBodyBlock, StandardFunctionBodyBlock }; > enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; >+ > enum DestructuringKind { > DestructureToVariables, >- DestructureToLexicalVariables, >+ DestructureToLet, >+ DestructureToConst, > DestructureToParameters, > DestructureToExpressions > }; > >+enum class DeclarationType { >+ VarDeclaration, >+ LetDeclaration, >+ ConstDeclaration >+}; >+ >+enum DeclarationResult { >+ Valid = 0, >+ InvalidStrictMode = 1 << 0, >+ InvalidDuplicateDeclaration = 1 << 1 >+}; >+ >+typedef uint8_t DeclarationResultMask; >+ >+ > template <typename T> inline bool isEvalNode() { return false; } > template <> inline bool isEvalNode<EvalNode>() { return true; } > >@@ -99,6 +115,19 @@ struct ScopeLabelInfo { > bool isLoop; > }; > >+ALWAYS_INLINE static bool isArguments(const VM* vm, const Identifier* ident) >+{ >+ return vm->propertyNames->arguments == *ident; >+} >+ALWAYS_INLINE static bool isEval(const VM* vm, const Identifier* ident) >+{ >+ return vm->propertyNames->eval == *ident; >+} >+ALWAYS_INLINE static bool isEvalOrArgumentsIdentifier(const VM* vm, const Identifier* ident) >+{ >+ return isEval(vm, ident) || isArguments(vm, ident); >+} >+ > struct Scope { > Scope(const VM* vm, bool isFunction, bool strictMode) > : m_vm(vm) >@@ -236,28 +265,37 @@ struct Scope { > addResult.iterator->value.clearIsVar(); > } > >- bool declareVariable(const Identifier* ident, bool isConstant = false) >+ DeclarationResultMask declareVariable(const Identifier* ident) > { > ASSERT(m_allowsVarDeclarations); >- bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident; >+ DeclarationResultMask result = DeclarationResult::Valid; >+ bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident); > m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; > auto addResult = m_declaredVariables.add(ident->impl()); > addResult.iterator->value.setIsVar(); >- if (isConstant) >- addResult.iterator->value.setIsConstant(); >- >- return isValidStrictMode; >+ if (!isValidStrictMode) >+ result |= DeclarationResult::InvalidStrictMode; >+ return result; > } > >- bool declareLexicalVariable(const Identifier* ident) >+ DeclarationResultMask declareLexicalVariable(const Identifier* ident, bool isConstant) > { > ASSERT(m_allowsLexicalDeclarations); >- bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident; >+ DeclarationResultMask result = DeclarationResult::Valid; >+ bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident); > m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; > auto addResult = m_lexicalVariables.add(ident->impl()); >- addResult.iterator->value.setIsLet(); >- bool successfulDeclaration = addResult.isNewEntry && isValidStrictMode; >- return successfulDeclaration; >+ if (isConstant) >+ addResult.iterator->value.setIsConst(); >+ else >+ addResult.iterator->value.setIsLet(); >+ >+ if (!addResult.isNewEntry) >+ result |= DeclarationResult::InvalidDuplicateDeclaration; >+ if (!isValidStrictMode) >+ result |= DeclarationResult::InvalidStrictMode; >+ >+ return result; > } > > bool hasDeclaredVariable(const Identifier& ident) >@@ -300,19 +338,22 @@ struct Scope { > bool allowsVarDeclarations() const { return m_allowsVarDeclarations; } > bool allowsLexicalDeclarations() const { return m_allowsLexicalDeclarations; } > >- bool declareParameter(const Identifier* ident) >+ DeclarationResultMask declareParameter(const Identifier* ident) > { > ASSERT(m_allowsVarDeclarations); >- bool isArguments = m_vm->propertyNames->arguments == *ident; >+ DeclarationResultMask result = DeclarationResult::Valid; >+ bool isArgumentsIdent = isArguments(m_vm, ident); > auto addResult = m_declaredVariables.add(ident->impl()); > addResult.iterator->value.clearIsVar(); >- bool isValidStrictMode = addResult.isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; >+ bool isValidStrictMode = addResult.isNewEntry && m_vm->propertyNames->eval != *ident && !isArgumentsIdent; > m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; > m_declaredParameters.add(ident->impl()); >- >- if (isArguments) >+ if (!isValidStrictMode) >+ result |= DeclarationResult::InvalidStrictMode; >+ if (isArgumentsIdent) > m_shadowsArguments = true; >- return isValidStrictMode; >+ >+ return result; > } > > enum BindingResult { >@@ -322,13 +363,13 @@ struct Scope { > }; > BindingResult declareBoundParameter(const Identifier* ident) > { >- bool isArguments = m_vm->propertyNames->arguments == *ident; >+ bool isArgumentsIdent = isArguments(m_vm, ident); > auto addResult = m_declaredVariables.add(ident->impl()); > addResult.iterator->value.setIsVar(); // Treat destructuring parameters as "var"s. >- bool isValidStrictMode = addResult.isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; >+ bool isValidStrictMode = addResult.isNewEntry && !isEval(m_vm, ident) && !isArgumentsIdent; > m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; > >- if (isArguments) >+ if (isArgumentsIdent) > m_shadowsArguments = true; > if (!addResult.isNewEntry) > return BindingFailed; >@@ -615,6 +656,33 @@ private: > Parser* m_parser; > }; > >+ ALWAYS_INLINE DestructuringKind destructuringKindFromDeclarationType(DeclarationType type) >+ { >+ switch (type) { >+ case DeclarationType::VarDeclaration: >+ return DestructureToVariables; >+ case DeclarationType::LetDeclaration: >+ return DestructureToLet; >+ case DeclarationType::ConstDeclaration: >+ return DestructureToConst; >+ } >+ >+ RELEASE_ASSERT_NOT_REACHED(); >+ return DestructureToVariables; >+ } >+ >+ ALWAYS_INLINE AssignmentContext assignmentContextFromDeclarationType(DeclarationType type) >+ { >+ switch (type) { >+ case DeclarationType::ConstDeclaration: >+ return AssignmentContext::ConstDeclarationStatement; >+ default: >+ return AssignmentContext::DeclarationStatement; >+ } >+ } >+ >+ ALWAYS_INLINE bool isEvalOrArguments(const Identifier* ident) { return isEvalOrArgumentsIdentifier(m_vm, ident); } >+ > ScopeRef currentScope() > { > return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); >@@ -661,8 +729,7 @@ private: > popScopeInternal(scope, shouldTrackClosedVariables); > } > >- enum class DeclarationType { VarDeclaration, LexicalDeclaration }; >- bool declareVariable(const Identifier* ident, typename Parser::DeclarationType type = DeclarationType::VarDeclaration, bool isConstant = false) >+ DeclarationResultMask declareVariable(const Identifier* ident, DeclarationType type = DeclarationType::VarDeclaration) > { > unsigned i = m_scopeStack.size() - 1; > ASSERT(i < m_scopeStack.size()); >@@ -673,21 +740,21 @@ private: > ASSERT(i < m_scopeStack.size()); > } > >- return m_scopeStack[i].declareVariable(ident, isConstant); >+ return m_scopeStack[i].declareVariable(ident); > } > >- ASSERT(type == DeclarationType::LexicalDeclaration); >+ ASSERT(type == DeclarationType::LetDeclaration || type == DeclarationType::ConstDeclaration); > > // Lexical variables declared at a top level scope that shadow arguments or vars are not allowed. > if (m_statementDepth == 1 && (hasDeclaredParameter(*ident) || hasDeclaredVariable(*ident))) >- return false; >+ return DeclarationResult::InvalidDuplicateDeclaration; > > while (!m_scopeStack[i].allowsLexicalDeclarations()) { > i--; > ASSERT(i < m_scopeStack.size()); > } > >- return m_scopeStack[i].declareLexicalVariable(ident); >+ return m_scopeStack[i].declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration); > } > > NEVER_INLINE bool hasDeclaredVariable(const Identifier& ident) >@@ -894,7 +961,7 @@ private: > void setStrictMode() { currentScope()->setStrictMode(); } > bool strictMode() { return currentScope()->strictMode(); } > bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } >- bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } >+ DeclarationResultMask declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } > Scope::BindingResult declareBoundParameter(const Identifier* ident) { return currentScope()->declareBoundParameter(ident); } > bool breakIsValid() > { >@@ -943,7 +1010,6 @@ private: > #endif > template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&); > template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType); >- template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&); > template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&); > template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&); > template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&); >@@ -979,8 +1045,7 @@ private: > template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, const JSTokenLocation&, int, int functionKeywordStart, int functionNameStart, int parametersStart, ConstructorKind, FunctionBodyType, unsigned, FunctionParseMode); > template <class TreeBuilder> ALWAYS_INLINE bool parseFormalParameters(TreeBuilder&, TreeFormalParameterList, unsigned&); > enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext }; >- template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType); >- template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&); >+ template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType, bool& forLoopConstDoesNotHaveInitializer); > template <class TreeBuilder> TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&); > template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&); > template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, const Identifier&, int depth, JSToken, AssignmentContext); >Index: Source/JavaScriptCore/parser/SyntaxChecker.h >=================================================================== >--- Source/JavaScriptCore/parser/SyntaxChecker.h (revision 187003) >+++ Source/JavaScriptCore/parser/SyntaxChecker.h (working copy) >@@ -127,7 +127,6 @@ public: > typedef int Statement; > typedef int ClauseList; > typedef int Clause; >- typedef int ConstDeclList; > typedef int BinaryOperand; > typedef int DestructuringPattern; > typedef DestructuringPattern ArrayPattern; >@@ -236,8 +235,7 @@ public: > int createForInLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; } > int createForOfLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; } > int createEmptyStatement(const JSTokenLocation&) { return StatementResult; } >- int createVarStatement(const JSTokenLocation&, int, int, int) { return StatementResult; } >- int createLetStatement(const JSTokenLocation&, int, int, int) { return StatementResult; } >+ int createDeclarationStatement(const JSTokenLocation&, int, int, int) { return StatementResult; } > int createReturnStatement(const JSTokenLocation&, int, int, int) { return StatementResult; } > int createBreakStatement(const JSTokenLocation&, int, int) { return StatementResult; } > int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; } >Index: Source/JavaScriptCore/parser/VariableEnvironment.h >=================================================================== >--- Source/JavaScriptCore/parser/VariableEnvironment.h (revision 187003) >+++ Source/JavaScriptCore/parser/VariableEnvironment.h (working copy) >@@ -35,12 +35,12 @@ namespace JSC { > struct VariableEnvironmentEntry { > public: > ALWAYS_INLINE bool isCaptured() const { return m_bits & IsCaptured; } >- ALWAYS_INLINE bool isConstant() const { return m_bits & IsConstant; } >+ ALWAYS_INLINE bool isConst() const { return m_bits & IsConst; } > ALWAYS_INLINE bool isVar() const { return m_bits & IsVar; } > ALWAYS_INLINE bool isLet() const { return m_bits & IsLet; } > > ALWAYS_INLINE void setIsCaptured() { m_bits |= IsCaptured; } >- ALWAYS_INLINE void setIsConstant() { m_bits |= IsConstant; } >+ ALWAYS_INLINE void setIsConst() { m_bits |= IsConst; } > ALWAYS_INLINE void setIsVar() { m_bits |= IsVar; } > ALWAYS_INLINE void setIsLet() { m_bits |= IsLet; } > >@@ -49,7 +49,7 @@ public: > private: > enum Traits { > IsCaptured = 1 << 0, >- IsConstant = 1 << 1, >+ IsConst = 1 << 1, > IsVar = 1 << 2, > IsLet = 1 << 3 > }; >Index: Source/JavaScriptCore/runtime/Executable.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/Executable.cpp (revision 187003) >+++ Source/JavaScriptCore/runtime/Executable.cpp (working copy) >@@ -522,10 +522,8 @@ JSObject* ProgramExecutable::initializeG > > const VariableEnvironment& variableDeclarations = unlinkedCodeBlock->variableDeclarations(); > for (auto& entry : variableDeclarations) { >- if (entry.value.isConstant()) >- globalObject->addConst(callFrame, Identifier::fromUid(&vm, entry.key.get())); >- else >- globalObject->addVar(callFrame, Identifier::fromUid(&vm, entry.key.get())); >+ ASSERT(entry.value.isVar()); >+ globalObject->addVar(callFrame, Identifier::fromUid(&vm, entry.key.get())); > } > return 0; > } >Index: Source/JavaScriptCore/runtime/JSGlobalObject.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSGlobalObject.cpp (revision 187003) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.cpp (working copy) >@@ -570,7 +570,7 @@ bool JSGlobalObject::defineOwnProperty(J > return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); > } > >-void JSGlobalObject::addGlobalVar(const Identifier& ident, ConstantMode constantMode) >+void JSGlobalObject::addGlobalVar(const Identifier& ident) > { > ConcurrentJITLocker locker(symbolTable()->m_lock); > SymbolTableEntry entry = symbolTable()->get(locker, ident.impl()); >@@ -578,11 +578,8 @@ void JSGlobalObject::addGlobalVar(const > return; > > ScopeOffset offset = symbolTable()->takeNextScopeOffset(locker); >- SymbolTableEntry newEntry(VarOffset(offset), (constantMode == IsConstant) ? ReadOnly : 0); >- if (constantMode == IsVariable) >- newEntry.prepareToWatch(); >- else >- newEntry.disableWatching(); >+ SymbolTableEntry newEntry(VarOffset(offset), 0); >+ newEntry.prepareToWatch(); > symbolTable()->add(locker, ident.impl(), newEntry); > > ScopeOffset offsetForAssert = addVariables(1); >@@ -593,7 +590,7 @@ void JSGlobalObject::addFunction(ExecSta > { > VM& vm = exec->vm(); > removeDirect(vm, propertyName); // Newly declared functions overwrite existing properties. >- addGlobalVar(propertyName, IsVariable); >+ addGlobalVar(propertyName); > } > > static inline JSObject* lastInPrototypeChain(JSObject* object) >Index: Source/JavaScriptCore/runtime/JSGlobalObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSGlobalObject.h (revision 187003) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.h (working copy) >@@ -23,7 +23,6 @@ > #define JSGlobalObject_h > > #include "ArrayAllocationProfile.h" >-#include "ConstantMode.h" > #include "JSArray.h" > #include "JSArrayBufferPrototype.h" > #include "JSClassRef.h" >@@ -357,7 +356,7 @@ protected: > setGlobalThis(vm, thisValue); > } > >- void addGlobalVar(const Identifier&, ConstantMode); >+ void addGlobalVar(const Identifier&); > > public: > JS_EXPORT_PRIVATE ~JSGlobalObject(); >@@ -382,12 +381,7 @@ public: > void addVar(ExecState* exec, const Identifier& propertyName) > { > if (!hasProperty(exec, propertyName)) >- addGlobalVar(propertyName, IsVariable); >- } >- void addConst(ExecState* exec, const Identifier& propertyName) >- { >- if (!hasProperty(exec, propertyName)) >- addGlobalVar(propertyName, IsConstant); >+ addGlobalVar(propertyName); > } > void addFunction(ExecState*, const Identifier&); > >Index: Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp (revision 187003) >+++ Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp (working copy) >@@ -70,7 +70,7 @@ inline bool JSLexicalEnvironment::symbol > return false; > ASSERT(!iter->value.isNull()); > if (iter->value.isReadOnly()) { >- if (shouldThrow) >+ if (shouldThrow || isLexicalScope()) > throwTypeError(exec, StrictModeReadonlyPropertyWriteError); > return true; > } >Index: Source/JavaScriptCore/tests/stress/const-and-with-statement.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/const-and-with-statement.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/const-and-with-statement.js (working copy) >@@ -0,0 +1,115 @@ >+function truth() { >+ return true; >+} >+noInline(truth); >+ >+function assert(cond) { >+ if (!cond) >+ throw new Error("broke assertion"); >+} >+noInline(assert); >+ >+function shouldThrowInvalidConstAssignment(f) { >+ var threw = false; >+ try { >+ f(); >+ } catch(e) { >+ if (e.name.indexOf("TypeError") !== -1 && e.message.indexOf("readonly") !== -1) >+ threw = true; >+ } >+ assert(threw); >+} >+noInline(shouldThrowInvalidConstAssignment); >+ >+ >+// Tests >+ >+const NUM_LOOPS = 10000; >+ >+;(function() { >+ function foo() { >+ const x = 40; >+ with ({x : 100}) { >+ assert(x === 100); >+ } >+ with ({y : 100}) { >+ assert(x === 40); >+ } >+ } >+ noInline(foo); >+ >+ function bar() { >+ const x = 40; >+ function capX() { return x; } >+ with ({x : 100}) { >+ if (truth()) { >+ const x = 50; >+ const capX = function() { return x; } >+ assert(x === 50); >+ assert(capX() === x); >+ } >+ assert(x === 100); >+ assert(capX() === 40); >+ } >+ with ({y : 100}) { >+ if (truth()) { >+ const x = 50; >+ const capX = function() { return x; } >+ assert(x === 50); >+ assert(capX() === x); >+ } >+ assert(x === 40); >+ assert(capX() === 40); >+ } >+ } >+ noInline(bar); >+ >+ function baz() { >+ const x = 40; >+ function capX() { return x; } >+ with ({x : 100}) { >+ if (truth()) { >+ const x = 50; >+ assert(x === 50); >+ } >+ assert(x === 100); >+ assert(capX() === 40); >+ } >+ with ({y : 100}) { >+ if (truth()) { >+ const x = 50; >+ assert(x === 50); >+ } >+ assert(x === 40); >+ assert(capX() === 40); >+ } >+ } >+ noInline(baz); >+ >+ for (let i = 0; i < NUM_LOOPS; i++) { >+ foo(); >+ bar(); >+ baz(); >+ } >+})(); >+ >+ >+;(function() { >+ function foo() { >+ const x = 40; >+ with ({x : 100}) { >+ assert(x === 100); >+ x = 20; >+ assert(x === 20); >+ } >+ assert(x === 40); >+ with ({y : 100}) { >+ assert(x === 40); >+ x = 100; >+ } >+ } >+ for (let i = 0; i < NUM_LOOPS; ++i) { >+ shouldThrowInvalidConstAssignment(foo); >+ } >+ >+})(); >Index: Source/JavaScriptCore/tests/stress/const-exception-handling.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/const-exception-handling.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/const-exception-handling.js (working copy) >@@ -0,0 +1,204 @@ >+"use strict"; >+ >+function truth() { >+ return true; >+} >+noInline(truth); >+ >+function assert(cond) { >+ if (!cond) >+ throw new Error("broke assertion"); >+} >+noInline(assert); >+ >+// Tests >+ >+ >+const NUM_LOOPS = 10000; >+ >+;(function () { >+function foo() { >+ const x = 20; >+ const y = "y"; >+ try { >+ assert(x === 20); >+ assert(y === "y"); >+ throw "error"; >+ } catch(e) { >+ assert(x === 20); >+ } finally { >+ assert(x === 20); >+ assert(y === "y"); >+ } >+ >+ for (let i = 0; i < 1; i++) { >+ let numFinally = 0; >+ try { >+ let a = 40; >+ let capA = function() { return a; } >+ assert(capA() === 40); >+ try { >+ const b = 41; >+ const capB = function() { return b; } >+ assert(capB() === 41); >+ assert(capA() === 40); >+ try { >+ return 20; >+ } catch(e){ >+ } finally { >+ const c = 42; >+ const capC = function() { return c; } >+ assert(capC() === 42); >+ assert(capB() === 41); >+ assert(capA() === 40); >+ if (i === 0) { >+ numFinally++; >+ } >+ return 22; >+ } >+ } catch(e) { >+ } finally { >+ if (i === 0) { >+ numFinally++; >+ } >+ return 23; >+ } >+ } catch(e) { >+ } finally { >+ if (i === 0) { >+ numFinally++; >+ } >+ assert(numFinally === 3); >+ return 24; >+ } >+ } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ assert(foo() === 24); >+} >+ >+})(); >+ >+ >+;(function () { >+function foo() { >+ for (let i = 0; i < 1; i++) { >+ let numFinally = 0; >+ let numErrors = 0; >+ try { >+ let a = 40; >+ let capA = function() { return a; } >+ assert(capA() === 40); >+ try { >+ const b = 41; >+ const capB = function() { return b; } >+ assert(capB() === 41); >+ assert(capA() === 40); >+ try { >+ throw "e"; >+ } catch(e) { >+ assert(i === 0); >+ assert(capB() === 41); >+ assert(capA() === 40); >+ numErrors++; >+ throw e; >+ } finally { >+ const c = 42; >+ const capC = function() { return c; } >+ const local = "local"; >+ assert(local === "local"); >+ assert(capC() === 42); >+ assert(capB() === 41); >+ assert(capA() === 40); >+ if (i === 0) { >+ numFinally++; >+ } >+ } >+ } catch(e) { >+ assert(i === 0); >+ assert(capA() === 40); >+ numErrors++; >+ const local = "local"; >+ assert(local === "local"); >+ } finally { >+ assert(capA() === 40); >+ if (i === 0) { >+ numFinally++; >+ } >+ const local = "local"; >+ assert(local === "local"); >+ return 23; >+ } >+ } catch(e) { >+ //assert(i === 0); >+ } finally { >+ if (i === 0) { >+ numFinally++; >+ } >+ >+ assert(numFinally === 3); >+ assert(numErrors === 2); >+ return 24; >+ } >+ } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ assert(foo() === 24); >+} >+ >+})(); >+ >+ >+var d = 100; >+;(function (){ >+function foo() { >+ assert(d === 100); >+ for (let i = 0; i < 1; i++) { >+ let numFinally = 0; >+ let numErrors = 0; >+ const c = 44; >+ assert(d === 100); >+ try { >+ const d = 45; >+ if (truth()) { >+ const a = 20; >+ const capA = function() { return a; } >+ assert(capA() === 20); >+ if (truth()) { >+ const b = 21; >+ const e = 48; >+ const capB = function() { return b; } >+ assert(capB() === 21); >+ assert(d === 45); >+ try { >+ throw "e"; >+ } catch(e) { >+ assert(capA() === 20); >+ assert(a === 20); >+ numErrors++; >+ } finally { >+ assert(capA() === 20); >+ assert(e === 48); >+ numFinally++; >+ return 30; >+ } >+ } >+ } >+ } finally { >+ assert(c === 44); >+ assert(d === 100); >+ numFinally++; >+ assert(numFinally === 2); >+ assert(numErrors === 1); >+ return 40; >+ } >+ } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ assert(foo() === 40); >+} >+ >+})(); >Index: Source/JavaScriptCore/tests/stress/const-loop-semantics.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/const-loop-semantics.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/const-loop-semantics.js (working copy) >@@ -0,0 +1,130 @@ >+"use strict"; >+function truth() { >+ return true; >+} >+noInline(truth); >+ >+function assert(cond) { >+ if (!cond) >+ throw new Error("broke assertion"); >+} >+noInline(assert); >+function shouldThrowInvalidConstAssignment(f) { >+ var threw = false; >+ try { >+ f(); >+ } catch(e) { >+ if (e.name.indexOf("TypeError") !== -1 && e.message.indexOf("readonly") !== -1) >+ threw = true; >+ } >+ assert(threw); >+} >+noInline(shouldThrowInvalidConstAssignment); >+ >+ >+// ========== tests below =========== >+ >+const NUM_LOOPS = 10000; >+ >+;(function() { >+ function foo() { >+ const obj = {a: 20, b: 40, c: 50}; >+ const props = []; >+ for (const p in obj) >+ props.push(p); >+ assert(props.length === 3); >+ for (const p of props) >+ assert(!!obj[p]); >+ assert(props.indexOf("a") !== -1); >+ assert(props.indexOf("b") !== -1); >+ assert(props.indexOf("c") !== -1); >+ } >+ >+ function bar() { >+ const funcs = []; >+ for (const item of [1, 2, 3]) >+ funcs.push(function() { return item; }); >+ let i = 1; >+ assert(funcs.length === 3); >+ for (const f of funcs) { >+ assert(f() === i); >+ i++; >+ } >+ } >+ function baz() { >+ const funcs = []; >+ const obj = {a:1, b:2, c:3}; >+ for (const p in obj) >+ funcs.push(function() { return p; }); >+ let i = 1; >+ assert(funcs.length === 3); >+ for (const f of funcs) { >+ assert(obj[f()] === i); >+ i++; >+ } >+ } >+ function taz() { >+ for (const item of [1,2,3]) { >+ const item = 20; >+ assert(item === 20); >+ } >+ } >+ function jaz() { >+ let i = 0; >+ for (const x = 40; i < 10; i++) { >+ assert(x === 40); >+ } >+ } >+ for (var i = 0; i < NUM_LOOPS; i++) { >+ foo(); >+ bar(); >+ baz(); >+ taz(); >+ jaz(); >+ } >+})(); >+ >+;(function() { >+ function foo() { >+ for (const item of [1,2,3]) >+ item = 20; >+ } >+ function bar() { >+ for (const item of [1,2,3]) >+ eval("item = 20") >+ } >+ function baz() { >+ for (const p in {a: 20, b: 40}) >+ p = 20; >+ } >+ function taz() { >+ for (const p in {a: 20, b: 40}) >+ eval("p = 20") >+ } >+ function jaz() { >+ for (const x = 0; x < 10; x++) { } >+ } >+ function raz() { >+ for (const x = 0; x < 10; ++x) { } >+ } >+ function paz() { >+ for (const x = 0; x < 10; x++) { >+ let f = function() { return x; } >+ } >+ } >+ function maz() { >+ for (const x = 0; x < 10; ++x) { >+ let f = function() { return x; } >+ } >+ } >+ for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowInvalidConstAssignment(foo); >+ shouldThrowInvalidConstAssignment(bar); >+ shouldThrowInvalidConstAssignment(baz); >+ shouldThrowInvalidConstAssignment(taz); >+ shouldThrowInvalidConstAssignment(jaz); >+ shouldThrowInvalidConstAssignment(raz); >+ shouldThrowInvalidConstAssignment(paz); >+ shouldThrowInvalidConstAssignment(maz); >+ } >+})(); >Index: Source/JavaScriptCore/tests/stress/const-not-strict-mode.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/const-not-strict-mode.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/const-not-strict-mode.js (working copy) >@@ -0,0 +1,147 @@ >+function truth() { >+ return true; >+} >+noInline(truth); >+ >+function assert(cond) { >+ if (!cond) >+ throw new Error("broke assertion"); >+} >+noInline(assert); >+ >+function shouldThrowTDZ(func) { >+ var hasThrown = false; >+ try { >+ func(); >+ } catch(e) { >+ if (e.name.indexOf("ReferenceError") !== -1) >+ hasThrown = true; >+ } >+ assert(hasThrown); >+} >+noInline(shouldThrowTDZ); >+ >+ >+// Tests >+ >+ >+const NUM_LOOPS = 10000; >+ >+;(function() { >+function foo() { >+ delete x; >+ const x = 20; >+} >+function bar() { >+ delete x; >+ const x = 20; >+ function capX() { return x; } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+} >+ >+})(); >+ >+ >+;(function() { >+ >+function foo() { >+ var hadError = false; >+ try { >+ x; >+ } catch(e) { >+ hadError = true; >+ } >+ assert(hadError); >+ >+ if (truth()) { >+ // This eval is enterpreted as follows: >+ // eval("var x; x = 20"); >+ // We first assign undefined to the "var x". >+ // Then, we interperet an assignment expression >+ // into the resolved variable x. x resolves to the lexical "const x;" >+ // Look at ECMA section 13.3.2.4 of the ES6 spec: >+ // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-variable-statement-runtime-semantics-evaluation >+ // And also look at section 8.3.1 ResolveBinding: >+ // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-resolvebinding >+ const x = 40; >+ let threw = false; >+ try { >+ eval("var x = 20;"); >+ } catch(e) { >+ if (e.name.indexOf("TypeError") !== -1 && e.message.indexOf("readonly") !== -1) >+ threw = true; >+ } >+ assert(threw); >+ assert(x === 40); >+ } >+ assert(x === undefined); >+} >+ >+function bar() { >+ var hadError = false; >+ try { >+ x; >+ } catch(e) { >+ hadError = true; >+ } >+ assert(hadError); >+ >+ if (truth()) { >+ const x = 40; >+ function capX() { return x; } >+ let threw = false; >+ try { >+ eval("var x = 20;"); >+ } catch(e) { >+ if (e.name.indexOf("TypeError") !== -1 && e.message.indexOf("readonly") !== -1) >+ threw = true; >+ } >+ assert(threw); >+ assert(x === 40); >+ } >+ assert(x === undefined); >+} >+ >+function baz() { >+ if (truth()) { >+ const x = 40; >+ eval("const x = 20; assert(x === 20);"); >+ assert(x === 40); >+ } >+ if (truth()) { >+ const x = 40; >+ function capX() { return x; } >+ eval("const x = 20; assert(x === 20);"); >+ assert(x === 40); >+ } >+} >+ >+function baz() { >+ // Test eval() caching. >+ const x = 20; >+ const evalString = "x;"; >+ >+ assert(eval(evalString) === 20); >+ if (truth()) { >+ const y = 60; >+ assert(eval(evalString) === 20); >+ assert(y === 60); >+ if (truth()) { >+ const y = 50, z = 70, x = 40; >+ assert(eval(evalString) === 40); >+ assert(y === 50 && z === 70); >+ } >+ } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ foo(); >+ bar(); >+ baz(); >+} >+ >+})(); >Index: Source/JavaScriptCore/tests/stress/const-semantics.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/const-semantics.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/const-semantics.js (working copy) >@@ -0,0 +1,262 @@ >+"use strict"; >+function truth() { >+ return true; >+} >+noInline(truth); >+ >+function assert(cond) { >+ if (!cond) >+ throw new Error("broke assertion"); >+} >+noInline(assert); >+function shouldThrowInvalidConstAssignment(f) { >+ var threw = false; >+ try { >+ f(); >+ } catch(e) { >+ if (e.name.indexOf("TypeError") !== -1 && e.message.indexOf("readonly") !== -1) >+ threw = true; >+ } >+ assert(threw); >+} >+noInline(shouldThrowInvalidConstAssignment); >+ >+ >+// ========== tests below =========== >+ >+const NUM_LOOPS = 10000; >+ >+ >+;(function() { >+ function foo() { >+ const x = 40; >+ const {y} = {y: 50}, [z] = [60]; >+ assert(x === 40); >+ assert(y === 50); >+ assert(z === 60); >+ } >+ function bar() { >+ const x = 40; >+ const {y} = {y: 50}, [z] = [60]; >+ function capture() { return x + y + z; } >+ assert(x === 40); >+ assert(y === 50); >+ assert(z === 60); >+ assert(capture() === 150); >+ if (truth()) { >+ const x = "x"; >+ assert(x === "x"); >+ if (truth()) { >+ let x = 100; >+ const y = 200; >+ assert(x === 100); >+ assert(y === 200); >+ >+ x = 10; >+ assert(x === 10); >+ } >+ assert(x === "x"); >+ } >+ assert(x === 40); >+ } >+ function baz() { >+ let y = 10; >+ function sideEffects() { >+ y = 20; >+ } >+ >+ const x = 10; >+ try { >+ x = sideEffects(); >+ } catch(e) {} >+ assert(y === 20); >+ assert(x === 10); >+ >+ try { >+ x = y = 30; >+ } catch(e) {} >+ assert(y === 30); >+ assert(x === 10); >+ } >+ function taz() { >+ let y = 10; >+ let z; >+ function sideEffects() { >+ y = 20; >+ return ["hello", "world"]; >+ } >+ >+ const x = 10; >+ try { >+ [z, x] = sideEffects(); >+ } catch(e) {} >+ assert(y === 20); >+ assert(x === 10); >+ assert(z === "hello"); >+ } >+ function jaz() { >+ const x = "x"; >+ function capX() { return x; } >+ assert(x === "x"); >+ assert(capX() === "x"); >+ if (truth()) { >+ let y = 40; >+ let capY = function() { return y; } >+ assert(x === "x"); >+ assert(capX() === "x"); >+ } >+ assert(x === "x"); >+ assert(capX() === "x"); >+ } >+ for (var i = 0; i < NUM_LOOPS; i++) { >+ foo(); >+ bar(); >+ baz(); >+ jaz(); >+ } >+})(); >+ >+ >+;(function() { >+ function foo() { >+ const x = 40; >+ x = 30; >+ } >+ function bar() { >+ const x = 40; >+ function capX() { return x; } >+ x = 30; >+ } >+ function baz() { >+ const x = 40; >+ assert(x === 40); >+ function bad() { x = 10; } >+ bad(); >+ } >+ function jaz() { >+ const x = 40; >+ assert(x === 40); >+ function bad() { eval("x = 10"); } >+ bad(); >+ } >+ function faz() { >+ const x = 40; >+ assert(x === 40); >+ eval("x = 10"); >+ } >+ function raz() { >+ const x = 40; >+ assert(x === 40); >+ ;({x} = {x: 20}); >+ } >+ function taz() { >+ const x = 40; >+ function capX() { return x; } >+ assert(capX() === 40); >+ ;({x} = {x: 20}); >+ } >+ function paz() { >+ const x = 20; >+ const y = x = 20; >+ } >+ for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowInvalidConstAssignment(foo); >+ shouldThrowInvalidConstAssignment(bar); >+ shouldThrowInvalidConstAssignment(baz); >+ shouldThrowInvalidConstAssignment(jaz); >+ shouldThrowInvalidConstAssignment(faz); >+ shouldThrowInvalidConstAssignment(raz); >+ shouldThrowInvalidConstAssignment(taz); >+ shouldThrowInvalidConstAssignment(paz); >+ } >+})(); >+ >+ >+;(function() { >+ function foo() { >+ const x = 40; >+ eval("x = 30;"); >+ } >+ function bar() { >+ const x = 20; >+ x += 20; >+ } >+ function baz() { >+ const x = 20; >+ x -= 20; >+ } >+ function taz() { >+ const x = 20; >+ shouldThrowInvalidConstAssignment(function() { x = 20; }); >+ shouldThrowInvalidConstAssignment(function() { x += 20; }); >+ shouldThrowInvalidConstAssignment(function() { x -= 20; }); >+ shouldThrowInvalidConstAssignment(function() { x *= 20; }); >+ shouldThrowInvalidConstAssignment(function() { x /= 20; }); >+ shouldThrowInvalidConstAssignment(function() { x >>= 20; }); >+ shouldThrowInvalidConstAssignment(function() { x <<= 20; }); >+ shouldThrowInvalidConstAssignment(function() { x ^= 20; }); >+ shouldThrowInvalidConstAssignment(function() { x++; }); >+ shouldThrowInvalidConstAssignment(function() { x--; }); >+ shouldThrowInvalidConstAssignment(function() { ++x; }); >+ shouldThrowInvalidConstAssignment(function() { --x; }); >+ } >+ function jaz() { >+ const x = 20; >+ let threw = false; >+ try { x = 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x += 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x -= 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x *= 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x /= 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x >>= 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x <<= 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x ^= 20; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { x++; } catch(e) { threw = true} >+ assert(threw); >+ >+ >+ threw = false; >+ try { x--; } catch(e) { threw = true} >+ assert(threw); >+ >+ >+ threw = false; >+ try { ++x; } catch(e) { threw = true} >+ assert(threw); >+ >+ threw = false; >+ try { --x; } catch(e) { threw = true}; >+ assert(threw); >+ } >+ for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowInvalidConstAssignment(foo); >+ shouldThrowInvalidConstAssignment(bar); >+ shouldThrowInvalidConstAssignment(baz); >+ taz(); >+ jaz(); >+ } >+})(); >Index: Source/JavaScriptCore/tests/stress/const-tdz.js >=================================================================== >--- Source/JavaScriptCore/tests/stress/const-tdz.js (revision 0) >+++ Source/JavaScriptCore/tests/stress/const-tdz.js (working copy) >@@ -0,0 +1,449 @@ >+"use strict"; >+ >+function truth() { >+ return true; >+} >+noInline(truth); >+ >+function assert(cond) { >+ if (!cond) >+ throw new Error("broke assertion"); >+} >+noInline(assert); >+ >+function shouldThrowTDZ(func) { >+ var hasThrown = false; >+ try { >+ func(); >+ } catch(e) { >+ if (e.name.indexOf("ReferenceError") !== -1) >+ hasThrown = true; >+ } >+ assert(hasThrown); >+} >+noInline(shouldThrowTDZ); >+ >+// Test cases >+ >+const NUM_LOOPS = 10000; >+ >+;(function() { >+function foo() { >+ x; >+ const x = 20; >+} >+function bar() { >+ const x = x; >+} >+function baz() { >+ const {x: prop, y: prop2} = {x: prop}; >+} >+function jaz() { >+ const {x: prop, y: prop2} = {x: 20, y: prop}; >+} >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+ shouldThrowTDZ(baz); >+ shouldThrowTDZ(jaz); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ x; >+ const x = 20; >+ function captureX() { return x; } >+} >+function bar() { >+ captureX(); >+ const x = 20; >+ function captureX() { return x; } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ if (truth()) { >+ const x = 20; >+ assert(x === 20); >+ } >+ x; >+ const x = 20; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+ >+;(function() { >+function foo() { >+ if (truth()) { >+ const y = 20; >+ const captureY = function() { return y; } >+ assert(y === 20); >+ x; >+ } >+ const x = 20; >+ const y = 40; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ if (truth()) { >+ const y = 20; >+ const x = 40; >+ const captureAll = function() { return x + y; } >+ assert(y === 20); >+ assert(x === 40); >+ assert(captureAll() === 60); >+ } >+ tdz; >+ const tdz = 20; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ if (truth()) { >+ const y = 20; >+ const x = 40; >+ const captureAll = function() { return x + y + tdz; } >+ assert(y === 20); >+ assert(x === 40); >+ } >+ tdz; >+ const tdz = 20; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ x = 10; >+ const x = 20; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ x = 10; >+ const x = 20; >+ function cap() { return x; } >+} >+function bar() { >+ captureX(); >+ const x = 20; >+ function captureX() { return x; } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ if (!truth()) { >+ y; >+ assert(false); >+ } >+ const y = undefined; >+ assert(y === undefined); >+ if (truth()) { >+ x; >+ } >+ const x = undefined; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ eval("x;"); >+ const x = 20; >+} >+function bar() { >+ function captureX() { return x; } >+ eval("captureX();"); >+ const x = 20; >+} >+function baz() { >+ function captureX() { return x; } >+ function other() { return captureX; } >+ other()(); >+ const x = 20; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+ shouldThrowTDZ(baz); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ const y = 40; >+ eval("y; x;"); >+ const x = 20; >+} >+ >+for (var i = 0; i < 1; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ const x = 20; >+ const y = 40; >+ assert(eval("x;") === 20); >+ if (truth()) { >+ assert(eval("eval('y');") === 40); >+ eval("eval('x');"); >+ const x = 40; >+ } >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+} >+})(); >+ >+ >+// FunctionResolveNode >+;(function() { >+function foo() { >+ function captureX() { return x; } >+ x(); >+ const x = function() { return 20; }; >+} >+ >+function bar() { >+ x(); >+ let x = function() { return 20; }; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+} >+})(); >+ >+ >+// TypeofResolveNode >+;(function() { >+function foo() { >+ function captureX() { return x; } >+ typeof x; >+ const x = function() { return 20; }; >+} >+ >+function bar() { >+ typeof x; >+ const x = function() { return 20; }; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+} >+})(); >+ >+ >+// ReadModifyResolveNode >+;(function() { >+function foo() { >+ function captureX() { return x; } >+ x++; >+ const x = 20; >+} >+ >+function bar() { >+ x--; >+ const x = 30; >+} >+ >+function baz() { >+ x *= 40; >+ const x = 30; >+} >+ >+function kaz() { >+ function captureX() { return x; } >+ x /= 20; >+ const x = 20; >+} >+ >+function haz() { >+ function captureX() { return x; } >+ --x; >+ const x = 20; >+} >+ >+function jaz() { >+ --x; >+ const x = 30; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(bar); >+ shouldThrowTDZ(baz); >+ shouldThrowTDZ(kaz); >+ shouldThrowTDZ(haz); >+ shouldThrowTDZ(jaz); >+} >+})(); >+ >+ >+;(function() { >+function foo(x) { >+ const y = 50; >+ let result = null; >+ switch(x) { >+ case 10: >+ const y = 40; >+ assert(y === 40); >+ case 20: >+ y += 1; >+ assert(y === 41); >+ result = y; >+ break; >+ default: >+ result = x; >+ break; >+ } >+ assert(y === 50); >+ return result; >+} >+function bar(x) { >+ const y = 50; >+ let result = null; >+ switch(x) { >+ case 10: >+ const y = 40; >+ assert(y === 40); >+ case 20: >+ const capY = function() { return y; } >+ y += 1; >+ assert(y === 41); >+ result = y; >+ break; >+ default: >+ result = x; >+ break; >+ } >+ assert(y === 50); >+ return result; >+} >+function baz(x) { >+ const y = 50; >+ let result = null; >+ switch(x) { >+ case 10: >+ const y = 40; >+ assert(y === 40); >+ case 20: >+ let inc = function() { y += 1; } >+ inc(); >+ assert(y === 41); >+ result = y; >+ break; >+ default: >+ result = x; >+ break; >+ } >+ assert(y === 50); >+ return result; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(function() { foo(20); }); >+ shouldThrowTDZ(function() { bar(20); }); >+ shouldThrowTDZ(function() { baz(20); }); >+} >+})(); >+ >+ >+;(function() { >+function foo() { >+ [x] = [1]; >+ const x = null; >+} >+ >+function boo() { >+ [x] = [1]; >+ const x = 20; >+ function capX() { return x; } >+} >+ >+function bar() { >+ ({a, p: y} = {a: 100, p: 40}); >+ const y = 40; >+} >+ >+function zar() { >+ ({a, p: y} = {a: 100, p: 40}); >+ const y = 10; >+ function capY() { return y; } >+} >+ >+function baz() { >+ ({a, p: {y}} = {a: 100, p: {p: {y: 40}}}); >+ const y = 100; >+} >+ >+function jaz() { >+ ({y} = {}); >+ const y = null; >+} >+ >+for (var i = 0; i < NUM_LOOPS; i++) { >+ shouldThrowTDZ(foo); >+ shouldThrowTDZ(boo); >+ shouldThrowTDZ(bar); >+ shouldThrowTDZ(zar); >+ shouldThrowTDZ(baz); >+ shouldThrowTDZ(jaz); >+} >+})(); >Index: Source/WebInspectorUI/ChangeLog >=================================================================== >--- Source/WebInspectorUI/ChangeLog (revision 187003) >+++ Source/WebInspectorUI/ChangeLog (working copy) >@@ -1,3 +1,16 @@ >+2015-07-18 Saam barati <saambarati1@gmail.com> >+ >+ [ES6] Add support for block scope const >+ https://bugs.webkit.org/show_bug.cgi?id=31813 >+ >+ Reviewed by Filip Pizlo. >+ >+ "const" variables do not live on the global object and are only >+ accessible within the "Program" they're defined in. Therefore, >+ the WebInspector global must be defined as "var" and not "const". >+ >+ * UserInterface/Base/WebInspector.js: >+ > 2015-07-16 Joseph Pecoraro <pecoraro@apple.com> > > Web Inspector: REGRESSION (r186218) ScriptTimelineRecord attempts to access null property >Index: Source/WebInspectorUI/UserInterface/Base/WebInspector.js >=================================================================== >--- Source/WebInspectorUI/UserInterface/Base/WebInspector.js (revision 187003) >+++ Source/WebInspectorUI/UserInterface/Base/WebInspector.js (working copy) >@@ -23,4 +23,4 @@ > * THE POSSIBILITY OF SUCH DAMAGE. > */ > >-const WebInspector = {}; // Namespace >+var WebInspector = {}; // Namespace >Index: LayoutTests/ChangeLog >=================================================================== >--- LayoutTests/ChangeLog (revision 187003) >+++ LayoutTests/ChangeLog (working copy) >@@ -1,3 +1,83 @@ >+2015-07-18 Saam barati <saambarati1@gmail.com> >+ >+ [ES6] Add support for block scope const >+ https://bugs.webkit.org/show_bug.cgi?id=31813 >+ >+ Reviewed by Filip Pizlo. >+ >+ "const" variables do not live on the global object. They >+ are only available in the "Program" (read: JavaScript file or >+ script tag) that they're defined in. Tests have been updated >+ accordingly to switch the "const" variables assumed to be globals >+ into "var"s. "var" declared variables in the top level scope >+ of a program do live on the global object. >+ >+ * fast/canvas/webgl/compressed-tex-image.html: >+ * fast/dom/event-handler-attributes.html: >+ * fast/forms/listbox-visible-size.html: >+ * js/arguments-expected.txt: >+ * js/arrowfunction-syntax-errors-expected.txt: >+ * js/const-expected.txt: >+ * js/const-without-initializer-expected.txt: >+ * js/constant-count-expected.txt: >+ * js/dom/inc-const-valueOf-expected.txt: >+ * js/dom/script-tests/inc-const-valueOf.js: >+ (testPreIncConstVarWithAssign): >+ * js/function-toString-parentheses-expected.txt: >+ * js/kde/const-expected.txt: >+ * js/kde/resources/const.js: >+ * js/parser-syntax-check-expected.txt: >+ * js/script-tests/arguments.js: >+ (argumentsVarUndefined): >+ (argumentsConst): >+ (argumentCalleeInException): >+ (argumentsConstUndefined): Deleted. >+ * js/script-tests/class-syntax-declaration.js: >+ (A): >+ * js/script-tests/class-syntax-expression.js: >+ * js/script-tests/const-without-initializer.js: >+ * js/script-tests/const.js: >+ (shouldThrowInvalidConstAssignment): >+ (assert): >+ (f): >+ (tryCatch1): >+ (tryCatch2): >+ (with1): >+ (with2): >+ (.): >+ * js/script-tests/constant-count.js: >+ (f): >+ * js/script-tests/function-dot-arguments.js: >+ (assignConstInitTest2.g): >+ (assignConstInitTest2): >+ * js/script-tests/function-toString-parentheses.js: >+ * js/script-tests/parser-syntax-check.js: >+ * sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.6-expected.txt: >+ * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T7-expected.txt: >+ * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T8-expected.txt: >+ * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T9-expected.txt: >+ * sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A13_T3-expected.txt: >+ * sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A14_T3-expected.txt: >+ * sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T1-expected.txt: >+ * sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T2-expected.txt: >+ * sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T3-expected.txt: >+ * sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T4-expected.txt: >+ * sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T6-expected.txt: >+ * sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T7-expected.txt: >+ * sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T8-expected.txt: >+ * transforms/3d/hit-testing/composited-hit-test.html: >+ * transforms/3d/hit-testing/coplanar-with-camera.html: >+ * transforms/3d/hit-testing/hover-rotated-negative-z.html: >+ * transforms/3d/hit-testing/hover-rotated-with-children-negative-z.html: >+ * transforms/3d/hit-testing/negative-zoffset-hit-test.html: >+ * transforms/3d/hit-testing/overlapping-layers-hit-test.html: >+ * transforms/3d/hit-testing/perspective-clipped.html: >+ * transforms/3d/hit-testing/rotated-hit-test-with-child.html: >+ * transforms/3d/hit-testing/rotated-hit-test.html: >+ * transforms/3d/hit-testing/rotated-hit-test2.html: >+ * transitions/resources/transition-test-helpers.js: >+ (roundNumber): >+ > 2015-07-18 David Kilzer <ddkilzer@apple.com> > > inspector/console/command-line-api.html is slow on Debug Yosemite WK2 >Index: LayoutTests/fast/canvas/webgl/compressed-tex-image.html >=================================================================== >--- LayoutTests/fast/canvas/webgl/compressed-tex-image.html (revision 187003) >+++ LayoutTests/fast/canvas/webgl/compressed-tex-image.html (working copy) >@@ -22,12 +22,12 @@ var wtu = WebGLTestUtils; > var canvas = document.createElement("canvas"); > var gl = wtu.create3DContext(canvas); > >-const COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; >-const COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; >-const COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; >-const ETC1_RGB8_OES = 0x8D64; >-const COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; >-const COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; >+var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; >+var COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; >+var COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; >+var ETC1_RGB8_OES = 0x8D64; >+var COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; >+var COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; > > if (!gl) { > testFailed("context does not exist"); >Index: LayoutTests/fast/dom/event-handler-attributes.html >=================================================================== >--- LayoutTests/fast/dom/event-handler-attributes.html (revision 187003) >+++ LayoutTests/fast/dom/event-handler-attributes.html (working copy) >@@ -278,14 +278,14 @@ function testArray(array, prefix, expect > } > } > >-const nonHTMLElement = document.createElementNS("foo", "foo"); >-const element = document.documentElement; >-const bodyElement = document.body; >-const audioElement = document.createElement("video"); >-const framesetElement = document.createElement("frameset"); >-const inputElement = document.createElement("input"); >-const videoElement = document.createElement("video"); >-const rectElement = document.createElementNS("http://www.w3.org/2000/svg", "rect"); >+var nonHTMLElement = document.createElementNS("foo", "foo"); >+var element = document.documentElement; >+var bodyElement = document.body; >+var audioElement = document.createElement("video"); >+var framesetElement = document.createElement("frameset"); >+var inputElement = document.createElement("input"); >+var videoElement = document.createElement("video"); >+var rectElement = document.createElementNS("http://www.w3.org/2000/svg", "rect"); > > testArray(windowEvents, "testScriptAttribute(window", "window", "Event names we expect to be able to set on the window object"); > testArray(arrayDifference(allEventNames, windowEvents), "testScriptAttribute(window", "none", "Event names we expect not to be able to set on the window object"); >Index: LayoutTests/fast/forms/listbox-visible-size.html >=================================================================== >--- LayoutTests/fast/forms/listbox-visible-size.html (revision 187003) >+++ LayoutTests/fast/forms/listbox-visible-size.html (working copy) >@@ -21,7 +21,7 @@ > <option>Sunday</option> > </select> > <script> >- const targetTop = 28; >+ var targetTop = 28; > var select; > function scrollSelect(newTop) > { >Index: LayoutTests/js/arguments-expected.txt >=================================================================== >--- LayoutTests/js/arguments-expected.txt (revision 187003) >+++ LayoutTests/js/arguments-expected.txt (working copy) >@@ -134,7 +134,7 @@ PASS access_after_delete_extra_5(1, 2, 3 > PASS argumentsParam(true) is true > PASS argumentsFunctionConstructorParam(true) is true > PASS argumentsVarUndefined() is '[object Arguments]' >-PASS argumentsConstUndefined() is '[object Arguments]' >+PASS argumentsConst() is '20' > PASS argumentCalleeInException() is argumentCalleeInException > PASS shadowedArgumentsApply([true]) is true > PASS shadowedArgumentsLength([]) is 0 >Index: LayoutTests/js/arrowfunction-syntax-errors-expected.txt >=================================================================== >--- LayoutTests/js/arrowfunction-syntax-errors-expected.txt (revision 187003) >+++ LayoutTests/js/arrowfunction-syntax-errors-expected.txt (working copy) >@@ -113,8 +113,8 @@ PASS var y = x=>} threw exception Syntax > PASS var t = x=>x+1; =>{} threw exception SyntaxError: Unexpected keyword '=>'. > PASS [=>x+1] threw exception SyntaxError: Unexpected keyword '=>'. > PASS [x=>x+1, =>x+1] threw exception SyntaxError: Unexpected keyword '=>'. >-PASS var f=>x+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after var declaration.. >-PASS var x, y=>y+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after var declaration.. >+PASS var f=>x+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after variable declaration.. >+PASS var x, y=>y+1; threw exception SyntaxError: Unexpected keyword '=>'. Expected ';' after variable declaration.. > PASS debug(=>x+1) threw exception SyntaxError: Unexpected keyword '=>'. > PASS debug("xyz", =>x+1) threw exception SyntaxError: Unexpected keyword '=>'. > PASS var af1=y >Index: LayoutTests/js/const-expected.txt >=================================================================== >--- LayoutTests/js/const-expected.txt (revision 187003) >+++ LayoutTests/js/const-expected.txt (working copy) >@@ -3,65 +3,59 @@ This test checks that const declarations > On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". > > >-FAIL const redef='a'; const redef='a'; should throw an exception. Was undefined. >-PASS x is "RIGHT" >-PASS y is "RIGHT" >-PASS a is 1 >-PASS one is 1 >-PASS a is 1 >-PASS one is 1 >-PASS a is 2 >-PASS one is 1 >-PASS a is 0 >-PASS one is 1 >-PASS a is 3 >-PASS one is 1 >-PASS a is 2 >-PASS one is 1 >-PASS function f() { const one = 1; one++; return one; } f(); is 1 >-PASS function f() { const oneString = '1'; return oneString++; } f(); is 1 >-PASS function f() { const one = 1; return one++; } f(); is 1 >-PASS function f() { const one = 1; one--; return one; } f(); is 1 >-PASS function f() { const oneString = '1'; return oneString--; } f(); is 1 >-PASS function f() { const one = 1; return one--; } f(); is 1 >-PASS function f() { const one = 1; ++one; return one; } f(); is 1 >-PASS function f() { const one = 1; return ++one; } f(); is 2 >-PASS function f() { const one = 1; --one; return one; } f(); is 1 >-PASS function f() { const one = 1; return --one; } f(); is 0 >-PASS function f() { const one = 1; one += 2; return one; } f(); is 1 >-PASS function f() { const one = 1; return one += 2; } f(); is 3 >-PASS function f() { const one = 1; one = 2; return one; } f(); is 1 >-PASS function f() { const one = 1; return one = 2; } f(); is 2 >-PASS one++ is 1 >-PASS one is 1 >-PASS one-- is 1 >-PASS one is 1 >-PASS ++one is 2 >-PASS one is 1 >-PASS --one is 0 >-PASS one is 1 >-PASS one += 1 is 2 >-PASS one is 1 >-PASS one = 2 is 2 >-PASS one is 1 >-PASS object.inWith1 is 'RIGHT' >-PASS inWith2 is 'RIGHT' >-PASS (function(){ one = 2; return one; })() is 1 >+PASS const redef='a'; const redef='a'; threw exception SyntaxError: Cannot declare a const variable twice: 'redef'.. >+PASS function threw exception: 'function () { x = "WRONG"; }' >+PASS Assertion passed. >+PASS function threw exception: 'function () { y = "WRONG"; }' >+PASS Assertion passed. >+PASS function threw exception: 'function () { a = one++; }' >+PASS Assertion passed. >+PASS Assertion passed. >+PASS function threw exception: 'function () { a = one--; }' >+PASS Assertion passed. >+PASS Assertion passed. >+PASS function threw exception: 'function () { a = ++one; }' >+PASS Assertion passed. >+PASS Assertion passed. >+PASS function threw exception: 'function () { a = --one; }' >+PASS Assertion passed. >+PASS Assertion passed. >+PASS function threw exception: 'function () { a = one += 2; }' >+PASS Assertion passed. >+PASS Assertion passed. >+PASS function threw exception: 'function () { a = one = 2; }' >+PASS Assertion passed. >+PASS Assertion passed. >+PASS function f() { const one = 1; one++; return one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const oneString = '1'; return oneString++; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; return one++; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; one--; return one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const oneString = '1'; return oneString--; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; return one--; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; ++one; return one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; return ++one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; --one; return one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; return --one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; one += 2; return one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; return one += 2; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; one = 2; return one; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS function f() { const one = 1; return one = 2; } f(); threw exception TypeError: Attempted to assign to readonly property.. >+PASS Assertion passed. >+PASS Assertion passed. >+PASS object.inWith1 is 'a' >+PASS object.inWith2 is 'b' > PASS f() is f >-PASS const a; is undefined >-PASS tryCatch1Result is 5 >-PASS tryCatch2Result is 5 >-PASS with1Result is 5 >-PASS with2Result is 5 >-PASS PASS: ++x should be 2 and is. >-PASS PASS: --x should be 0 and is. >-PASS PASS: x should be 1 and is. >-PASS PASS: x++ should be 1 and is. >-PASS PASS: x should be 1 and is. >-PASS PASS: ++x should be 2 and is. >-PASS PASS: x should be 1 and is. >-PASS PASS: x++ should be 1 and is. >-PASS PASS: x should be 1 and is. >+PASS tryCatch1Result is null >+PASS tryCatch2Result is null >+PASS with1Result is null >+PASS with2Result is null >+PASS function threw exception: 'function () { ++x; }' >+PASS Assertion passed. >+PASS function threw exception: 'function () { x++; }' >+PASS Assertion passed. >+PASS function threw exception: 'function () { x--; }' >+PASS Assertion passed. >+PASS function threw exception: 'function () { --x; }' > PASS successfullyParsed is true > > TEST COMPLETE >Index: LayoutTests/js/const-without-initializer-expected.txt >=================================================================== >--- LayoutTests/js/const-without-initializer-expected.txt (revision 187003) >+++ LayoutTests/js/const-without-initializer-expected.txt (working copy) >@@ -3,8 +3,7 @@ Tests that declaring a const variable wi > On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". > > >-PASS f is undefined >-PASS f is undefined >+PASS const f threw exception SyntaxError: Unexpected end of script. > PASS successfullyParsed is true > > TEST COMPLETE >Index: LayoutTests/js/constant-count-expected.txt >=================================================================== >--- LayoutTests/js/constant-count-expected.txt (revision 187003) >+++ LayoutTests/js/constant-count-expected.txt (working copy) >@@ -3,8 +3,8 @@ This test checks exceptional cases for c > On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". > > >-PASS a is undefined >-PASS f() is undefined >+PASS 'a' is all good >+PASS f() is 10 > PASS successfullyParsed is true > > TEST COMPLETE >Index: LayoutTests/js/function-toString-parentheses-expected.txt >=================================================================== >--- LayoutTests/js/function-toString-parentheses-expected.txt (revision 187003) >+++ LayoutTests/js/function-toString-parentheses-expected.txt (working copy) >@@ -489,8 +489,8 @@ PASS compileAndSerializeLeftmostTest('va > PASS compileAndSerializeLeftmostTest('var a = 1, b = 2, c = 3') is 'var a = 1, b = 2, c = 3' > PASS compileAndSerializeLeftmostTest('const a = 1') is 'const a = 1' > PASS compileAndSerializeLeftmostTest('const a = (1, 2)') is 'const a = (1, 2)' >-PASS compileAndSerializeLeftmostTest('const a, b = 1') is 'const a, b = 1' >-PASS compileAndSerializeLeftmostTest('const a = 1, b') is 'const a = 1, b' >+PASS compileAndSerializeLeftmostTest('const a = 10, b = 1') is 'const a = 10, b = 1' >+PASS compileAndSerializeLeftmostTest('const a = 1, b = 2') is 'const a = 1, b = 2' > PASS compileAndSerializeLeftmostTest('const a = 1, b = 1') is 'const a = 1, b = 1' > PASS compileAndSerializeLeftmostTest('const a = (1, 2), b = 1') is 'const a = (1, 2), b = 1' > PASS compileAndSerializeLeftmostTest('const a = 1, b = (1, 2)') is 'const a = 1, b = (1, 2)' >Index: LayoutTests/js/parser-syntax-check-expected.txt >=================================================================== >--- LayoutTests/js/parser-syntax-check-expected.txt (revision 187003) >+++ LayoutTests/js/parser-syntax-check-expected.txt (working copy) >@@ -319,16 +319,18 @@ PASS Invalid: "function f() { throw }" > var and const statements > PASS Valid: "var a, b = null" > PASS Valid: "function f() { var a, b = null }" >-PASS Valid: "const a = 5, b, c" >-PASS Valid: "function f() { const a = 5, b, c }" >+PASS Valid: "const a = 5, b = 10, c = 20" >+PASS Valid: "function f() { const a = 5, b = 10, c = 20 }" > PASS Invalid: "var" > PASS Invalid: "function f() { var }" > PASS Invalid: "var = 7" > PASS Invalid: "function f() { var = 7 }" > PASS Invalid: "var c (6)" > PASS Invalid: "function f() { var c (6) }" >-PASS Valid: "if (a) var a,b; else { const b, c }" >-PASS Valid: "function f() { if (a) var a,b; else { const b, c } }" >+PASS Valid: "if (a) var a,b; else { const b = 1, c = 2; }" >+PASS Valid: "function f() { if (a) var a,b; else { const b = 1, c = 2; } }" >+PASS Invalid: "if (a) var a,b; else { const b, c }" >+PASS Invalid: "function f() { if (a) var a,b; else { const b, c } }" > PASS Invalid: "var 5 = 6" > PASS Invalid: "function f() { var 5 = 6 }" > PASS Valid: "while (0) var a, b, c=6, d, e, f=5*6, g=f*h, h" >@@ -337,8 +339,8 @@ PASS Invalid: "var a = if (b) { c }" > PASS Invalid: "function f() { var a = if (b) { c } }" > PASS Invalid: "var a = var b" > PASS Invalid: "function f() { var a = var b }" >-PASS Valid: "const a = b += c, a, a, a = (b - f())" with ReferenceError >-PASS Valid: "function f() { const a = b += c, a, a, a = (b - f()) }" >+PASS Invalid: "const a = b += c, a, a, a = (b - f())" >+PASS Invalid: "function f() { const a = b += c, a, a, a = (b - f()) }" > PASS Invalid: "var a %= b | 5" > PASS Invalid: "function f() { var a %= b | 5 }" > PASS Invalid: "var (a) = 5" >@@ -351,8 +353,10 @@ PASS Invalid: "var var = 3" > PASS Invalid: "function f() { var var = 3 }" > PASS Valid: "var varr = 3 in 1" with TypeError > PASS Valid: "function f() { var varr = 3 in 1 }" >-PASS Valid: "const a, a, a = void 7 - typeof 8, a = 8" >-PASS Valid: "function f() { const a, a, a = void 7 - typeof 8, a = 8 }" >+PASS Valid: "const a = void 7 - typeof 8, b = 8" >+PASS Valid: "function f() { const a = void 7 - typeof 8, b = 8 }" >+PASS Invalid: "const a, a, a = void 7 - typeof 8, a = 8" >+PASS Invalid: "function f() { const a, a, a = void 7 - typeof 8, a = 8 }" > PASS Valid: "const x_x = 6 /= 7 ? e : f" with ReferenceError > PASS Valid: "function f() { const x_x = 6 /= 7 ? e : f }" > PASS Invalid: "var a = ?" >@@ -367,29 +371,29 @@ PASS Invalid: "var a = b ? c, b" > PASS Invalid: "function f() { var a = b ? c, b }" > PASS Invalid: "const a = b : c" > PASS Invalid: "function f() { const a = b : c }" >-PASS Valid: "const a = 7; eval(''); a++" >+PASS Valid: "const a = 7; eval(''); a++" with TypeError > PASS Valid: "function f() { const a = 7; eval(''); a++ }" >-PASS Valid: "const a = 7; eval(''); a--" >+PASS Valid: "const a = 7; eval(''); a--" with TypeError > PASS Valid: "function f() { const a = 7; eval(''); a-- }" >-PASS Valid: "const a = 7; with({}) a++" >+PASS Valid: "const a = 7; with({}) a++" with TypeError > PASS Valid: "function f() { const a = 7; with({}) a++ }" >-PASS Valid: "const a = 7; with({}) a--" >+PASS Valid: "const a = 7; with({}) a--" with TypeError > PASS Valid: "function f() { const a = 7; with({}) a-- }" >-PASS Valid: "const a = 7; eval(''); a+=1" >+PASS Valid: "const a = 7; eval(''); a+=1" with TypeError > PASS Valid: "function f() { const a = 7; eval(''); a+=1 }" >-PASS Valid: "const a = 7; eval(''); a-=1" >+PASS Valid: "const a = 7; eval(''); a-=1" with TypeError > PASS Valid: "function f() { const a = 7; eval(''); a-=1 }" >-PASS Valid: "const a = 7; with({}) a+=1" >+PASS Valid: "const a = 7; with({}) a+=1" with TypeError > PASS Valid: "function f() { const a = 7; with({}) a+=1 }" >-PASS Valid: "const a = 7; with({}) a-=1" >+PASS Valid: "const a = 7; with({}) a-=1" with TypeError > PASS Valid: "function f() { const a = 7; with({}) a-=1 }" >-PASS Valid: "const a = 7; eval(''); a=1" >+PASS Valid: "const a = 7; eval(''); a=1" with TypeError > PASS Valid: "function f() { const a = 7; eval(''); a=1 }" >-PASS Valid: "const a = 7; eval(''); a=1" >+PASS Valid: "const a = 7; eval(''); a=1" with TypeError > PASS Valid: "function f() { const a = 7; eval(''); a=1 }" >-PASS Valid: "const a = 7; with({}) a=1" >+PASS Valid: "const a = 7; with({}) a=1" with TypeError > PASS Valid: "function f() { const a = 7; with({}) a=1 }" >-PASS Valid: "const a = 7; with({}) a=1" >+PASS Valid: "const a = 7; with({}) a=1" with TypeError > PASS Valid: "function f() { const a = 7; with({}) a=1 }" > for statement > PASS Valid: "for ( ; ; ) { break }" >@@ -430,8 +434,36 @@ PASS Valid: "for (var a = b, c, d ; ; > PASS Valid: "function f() { for (var a = b, c, d ; ; 1 in a()) break }" > PASS Invalid: "for ( ; var a ; ) break" > PASS Invalid: "function f() { for ( ; var a ; ) break }" >-PASS Invalid: "for (const a; ; ) break" >-PASS Invalid: "function f() { for (const a; ; ) break }" >+PASS Invalid: "for (const x; ; ) break" >+PASS Invalid: "function f() { for (const x; ; ) break }" >+PASS Invalid: "for (const x = 20, y; ; ) break" >+PASS Invalid: "function f() { for (const x = 20, y; ; ) break }" >+PASS Valid: "for (const x = 20; ; ) break" >+PASS Valid: "function f() { for (const x = 20; ; ) break }" >+PASS Valid: "for (const x of []) break" >+PASS Valid: "function f() { for (const x of []) break }" >+PASS Valid: "for (const x in {}) break" >+PASS Valid: "function f() { for (const x in {}) break }" >+PASS Invalid: "for (const x = 20, x = 30; ; ) { const x = 20; break; }" >+PASS Invalid: "function f() { for (const x = 20, x = 30; ; ) { const x = 20; break; } }" >+PASS Valid: "for (const x = 20; ; ) { const x = 20; break; }" >+PASS Valid: "function f() { for (const x = 20; ; ) { const x = 20; break; } }" >+PASS Valid: "for (const x of []) { const x = 20; break; }" >+PASS Valid: "function f() { for (const x of []) { const x = 20; break; } }" >+PASS Valid: "for (const x in {}) { const x = 20; break; }" >+PASS Valid: "function f() { for (const x in {}) { const x = 20; break; } }" >+PASS Invalid: "for (const let = 10; ; ) { break; }" >+PASS Invalid: "function f() { for (const let = 10; ; ) { break; } }" >+PASS Invalid: "for (const let in {}) { break; }" >+PASS Invalid: "function f() { for (const let in {}) { break; } }" >+PASS Invalid: "for (const let of []) { break; }" >+PASS Invalid: "function f() { for (const let of []) { break; } }" >+PASS Invalid: "for (let let = 10; ; ) { break; }" >+PASS Invalid: "function f() { for (let let = 10; ; ) { break; } }" >+PASS Invalid: "for (let let in {}) { break; }" >+PASS Invalid: "function f() { for (let let in {}) { break; } }" >+PASS Invalid: "for (let let of []) { break; }" >+PASS Invalid: "function f() { for (let let of []) { break; } }" > PASS Invalid: "for ( %a ; ; ) { }" > PASS Invalid: "function f() { for ( %a ; ; ) { } }" > PASS Valid: "for (a in b) break" with ReferenceError >Index: LayoutTests/js/dom/inc-const-valueOf-expected.txt >=================================================================== >--- LayoutTests/js/dom/inc-const-valueOf-expected.txt (revision 187003) >+++ LayoutTests/js/dom/inc-const-valueOf-expected.txt (working copy) >@@ -3,9 +3,9 @@ Test for regression against > On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". > > >-PASS testPostIncConstVarWithIgnoredResult() is true >-PASS testPreIncConstVarWithIgnoredResult() is true >-PASS testPreIncConstVarWithAssign() is true >+PASS testPostIncConstVarWithIgnoredResult() threw exception TypeError: Attempted to assign to readonly property.. >+PASS testPreIncConstVarWithIgnoredResult() threw exception TypeError: Attempted to assign to readonly property.. >+PASS testPreIncConstVarWithAssign() instanceof TypeError is true > PASS successfullyParsed is true > > TEST COMPLETE >Index: LayoutTests/js/dom/script-tests/inc-const-valueOf.js >=================================================================== >--- LayoutTests/js/dom/script-tests/inc-const-valueOf.js (revision 187003) >+++ LayoutTests/js/dom/script-tests/inc-const-valueOf.js (working copy) >@@ -49,8 +49,8 @@ function testPreIncConstVarWithAssign() > return okay; > } > >-shouldBeTrue('testPostIncConstVarWithIgnoredResult()'); >-shouldBeTrue('testPreIncConstVarWithIgnoredResult()'); >-shouldBeTrue('testPreIncConstVarWithAssign()'); >+shouldThrow('testPostIncConstVarWithIgnoredResult()'); >+shouldThrow('testPreIncConstVarWithIgnoredResult()'); >+shouldBeTrue('testPreIncConstVarWithAssign() instanceof TypeError'); > > successfullyParsed = true; >Index: LayoutTests/js/kde/const-expected.txt >=================================================================== >--- LayoutTests/js/kde/const-expected.txt (revision 187003) >+++ LayoutTests/js/kde/const-expected.txt (working copy) >@@ -3,8 +3,9 @@ KDE JS Test > On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". > > >-PASS c is 11 >-PASS c is 11 >+PASS c is eleven >+PASS cant assign to const >+PASS c is eleven > PASS v is 1 > PASS successfullyParsed is true > >Index: LayoutTests/js/kde/resources/const.js >=================================================================== >--- LayoutTests/js/kde/resources/const.js (revision 187003) >+++ LayoutTests/js/kde/resources/const.js (working copy) >@@ -1,10 +1,26 @@ > // constant definition > const c = 11; >-shouldBe("c", "11"); >+if (c !== 11) >+ testFailed("c is not eleven"); >+else >+ testPassed("c is eleven"); > > // attempt to redefine should have no effect >-c = 22; >-shouldBe("c", "11"); >+var threwError = false; >+try { >+ c = 22; >+} catch(e) { >+ threwError = true; >+} >+if (threwError) >+ testPassed("cant assign to const"); >+else >+ testFailed("const assignment worked but should not have"); >+ >+if (c !== 11) >+ testFailed("c is not eleven"); >+else >+ testPassed("c is eleven"); > > const dummy = 0; > for (var v = 0;;) { >Index: LayoutTests/js/script-tests/arguments.js >=================================================================== >--- LayoutTests/js/script-tests/arguments.js (revision 187003) >+++ LayoutTests/js/script-tests/arguments.js (working copy) >@@ -551,12 +551,12 @@ function argumentsVarUndefined() > } > shouldBe("argumentsVarUndefined()", "'[object Arguments]'"); > >-function argumentsConstUndefined() >+function argumentsConst() > { >- const arguments; >+ const arguments = 20; > return String(arguments); > } >-shouldBe("argumentsConstUndefined()", "'[object Arguments]'"); >+shouldBe("argumentsConst()", "'20'"); > > function argumentCalleeInException() { > try { >Index: LayoutTests/js/script-tests/class-syntax-declaration.js >=================================================================== >--- LayoutTests/js/script-tests/class-syntax-declaration.js (revision 187003) >+++ LayoutTests/js/script-tests/class-syntax-declaration.js (working copy) >@@ -2,9 +2,9 @@ > description('Tests for ES6 class syntax declarations'); > > var constructorCallCount = 0; >-const staticMethodValue = [1]; >-const instanceMethodValue = [2]; >-const getterValue = [3]; >+var staticMethodValue = [1]; >+var instanceMethodValue = [2]; >+var getterValue = [3]; > var setterValue = undefined; > class A { > constructor() { constructorCallCount++; } >Index: LayoutTests/js/script-tests/class-syntax-expression.js >=================================================================== >--- LayoutTests/js/script-tests/class-syntax-expression.js (revision 187003) >+++ LayoutTests/js/script-tests/class-syntax-expression.js (working copy) >@@ -2,9 +2,9 @@ > description('Tests for ES6 class syntax expressions'); > > var constructorCallCount = 0; >-const staticMethodValue = [1]; >-const instanceMethodValue = [2]; >-const getterValue = [3]; >+var staticMethodValue = [1]; >+var instanceMethodValue = [2]; >+var getterValue = [3]; > var setterValue = undefined; > var A = class { > constructor() { constructorCallCount++; } >Index: LayoutTests/js/script-tests/const-without-initializer.js >=================================================================== >--- LayoutTests/js/script-tests/const-without-initializer.js (revision 187003) >+++ LayoutTests/js/script-tests/const-without-initializer.js (working copy) >@@ -2,10 +2,4 @@ description( > 'Tests that declaring a const variable without initializing has the correct behavior and does not crash' > ); > >-const f; >- >-shouldBe('f', 'undefined'); >- >-f = 10; >- >-shouldBe('f', 'undefined'); >+shouldThrow("const f"); >Index: LayoutTests/js/script-tests/const.js >=================================================================== >--- LayoutTests/js/script-tests/const.js (revision 187003) >+++ LayoutTests/js/script-tests/const.js (working copy) >@@ -2,119 +2,114 @@ description( > "This test checks that const declarations in JavaScript work and are readonly." > ); > >+function shouldThrowInvalidConstAssignment(f) { >+ var threw = false; >+ try { >+ f(); >+ } catch(e) { >+ if (e.name.indexOf("TypeError") !== -1 && e.message.indexOf("readonly") !== -1) >+ threw = true; >+ } >+ if (threw) >+ testPassed("function threw exception: '" + f.toString() + "'"); >+ else >+ testFailed("function did not throw: '" + f.toString() + "'"); >+} >+function assert(b) { >+ if (!b) >+ testFailed("Invalid assertion.") >+ else >+ testPassed("Assertion passed."); >+} >+ > > shouldThrow("const redef='a'; const redef='a';"); > > const x = "RIGHT"; >-x = "WRONG"; >-shouldBe("x", '"RIGHT"'); >+shouldThrowInvalidConstAssignment(function() { x = "WRONG"; }); >+assert(x === "RIGHT"); >+ > > const z = "RIGHT", y = "RIGHT"; >-y = "WRONG"; >-shouldBe("y", '"RIGHT"'); >+shouldThrowInvalidConstAssignment(function() { y = "WRONG"; }); >+assert(y === "RIGHT"); > > const one = 1; > >-var a; >- >-// PostIncResolveNode >-a = one++; >-shouldBe("a", "1"); >-shouldBe("one", "1"); >- >-// PostDecResolveNode >-a = one--; >-shouldBe("a", "1"); >-shouldBe("one", "1"); >- >-// PreIncResolveNode >-a = ++one; >-shouldBe("a", "2"); >-shouldBe("one", "1"); >- >-// PreDecResolveNode >-a = --one; >-shouldBe("a", "0"); >-shouldBe("one", "1"); >- >-// ReadModifyConstNode >-a = one += 2; >-shouldBe("a", "3"); >-shouldBe("one", "1"); >- >-// AssignConstNode >-a = one = 2; >-shouldBe("a", "2"); >-shouldBe("one", "1"); >+var a = null; > > // PostIncResolveNode >-shouldBe("function f() { const one = 1; one++; return one; } f();", "1"); >-shouldBe("function f() { const oneString = '1'; return oneString++; } f();", "1"); >-shouldBe("function f() { const one = 1; return one++; } f();", "1"); >+shouldThrowInvalidConstAssignment(function() { a = one++; }); >+assert(a === null); >+assert(one === 1); > > // PostDecResolveNode >-shouldBe("function f() { const one = 1; one--; return one; } f();", "1"); >-shouldBe("function f() { const oneString = '1'; return oneString--; } f();", "1"); >-shouldBe("function f() { const one = 1; return one--; } f();", "1"); >+shouldThrowInvalidConstAssignment(function() { a = one--; }); >+assert(a === null); >+assert(one === 1); > > // PreIncResolveNode >-shouldBe("function f() { const one = 1; ++one; return one; } f();", "1"); >-shouldBe("function f() { const one = 1; return ++one; } f();", "2"); >+shouldThrowInvalidConstAssignment(function() { a = ++one; }); >+assert(a === null); >+assert(one === 1); > > // PreDecResolveNode >-shouldBe("function f() { const one = 1; --one; return one; } f();", "1"); >-shouldBe("function f() { const one = 1; return --one; } f();", "0"); >+shouldThrowInvalidConstAssignment(function() { a = --one; }); >+assert(a === null); >+assert(one === 1); > > // ReadModifyConstNode >-shouldBe("function f() { const one = 1; one += 2; return one; } f();", "1"); >-shouldBe("function f() { const one = 1; return one += 2; } f();", "3"); >+shouldThrowInvalidConstAssignment(function() { a = one += 2; }); >+assert(a === null); >+assert(one === 1); > > // AssignConstNode >-shouldBe("function f() { const one = 1; one = 2; return one; } f();", "1"); >-shouldBe("function f() { const one = 1; return one = 2; } f();", "2"); >+shouldThrowInvalidConstAssignment(function() { a = one = 2; }); >+assert(a === null); >+assert(one === 1); > > // PostIncResolveNode >-shouldBe("one++", "1"); >-shouldBe("one", "1"); >+shouldThrow("function f() { const one = 1; one++; return one; } f();"); >+shouldThrow("function f() { const oneString = '1'; return oneString++; } f();"); >+shouldThrow("function f() { const one = 1; return one++; } f();"); > > // PostDecResolveNode >-shouldBe("one--", "1"); >-shouldBe("one", "1"); >+shouldThrow("function f() { const one = 1; one--; return one; } f();"); >+shouldThrow("function f() { const oneString = '1'; return oneString--; } f();"); >+shouldThrow("function f() { const one = 1; return one--; } f();"); > > // PreIncResolveNode >-shouldBe("++one", "2"); >-shouldBe("one", "1"); >+shouldThrow("function f() { const one = 1; ++one; return one; } f();"); >+shouldThrow("function f() { const one = 1; return ++one; } f();"); > > // PreDecResolveNode >-shouldBe("--one", "0"); >-shouldBe("one", "1"); >+shouldThrow("function f() { const one = 1; --one; return one; } f();"); >+shouldThrow("function f() { const one = 1; return --one; } f();"); > > // ReadModifyConstNode >-shouldBe("one += 1", "2"); >-shouldBe("one", "1"); >+shouldThrow("function f() { const one = 1; one += 2; return one; } f();"); >+shouldThrow("function f() { const one = 1; return one += 2; } f();"); > > // AssignConstNode >-shouldBe("one = 2", "2"); >-shouldBe("one", "1"); >+shouldThrow("function f() { const one = 1; one = 2; return one; } f();"); >+shouldThrow("function f() { const one = 1; return one = 2; } f();"); > >-var object = { inWith1: "RIGHT", inWith2: ""} >+var object = { inWith1: "a", inWith2: "b"} > with (object) { >- const inWith1 = "WRONG"; >- const inWith2 = "RIGHT"; >- inWith2 = "WRONG"; >+ const inWith1 = "hello"; >+ const inWith2 = "world"; >+ assert(inWith1 === "hello"); >+ assert(inWith2 === "world"); > } >-shouldBe("object.inWith1", "'RIGHT'"); >-shouldBe("inWith2", "'RIGHT'"); >+shouldBe("object.inWith1", "'a'"); >+shouldBe("object.inWith2", "'b'"); > >-shouldBe("(function(){ one = 2; return one; })()", "1") > var f = function g() { g="FAIL"; return g; }; > shouldBe("f()", "f"); > >-shouldBe("const a;", "undefined"); >- > // Make sure that dynamic scopes (catch, with) don't break const declarations > function tryCatch1() { >- var bar; >+ var bar = null; > eval("try {\ > stuff();\ > } catch (e) {\ >@@ -124,7 +119,7 @@ function tryCatch1() { > } > > function tryCatch2() { >- var bar; >+ var bar = null; > try { > stuff(); > } catch (e) { >@@ -134,51 +129,36 @@ function tryCatch2() { > } > > tryCatch1Result = tryCatch1(); >-shouldBe("tryCatch1Result", "5"); >+shouldBe("tryCatch1Result", "null"); > tryCatch2Result = tryCatch2(); >-shouldBe("tryCatch2Result", "5"); >+shouldBe("tryCatch2Result", "null"); > > function with1() { >- var bar; >+ var bar = null; > eval("with({foo:42}) { const bar = 5; }"); > return bar; > } > > function with2() { >- var bar; >+ var bar = null; > with({foo:42}) { const bar = 5; } > return bar; > } > > with1Result = with1(); >-shouldBe("with1Result", "5"); >+shouldBe("with1Result", "null"); > with2Result = with2(); >-shouldBe("with2Result", "5"); >+shouldBe("with2Result", "null"); > > (function () { >- function shouldBe(aDescription, a, b) >- { >- if (a === b) { >- testPassed("PASS: " + aDescription + " should be " + b + " and is."); >- return; >- } >- >- testFailed("FAIL: " + aDescription + " should be " + b + " but instead is " + a + "."); >- } >- > (function() { > const x = "1"; >- shouldBe("++x", ++x, 2); >- shouldBe("--x", --x, 0); >- shouldBe("x", x, "1"); >- shouldBe("x++", x++, 1); >- shouldBe("x", x, "1"); >- })(); >- (function() { >- const x = 1; >- shouldBe("++x", ++x, 2); >- shouldBe("x", x, 1); >- shouldBe("x++", x++, 1); >- shouldBe("x", x, 1); >+ shouldThrowInvalidConstAssignment(function() { ++x; }); >+ assert(x === "1"); >+ shouldThrowInvalidConstAssignment(function() { x++; }); >+ assert(x === "1"); >+ shouldThrowInvalidConstAssignment(function() { x--; }); >+ assert(x === "1"); >+ shouldThrowInvalidConstAssignment(function() { --x; }); > })(); > })(); >Index: LayoutTests/js/script-tests/constant-count.js >=================================================================== >--- LayoutTests/js/script-tests/constant-count.js (revision 187003) >+++ LayoutTests/js/script-tests/constant-count.js (working copy) >@@ -2,21 +2,29 @@ description( > "This test checks exceptional cases for constant counting in the parser." > ); > >-const a; >-const b; >---a; >---b; >+const a = 15; >+const b = 25; >+try { >+ --a; >+ --b; >+} catch(e) { } > >-shouldBe("a", "undefined"); >+if (a !== 15) >+ testFailed("Unexpected result for 'a'"); >+else >+ testPassed("'a' is all good"); > > function f() > { >- const a; >- const b; >- --a; >- --b; >+ const a = 10; >+ const b = 20; >+ try { >+ } catch(e) { >+ a--; >+ b--; >+ } > > return a; > } > >-shouldBe("f()", "undefined"); >+shouldBe("f()", "10"); >Index: LayoutTests/js/script-tests/function-dot-arguments.js >=================================================================== >--- LayoutTests/js/script-tests/function-dot-arguments.js (revision 187003) >+++ LayoutTests/js/script-tests/function-dot-arguments.js (working copy) >@@ -120,7 +120,7 @@ function assignConstInitTest2() > return assignConstInitTest2.arguments; > } > >- const a, arguments = true; >+ const a = 5, arguments = true; > return g(); > } > shouldBe("assignConstInitTest2().toString()", "'[object Arguments]'"); >Index: LayoutTests/js/script-tests/function-toString-parentheses.js >=================================================================== >--- LayoutTests/js/script-tests/function-toString-parentheses.js (revision 187003) >+++ LayoutTests/js/script-tests/function-toString-parentheses.js (working copy) >@@ -201,8 +201,8 @@ shouldBe("compileAndSerializeLeftmostTes > > shouldBe("compileAndSerializeLeftmostTest('const a = 1')", "'const a = 1'"); > shouldBe("compileAndSerializeLeftmostTest('const a = (1, 2)')", "'const a = (1, 2)'"); >-shouldBe("compileAndSerializeLeftmostTest('const a, b = 1')", "'const a, b = 1'"); >-shouldBe("compileAndSerializeLeftmostTest('const a = 1, b')", "'const a = 1, b'"); >+shouldBe("compileAndSerializeLeftmostTest('const a = 10, b = 1')", "'const a = 10, b = 1'"); >+shouldBe("compileAndSerializeLeftmostTest('const a = 1, b = 2')", "'const a = 1, b = 2'"); > shouldBe("compileAndSerializeLeftmostTest('const a = 1, b = 1')", "'const a = 1, b = 1'"); > shouldBe("compileAndSerializeLeftmostTest('const a = (1, 2), b = 1')", "'const a = (1, 2), b = 1'"); > shouldBe("compileAndSerializeLeftmostTest('const a = 1, b = (1, 2)')", "'const a = 1, b = (1, 2)'"); >Index: LayoutTests/js/script-tests/parser-syntax-check.js >=================================================================== >--- LayoutTests/js/script-tests/parser-syntax-check.js (revision 187003) >+++ LayoutTests/js/script-tests/parser-syntax-check.js (working copy) >@@ -232,23 +232,25 @@ invalid("throw"); > debug ("var and const statements"); > > valid ("var a, b = null"); >-valid ("const a = 5, b, c"); >+valid ("const a = 5, b = 10, c = 20"); > invalid("var"); > invalid("var = 7"); > invalid("var c (6)"); >-valid ("if (a) var a,b; else { const b, c }"); >+valid ("if (a) var a,b; else { const b = 1, c = 2; }"); >+invalid("if (a) var a,b; else { const b, c }"); > invalid("var 5 = 6"); > valid ("while (0) var a, b, c=6, d, e, f=5*6, g=f*h, h"); > invalid("var a = if (b) { c }"); > invalid("var a = var b"); >-valid ("const a = b += c, a, a, a = (b - f())"); >+invalid("const a = b += c, a, a, a = (b - f())"); > invalid("var a %= b | 5"); > invalid("var (a) = 5"); > invalid("var a = (4, b = 6"); > invalid("const 'l' = 3"); > invalid("var var = 3"); > valid ("var varr = 3 in 1"); >-valid ("const a, a, a = void 7 - typeof 8, a = 8"); >+valid ("const a = void 7 - typeof 8, b = 8"); >+invalid("const a, a, a = void 7 - typeof 8, a = 8"); > valid ("const x_x = 6 /= 7 ? e : f"); > invalid("var a = ?"); > invalid("const a = *7"); >@@ -291,7 +293,21 @@ valid ("for (var a = b, b = a ; ; ) bre > valid ("for (var a = b, c, d, b = a ; x in b ; ) { break }"); > valid ("for (var a = b, c, d ; ; 1 in a()) break"); > invalid("for ( ; var a ; ) break"); >-invalid("for (const a; ; ) break"); >+invalid("for (const x; ; ) break"); >+invalid("for (const x = 20, y; ; ) break"); >+valid ("for (const x = 20; ; ) break"); >+valid ("for (const x of []) break"); >+valid ("for (const x in {}) break"); >+invalid("for (const x = 20, x = 30; ; ) { const x = 20; break; }"); >+valid ("for (const x = 20; ; ) { const x = 20; break; }"); >+valid ("for (const x of []) { const x = 20; break; }"); >+valid ("for (const x in {}) { const x = 20; break; }"); >+invalid("for (const let = 10; ; ) { break; }"); >+invalid("for (const let in {}) { break; }"); >+invalid("for (const let of []) { break; }"); >+invalid("for (let let = 10; ; ) { break; }"); >+invalid("for (let let in {}) { break; }"); >+invalid("for (let let of []) { break; }"); > invalid("for ( %a ; ; ) { }"); > valid ("for (a in b) break"); > valid ("for (a() in b) break"); >Index: LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.6-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.6-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.6-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected token '='. Expected an identifier name in const declaration. >+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected token '='. Expected a parameter pattern or a ')' in parameter list. > S7.5.3_A1.6 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T7-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T7-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T7-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected identifier '\u0067'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected identifier '\u0067'. Expected ';' after variable declaration. > S7.8.5_A3.1_T7 > > FAIL successfullyParsed is not set >Index: LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T8-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T8-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T8-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected identifier '\u0069'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected identifier '\u0069'. Expected ';' after variable declaration. > S7.8.5_A3.1_T8 > > FAIL successfullyParsed is not set >Index: LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T9-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T9-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A3.1_T9-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected identifier '\u006D'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected identifier '\u006D'. Expected ';' after variable declaration. > S7.8.5_A3.1_T9 > > FAIL successfullyParsed is not set >Index: LayoutTests/sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A13_T3-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A13_T3-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A13_T3-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected string literal ''. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected string literal ''. Expected ';' after variable declaration. > S8.4_A13_T3 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A14_T3-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A14_T3-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/08_Types/8.4_The_String_Type/S8.4_A14_T3-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected string literal "". Expected ';' after var declaration. >+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected string literal "". Expected ';' after variable declaration. > S8.4_A14_T3 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T1-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T1-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T1-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '+='. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '+='. Expected ';' after variable declaration. > S12.2_A8_T1 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T2-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T2-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T2-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '|'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '|'. Expected ';' after variable declaration. > S12.2_A8_T2 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T3-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T3-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T3-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '&&'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '&&'. Expected ';' after variable declaration. > S12.2_A8_T3 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T4-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T4-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T4-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '++'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '++'. Expected ';' after variable declaration. > S12.2_A8_T4 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T6-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T6-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T6-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '*'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '*'. Expected ';' after variable declaration. > S12.2_A8_T6 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T7-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T7-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T7-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '>>'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '>>'. Expected ';' after variable declaration. > S12.2_A8_T7 > > PASS Expected parsing failure >Index: LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T8-expected.txt >=================================================================== >--- LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T8-expected.txt (revision 187003) >+++ LayoutTests/sputnik/Conformance/12_Statement/12.2_Variable_Statement/S12.2_A8_T8-expected.txt (working copy) >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 80: SyntaxError: Unexpected keyword 'in'. Expected ';' after var declaration. >+CONSOLE MESSAGE: line 80: SyntaxError: Unexpected keyword 'in'. Expected ';' after variable declaration. > S12.2_A8_T8 > > PASS Expected parsing failure >Index: LayoutTests/transforms/3d/hit-testing/composited-hit-test.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/composited-hit-test.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/composited-hit-test.html (working copy) >@@ -43,7 +43,7 @@ > </style> > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [48, 48], 'target' : 'container' }, > { 'point': [75, 75], 'target' : 'target' }, > { 'point': [100, 100], 'target' : 'target' }, >Index: LayoutTests/transforms/3d/hit-testing/coplanar-with-camera.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/coplanar-with-camera.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/coplanar-with-camera.html (working copy) >@@ -50,7 +50,7 @@ > > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [98, 200], 'target' : 'background' }, > { 'point': [302, 200], 'target' : 'background' }, > { 'point': [200, 98], 'target' : 'background' }, >Index: LayoutTests/transforms/3d/hit-testing/hover-rotated-negative-z.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/hover-rotated-negative-z.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/hover-rotated-negative-z.html (working copy) >@@ -22,7 +22,7 @@ > > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [70, 70], 'target' : 'transformed' }, > { 'point': [630, 130], 'target' : 'transformed' }, > { 'point': [40, 130], 'target' : 'transformed' }, >@@ -39,4 +39,4 @@ > > <div id="results"></div> > </body> >-</html> >\ No newline at end of file >+</html> >Index: LayoutTests/transforms/3d/hit-testing/hover-rotated-with-children-negative-z.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/hover-rotated-with-children-negative-z.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/hover-rotated-with-children-negative-z.html (working copy) >@@ -37,7 +37,7 @@ > > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [70, 70], 'target' : 'transformed' }, > { 'point': [630, 130], 'target' : 'transformed' }, > { 'point': [40, 130], 'target' : 'transformed' }, >@@ -62,4 +62,4 @@ > > <div id="results"></div> > </body> >-</html> >\ No newline at end of file >+</html> >Index: LayoutTests/transforms/3d/hit-testing/negative-zoffset-hit-test.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/negative-zoffset-hit-test.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/negative-zoffset-hit-test.html (working copy) >@@ -29,7 +29,7 @@ > </style> > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [50, 50], 'target' : 'container' }, > { 'point': [60, 60], 'target' : 'container' }, > { 'point': [70, 70], 'target' : 'target' }, >Index: LayoutTests/transforms/3d/hit-testing/overlapping-layers-hit-test.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/overlapping-layers-hit-test.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/overlapping-layers-hit-test.html (working copy) >@@ -61,7 +61,7 @@ > </style> > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > > { 'point': [10, 100], 'target' : 'container-nopreserve' }, > { 'point': [20, 100], 'target' : 'target2' }, >Index: LayoutTests/transforms/3d/hit-testing/perspective-clipped.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/perspective-clipped.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/perspective-clipped.html (working copy) >@@ -60,7 +60,7 @@ > </style> > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > // Points near the corners of the top layer > { 'point': [35, 100], 'target' : 'topLayer' }, > { 'point': [370, 100], 'target' : 'topLayer' }, >Index: LayoutTests/transforms/3d/hit-testing/rotated-hit-test2.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/rotated-hit-test2.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/rotated-hit-test2.html (working copy) >@@ -51,7 +51,7 @@ > </style> > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [170, 250], 'target' : 'left' }, > { 'point': [260, 170], 'target' : 'top' }, > { 'point': [330, 250], 'target' : 'right' }, >Index: LayoutTests/transforms/3d/hit-testing/rotated-hit-test-with-child.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/rotated-hit-test-with-child.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/rotated-hit-test-with-child.html (working copy) >@@ -42,7 +42,7 @@ > </style> > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [30, 30], 'target' : 'box1' }, > { 'point': [80, 100], 'target' : 'box1' }, > { 'point': [100, 120], 'target' : 'box2' }, >Index: LayoutTests/transforms/3d/hit-testing/rotated-hit-test.html >=================================================================== >--- LayoutTests/transforms/3d/hit-testing/rotated-hit-test.html (revision 187003) >+++ LayoutTests/transforms/3d/hit-testing/rotated-hit-test.html (working copy) >@@ -46,7 +46,7 @@ > </style> > <script src="resources/hit-test-utils.js"></script> > <script> >- const hitTestData = [ >+ var hitTestData = [ > { 'point': [85, 100], 'target' : 'left' }, > { 'point': [155, 80], 'target' : 'top' }, > { 'point': [230, 80], 'target' : 'right' }, >Index: LayoutTests/transitions/resources/transition-test-helpers.js >=================================================================== >--- LayoutTests/transitions/resources/transition-test-helpers.js (revision 187003) >+++ LayoutTests/transitions/resources/transition-test-helpers.js (working copy) >@@ -21,11 +21,11 @@ Function parameters: > > */ > >-const usePauseAPI = true; >-const dontUsePauseAPI = false; >+var usePauseAPI = true; >+var dontUsePauseAPI = false; > >-const shouldBeTransitioning = true; >-const shouldNotBeTransitioning = false; >+var shouldBeTransitioning = true; >+var shouldNotBeTransitioning = false; > > function roundNumber(num, decimalPlaces) > {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
buildbot
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 31813
:
256546
|
256608
|
256611
|
256761
|
256926
|
256930
|
256934
|
256945
|
256951
|
256953
|
257039
|
257040
|
257041
|
257051