Changeset 187515 in webkit
- Timestamp:
- Jul 28, 2015, 2:39:34 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 deleted
- 35 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r187483 r187515 491 491 runtime/JSCJSValue.cpp 492 492 runtime/JSCallee.cpp 493 runtime/JSCatchScope.cpp494 493 runtime/JSCell.cpp 495 494 runtime/JSConsole.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r187513 r187515 1 2015-07-28 Saam barati <[email protected]> 2 3 Implement catch scope using lexical scoping constructs introduced with "let" scoping patch 4 https://bugs.webkit.org/show_bug.cgi?id=146979 5 6 Reviewed by Geoffrey Garen. 7 8 Now that BytecodeGenerator has a notion of local scope depth, 9 we can easily implement a catch scope that doesn't claim that 10 all variables are dynamically scoped. This means that functions 11 that use try/catch can have local variable resolution. This also 12 means that all functions that use try/catch don't have all 13 their variables marked as being captured. 14 15 Catch scopes now behave like a "let" scope (sans the TDZ logic) with a 16 single variable. Catch scopes are now just JSLexicalEnvironments and the 17 symbol table backing the catch scope knows that it corresponds to a catch scope. 18 19 * CMakeLists.txt: 20 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 21 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters: 22 * JavaScriptCore.xcodeproj/project.pbxproj: 23 * bytecode/CodeBlock.cpp: 24 (JSC::CodeBlock::dumpBytecode): 25 * bytecode/EvalCodeCache.h: 26 (JSC::EvalCodeCache::isCacheable): 27 * bytecompiler/BytecodeGenerator.cpp: 28 (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack): 29 (JSC::BytecodeGenerator::emitLoadGlobalObject): 30 (JSC::BytecodeGenerator::pushLexicalScope): 31 (JSC::BytecodeGenerator::pushLexicalScopeInternal): 32 (JSC::BytecodeGenerator::popLexicalScope): 33 (JSC::BytecodeGenerator::popLexicalScopeInternal): 34 (JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration): 35 (JSC::BytecodeGenerator::variable): 36 (JSC::BytecodeGenerator::resolveType): 37 (JSC::BytecodeGenerator::emitResolveScope): 38 (JSC::BytecodeGenerator::emitPopScope): 39 (JSC::BytecodeGenerator::emitPopWithScope): 40 (JSC::BytecodeGenerator::emitDebugHook): 41 (JSC::BytecodeGenerator::popScopedControlFlowContext): 42 (JSC::BytecodeGenerator::emitPushCatchScope): 43 (JSC::BytecodeGenerator::emitPopCatchScope): 44 (JSC::BytecodeGenerator::beginSwitch): 45 (JSC::BytecodeGenerator::emitPopWithOrCatchScope): Deleted. 46 * bytecompiler/BytecodeGenerator.h: 47 (JSC::BytecodeGenerator::lastOpcodeID): 48 * bytecompiler/NodesCodegen.cpp: 49 (JSC::AssignResolveNode::emitBytecode): 50 (JSC::WithNode::emitBytecode): 51 (JSC::TryNode::emitBytecode): 52 * debugger/DebuggerScope.cpp: 53 (JSC::DebuggerScope::isCatchScope): 54 (JSC::DebuggerScope::isFunctionNameScope): 55 (JSC::DebuggerScope::isFunctionOrEvalScope): 56 (JSC::DebuggerScope::caughtValue): 57 * debugger/DebuggerScope.h: 58 * inspector/ScriptDebugServer.cpp: 59 (Inspector::ScriptDebugServer::exceptionOrCaughtValue): 60 * interpreter/Interpreter.cpp: 61 (JSC::Interpreter::execute): 62 * jit/JITOpcodes.cpp: 63 (JSC::JIT::emit_op_push_name_scope): 64 * jit/JITOpcodes32_64.cpp: 65 (JSC::JIT::emit_op_push_name_scope): 66 * jit/JITOperations.cpp: 67 * jit/JITOperations.h: 68 * parser/ASTBuilder.h: 69 (JSC::ASTBuilder::createContinueStatement): 70 (JSC::ASTBuilder::createTryStatement): 71 * parser/NodeConstructors.h: 72 (JSC::ThrowNode::ThrowNode): 73 (JSC::TryNode::TryNode): 74 (JSC::FunctionParameters::FunctionParameters): 75 * parser/Nodes.h: 76 * parser/Parser.cpp: 77 (JSC::Parser<LexerType>::parseTryStatement): 78 * parser/SyntaxChecker.h: 79 (JSC::SyntaxChecker::createBreakStatement): 80 (JSC::SyntaxChecker::createContinueStatement): 81 (JSC::SyntaxChecker::createTryStatement): 82 (JSC::SyntaxChecker::createSwitchStatement): 83 (JSC::SyntaxChecker::createWhileStatement): 84 (JSC::SyntaxChecker::createWithStatement): 85 * runtime/JSCatchScope.cpp: 86 * runtime/JSCatchScope.h: 87 (JSC::JSCatchScope::JSCatchScope): Deleted. 88 (JSC::JSCatchScope::create): Deleted. 89 (JSC::JSCatchScope::createStructure): Deleted. 90 * runtime/JSFunctionNameScope.h: 91 (JSC::JSFunctionNameScope::JSFunctionNameScope): 92 * runtime/JSGlobalObject.cpp: 93 (JSC::JSGlobalObject::init): 94 (JSC::JSGlobalObject::visitChildren): 95 * runtime/JSGlobalObject.h: 96 (JSC::JSGlobalObject::withScopeStructure): 97 (JSC::JSGlobalObject::strictEvalActivationStructure): 98 (JSC::JSGlobalObject::activationStructure): 99 (JSC::JSGlobalObject::functionNameScopeStructure): 100 (JSC::JSGlobalObject::directArgumentsStructure): 101 (JSC::JSGlobalObject::scopedArgumentsStructure): 102 (JSC::JSGlobalObject::catchScopeStructure): Deleted. 103 * runtime/JSNameScope.cpp: 104 (JSC::JSNameScope::create): 105 (JSC::JSNameScope::toThis): 106 * runtime/JSNameScope.h: 107 * runtime/JSObject.cpp: 108 (JSC::JSObject::toThis): 109 (JSC::JSObject::isFunctionNameScopeObject): 110 (JSC::JSObject::isCatchScopeObject): Deleted. 111 * runtime/JSObject.h: 112 * runtime/JSScope.cpp: 113 (JSC::JSScope::collectVariablesUnderTDZ): 114 (JSC::JSScope::isLexicalScope): 115 (JSC::JSScope::isCatchScope): 116 (JSC::resolveModeName): 117 * runtime/JSScope.h: 118 * runtime/SymbolTable.cpp: 119 (JSC::SymbolTable::SymbolTable): 120 (JSC::SymbolTable::cloneScopePart): 121 * runtime/SymbolTable.h: 122 * tests/stress/const-semantics.js: 123 (.): 124 1 125 2015-07-28 Filip Pizlo <[email protected]> 2 126 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r187483 r187515 746 746 <ClCompile Include="..\runtime\JSCJSValue.cpp" /> 747 747 <ClCompile Include="..\runtime\JSCallee.cpp" /> 748 <ClCompile Include="..\runtime\JSCatchScope.cpp" />749 748 <ClCompile Include="..\runtime\JSCell.cpp" /> 750 749 <ClCompile Include="..\runtime\JSConsole.cpp" /> … … 1558 1557 <ClInclude Include="..\runtime\JSCJSValueInlines.h" /> 1559 1558 <ClInclude Include="..\runtime\JSCallee.h" /> 1560 <ClInclude Include="..\runtime\JSCatchScope.h" />1561 1559 <ClInclude Include="..\runtime\JSCell.h" /> 1562 1560 <ClInclude Include="..\runtime\JSConsole.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
r187483 r187515 1772 1772 <ClCompile Include="..\ftl\FTLJSCallBase.cpp" /> 1773 1773 <ClCompile Include="..\ftl\FTLJSCallVarargs.cpp" /> 1774 <ClCompile Include="..\runtime\JSCatchScope.cpp" />1775 1774 <ClCompile Include="..\runtime\JSFunctionNameScope.cpp" /> 1776 1775 <ClCompile Include="..\jit\ExecutableAllocatorFixedVMPool.cpp"> … … 4273 4272 <ClInclude Include="..\ftl\FTLJSCallBase.h" /> 4274 4273 <ClInclude Include="..\ftl\FTLJSCallVarargs.h" /> 4275 <ClInclude Include="..\runtime\JSCatchScope.h" />4276 4274 <ClInclude Include="..\runtime\JSFunctionNameScope.h" /> 4277 4275 <ClInclude Include="..\runtime\MathCommon.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r187483 r187515 611 611 0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD8A32317D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp */; }; 612 612 0FD8A32C17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD8A32417D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; }; 613 0FD949821A97DB9600E28966 /* JSCatchScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */; };614 0FD949831A97DB9600E28966 /* JSCatchScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD9497F1A97DB9600E28966 /* JSCatchScope.h */; settings = {ATTRIBUTES = (Private, ); }; };615 613 0FD949841A97DB9600E28966 /* JSFunctionNameScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD949801A97DB9600E28966 /* JSFunctionNameScope.cpp */; }; 616 614 0FD949851A97DB9600E28966 /* JSFunctionNameScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD949811A97DB9600E28966 /* JSFunctionNameScope.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 2373 2371 0FD8A32317D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGToFTLForOSREntryDeferredCompilationCallback.cpp; path = dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp; sourceTree = "<group>"; }; 2374 2372 0FD8A32417D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGToFTLForOSREntryDeferredCompilationCallback.h; path = dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h; sourceTree = "<group>"; }; 2375 0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCatchScope.cpp; sourceTree = "<group>"; };2376 0FD9497F1A97DB9600E28966 /* JSCatchScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCatchScope.h; sourceTree = "<group>"; };2377 2373 0FD949801A97DB9600E28966 /* JSFunctionNameScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFunctionNameScope.cpp; sourceTree = "<group>"; }; 2378 2374 0FD949811A97DB9600E28966 /* JSFunctionNameScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFunctionNameScope.h; sourceTree = "<group>"; }; … … 4531 4527 657CF45619BF6662004ACBF2 /* JSCallee.cpp */, 4532 4528 657CF45719BF6662004ACBF2 /* JSCallee.h */, 4533 0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */,4534 0FD9497F1A97DB9600E28966 /* JSCatchScope.h */,4535 4529 BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */, 4536 4530 BC1167D80E19BCC9008066DD /* JSCell.h */, … … 6293 6287 A7CA3AE817DA41AE006538AF /* JSWeakMap.h in Headers */, 6294 6288 A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */, 6295 0FD949831A97DB9600E28966 /* JSCatchScope.h in Headers */,6296 6289 A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */, 6297 6290 1442566215EDE98D0066A49B /* JSWithScope.h in Headers */, … … 7436 7429 14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */, 7437 7430 70DC3E091B2DF2C700054299 /* IteratorPrototype.cpp in Sources */, 7438 0FD949821A97DB9600E28966 /* JSCatchScope.cpp in Sources */,7439 7431 A72028B61797601E0098028C /* JSCTestRunnerUtils.cpp in Sources */, 7440 7432 0F2B66EB17B6B5AB00A7AE3F /* JSDataView.cpp in Sources */, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r187033 r187515 1458 1458 JSNameScope::Type scopeType = (JSNameScope::Type)(++it)->u.operand; 1459 1459 printLocationAndOp(out, exec, location, it, "push_name_scope"); 1460 out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(r1).data(), constantName(k0).data(), (scopeType == JSNameScope::FunctionNameScope) ? "functionScope" : ((scopeType == JSNameScope::CatchScope) ? "catchScope" : "unknownScopeType"));1460 out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(r1).data(), constantName(k0).data(), (scopeType == JSNameScope::FunctionNameScope) ? "functionScope" : "unknownScopeType"); 1461 1461 break; 1462 1462 } -
trunk/Source/JavaScriptCore/bytecode/EvalCodeCache.h
r186860 r187515 82 82 && evalSource.length() < Options::maximumEvalCacheableSourceLength() 83 83 && scope->begin()->isVariableObject() 84 && !scope->isLexicalScope(); 84 && !scope->isLexicalScope() 85 && !scope->isCatchScope(); 85 86 } 86 87 static const int maxCacheEntries = 64; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r187437 r187515 579 579 580 580 // This implements step 25 of section 9.2.12. 581 pushLexicalScopeInternal(environment, true, nullptr );581 pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope); 582 582 583 583 RefPtr<RegisterID> temp = newTemporary(); … … 1358 1358 } 1359 1359 1360 void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult) 1360 void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult) 1361 { 1362 VariableEnvironment& environment = node->lexicalVariables(); 1363 pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope); 1364 } 1365 1366 void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType) 1361 1367 { 1362 1368 if (!environment.size()) … … 1367 1373 1368 1374 Strong<SymbolTable> symbolTable(*m_vm, SymbolTable::create(*m_vm)); 1369 symbolTable->setDoesCorrespondToLexicalScope(); 1375 switch (scopeType) { 1376 case ScopeType::CatchScope: 1377 symbolTable->setScopeType(SymbolTable::ScopeType::CatchScope); 1378 break; 1379 case ScopeType::LetConstScope: 1380 symbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope); 1381 break; 1382 } 1383 1370 1384 bool hasCapturedVariables = false; 1371 1385 { 1372 1386 ConcurrentJITLocker locker(symbolTable->m_lock); 1373 for (auto entry : environment) {1387 for (auto& entry : environment) { 1374 1388 ASSERT(entry.value.isLet() || entry.value.isConst()); 1375 1389 ASSERT(!entry.value.isVar()); … … 1409 1423 instructions().append(scopeRegister()->index()); 1410 1424 instructions().append(constantSymbolTable->index()); 1411 instructions().append(addConstantValue( jsTDZValue())->index());1425 instructions().append(addConstantValue(tdzRequirement == TDZRequirement::UnderTDZ ? jsTDZValue() : jsUndefined())->index()); 1412 1426 1413 1427 emitMove(scopeRegister(), newScope); … … 1417 1431 1418 1432 m_symbolTableStack.append(SymbolTableStackEntry{ symbolTable, newScope, false, symbolTableConstantIndex }); 1419 m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks)); 1420 // Prefill stack variables with the TDZ empty value. 1421 // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated. 1422 for (auto entry : environment) { 1423 SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get()); 1424 ASSERT(!symbolTableEntry.isNull()); 1425 VarOffset offset = symbolTableEntry.varOffset(); 1426 if (offset.isScope()) { 1427 ASSERT(newScope); 1428 continue; 1429 } 1430 ASSERT(offset.isStack()); 1431 emitMoveEmptyValue(®isterFor(offset.stackOffset())); 1432 } 1433 } 1434 1435 void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult) 1433 if (tdzRequirement == TDZRequirement::UnderTDZ) 1434 m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks)); 1435 1436 if (tdzRequirement == TDZRequirement::UnderTDZ) { 1437 // Prefill stack variables with the TDZ empty value. 1438 // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated. 1439 for (auto& entry : environment) { 1440 SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get()); 1441 ASSERT(!symbolTableEntry.isNull()); 1442 VarOffset offset = symbolTableEntry.varOffset(); 1443 if (offset.isScope()) { 1444 ASSERT(newScope); 1445 continue; 1446 } 1447 ASSERT(offset.isStack()); 1448 emitMoveEmptyValue(®isterFor(offset.stackOffset())); 1449 } 1450 } 1451 } 1452 1453 void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node) 1436 1454 { 1437 1455 VariableEnvironment& environment = node->lexicalVariables(); 1438 pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult); 1439 } 1440 1441 void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node) 1442 { 1443 VariableEnvironment& environment = node->lexicalVariables(); 1456 popLexicalScopeInternal(environment, TDZRequirement::UnderTDZ); 1457 } 1458 1459 void BytecodeGenerator::popLexicalScopeInternal(VariableEnvironment& environment, TDZRequirement tdzRequirement) 1460 { 1444 1461 if (!environment.size()) 1445 1462 return; … … 1452 1469 ConcurrentJITLocker locker(symbolTable->m_lock); 1453 1470 bool hasCapturedVariables = false; 1454 for (auto entry : environment) {1471 for (auto& entry : environment) { 1455 1472 if (entry.value.isCaptured()) { 1456 1473 hasCapturedVariables = true; … … 1472 1489 } 1473 1490 1474 m_TDZStack.removeLast(); 1491 if (tdzRequirement == TDZRequirement::UnderTDZ) 1492 m_TDZStack.removeLast(); 1475 1493 } 1476 1494 … … 1577 1595 for (unsigned i = m_symbolTableStack.size(); i--; ) { 1578 1596 SymbolTableStackEntry& stackEntry = m_symbolTableStack[i]; 1579 if (stackEntry.m_isWith OrCatch)1597 if (stackEntry.m_isWithScope) 1580 1598 return Variable(property); 1581 1599 Strong<SymbolTable>& symbolTable = stackEntry.m_symbolTable; … … 1584 1602 continue; 1585 1603 1586 return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable-> correspondsToLexicalScope());1604 return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope); 1587 1605 } 1588 1606 … … 1662 1680 { 1663 1681 for (unsigned i = m_symbolTableStack.size(); i--; ) { 1664 if (m_symbolTableStack[i].m_isWith OrCatch)1682 if (m_symbolTableStack[i].m_isWithScope) 1665 1683 return Dynamic; 1666 1684 } … … 1689 1707 for (unsigned i = m_symbolTableStack.size(); i--; ) { 1690 1708 SymbolTableStackEntry& stackEntry = m_symbolTableStack[i]; 1691 // We should not resolve a variable to VarKind::Scope if a "with" or "catch"scope lies in between the current1709 // We should not resolve a variable to VarKind::Scope if a "with" scope lies in between the current 1692 1710 // scope and the resolved scope. 1693 RELEASE_ASSERT(!stackEntry.m_isWith OrCatch);1711 RELEASE_ASSERT(!stackEntry.m_isWithScope); 1694 1712 1695 1713 if (stackEntry.m_symbolTable->get(variable.ident().impl()).isNull()) … … 2568 2586 } 2569 2587 2570 void BytecodeGenerator::emitPopWith OrCatchScope(RegisterID* srcDst)2588 void BytecodeGenerator::emitPopWithScope(RegisterID* srcDst) 2571 2589 { 2572 2590 emitPopScope(srcDst, srcDst); 2573 2591 popScopedControlFlowContext(); 2574 2592 SymbolTableStackEntry stackEntry = m_symbolTableStack.takeLast(); 2575 RELEASE_ASSERT(stackEntry.m_isWith OrCatch);2593 RELEASE_ASSERT(stackEntry.m_isWithScope); 2576 2594 } 2577 2595 … … 3008 3026 } 3009 3027 3010 void BytecodeGenerator::emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes) 3011 { 3012 pushScopedControlFlowContext(); 3013 3014 emitOpcode(op_push_name_scope); 3015 instructions().append(dst->index()); 3016 instructions().append(value->index()); 3017 instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property, attributes))->index()); 3018 instructions().append(JSNameScope::CatchScope); 3019 3020 m_symbolTableStack.append(SymbolTableStackEntry{ Strong<SymbolTable>(), nullptr, true, 0 }); 3028 void BytecodeGenerator::emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment& environment) 3029 { 3030 RELEASE_ASSERT(environment.contains(property.impl())); 3031 pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope); 3032 Variable exceptionVar = variable(property); 3033 RELEASE_ASSERT(exceptionVar.isResolved()); 3034 RefPtr<RegisterID> scope = emitResolveScope(nullptr, exceptionVar); 3035 emitPutToScope(scope.get(), exceptionVar, exceptionValue, ThrowIfNotFound); 3036 } 3037 3038 void BytecodeGenerator::emitPopCatchScope(VariableEnvironment& environment) 3039 { 3040 popLexicalScopeInternal(environment, TDZRequirement::NotUnderTDZ); 3021 3041 } 3022 3042 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r187351 r187515 582 582 583 583 void emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes); 584 void emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes); 584 void emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment&); 585 void emitPopCatchScope(VariableEnvironment&); 585 586 586 587 void emitGetScope(); 587 588 RegisterID* emitPushWithScope(RegisterID* dst, RegisterID* scope); 588 589 void emitPopScope(RegisterID* dst, RegisterID* scope); 589 void emitPopWith OrCatchScope(RegisterID* srcDst);590 void emitPopWithScope(RegisterID* srcDst); 590 591 RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope); 591 592 … … 623 624 624 625 private: 625 void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult); 626 enum class TDZRequirement { UnderTDZ, NotUnderTDZ }; 627 enum class ScopeType { CatchScope, LetConstScope }; 628 void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType); 629 void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement); 626 630 public: 627 631 void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr); … … 739 743 Strong<SymbolTable> m_symbolTable; 740 744 RegisterID* m_scope; 741 bool m_isWith OrCatch;745 bool m_isWithScope; 742 746 int m_symbolTableConstantIndex; 743 747 }; -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r187351 r187515 1859 1859 1860 1860 if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) { 1861 result = generator.emitNode(dst, m_right); // Execute side effects first. 1861 1862 generator.emitReadOnlyExceptionIfNeeded(var); 1862 result = generator.emitNode(dst, m_right);1863 1863 } else if (var.isSpecial() || generator.vm()->typeProfiler()) { 1864 1864 RefPtr<RegisterID> tempDst = generator.tempDestination(dst); … … 1889 1889 RefPtr<RegisterID> result = generator.emitNode(dst, m_right); 1890 1890 if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) { 1891 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first. 1891 1892 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var); 1892 1893 if (threwException) 1893 return generator.emitNode(dst, m_right);1894 return result; 1894 1895 } 1895 1896 generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); … … 2684 2685 generator.emitPushWithScope(generator.scopeRegister(), scope.get()); 2685 2686 generator.emitNode(dst, m_statement); 2686 generator.emitPopWith OrCatchScope(generator.scopeRegister());2687 generator.emitPopWithScope(generator.scopeRegister()); 2687 2688 } 2688 2689 … … 2934 2935 } 2935 2936 2936 generator.emitPushCatchScope( generator.scopeRegister(), m_thrownValueIdent, thrownValueRegister.get(), DontDelete);2937 generator.emitPushCatchScope(m_thrownValueIdent, thrownValueRegister.get(), m_catchEnvironment); 2937 2938 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1); 2938 2939 generator.emitNode(dst, m_catchBlock); 2939 generator.emitPop WithOrCatchScope(generator.scopeRegister());2940 generator.emitPopCatchScope(m_catchEnvironment); 2940 2941 generator.emitLabel(catchEndLabel.get()); 2941 2942 } -
trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp
r186860 r187515 168 168 bool DebuggerScope::isCatchScope() const 169 169 { 170 return m_scope->isCatchScope Object();170 return m_scope->isCatchScope(); 171 171 } 172 172 … … 191 191 // lexical environment object. Hence, a lexical environment object implies a 192 192 // function or eval scope. 193 return m_scope->isActivationObject() ;194 } 195 196 JSValue DebuggerScope::caughtValue( ) const193 return m_scope->isActivationObject() && !isCatchScope(); 194 } 195 196 JSValue DebuggerScope::caughtValue(ExecState* exec) const 197 197 { 198 198 ASSERT(isCatchScope()); 199 return reinterpret_cast<JSNameScope*>(m_scope.get())->value(); 199 JSLexicalEnvironment* catchEnvironment = jsCast<JSLexicalEnvironment*>(m_scope.get()); 200 SymbolTable* catchSymbolTable = catchEnvironment->symbolTable(); 201 RELEASE_ASSERT(catchSymbolTable->size() == 1); 202 PropertyName errorName(catchSymbolTable->begin(catchSymbolTable->m_lock)->key.get()); 203 PropertySlot slot(m_scope.get()); 204 bool success = catchEnvironment->getOwnPropertySlot(catchEnvironment, exec, errorName, slot); 205 RELEASE_ASSERT(success && slot.isValue()); 206 return slot.getValue(exec, errorName); 200 207 } 201 208 -
trunk/Source/JavaScriptCore/debugger/DebuggerScope.h
r182747 r187515 92 92 bool isFunctionOrEvalScope() const; 93 93 94 JSValue caughtValue( ) const;94 JSValue caughtValue(ExecState*) const; 95 95 96 96 private: -
trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
r185608 r187515 341 341 DebuggerScope* scope = debuggerCallFrame->scope(); 342 342 if (scope->isCatchScope()) 343 return Deprecated::ScriptValue(state->vm(), scope->caughtValue( ));343 return Deprecated::ScriptValue(state->vm(), scope->caughtValue(state)); 344 344 debuggerCallFrame = debuggerCallFrame->callerFrame(); 345 345 } -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r187142 r187515 1141 1141 } 1142 1142 if (JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast<JSLexicalEnvironment*>(node)) { 1143 if ( !lexicalEnvironment->symbolTable()->correspondsToLexicalScope()) {1143 if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) { 1144 1144 variableObject = node; 1145 1145 break; -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r186860 r187515 498 498 int dst = currentInstruction[1].u.operand; 499 499 emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); 500 if (currentInstruction[4].u.operand == JSNameScope::CatchScope) {501 callOperation(operationPushCatchScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT0);502 return;503 }504 505 500 RELEASE_ASSERT(currentInstruction[4].u.operand == JSNameScope::FunctionNameScope); 506 501 callOperation(operationPushFunctionNameScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT0); -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r186860 r187515 805 805 int dst = currentInstruction[1].u.operand; 806 806 emitLoad(currentInstruction[2].u.operand, regT1, regT0); 807 if (currentInstruction[4].u.operand == JSNameScope::CatchScope) {808 callOperation(operationPushCatchScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT1, regT0);809 return;810 }811 812 807 RELEASE_ASSERT(currentInstruction[4].u.operand == JSNameScope::FunctionNameScope); 813 808 callOperation(operationPushFunctionNameScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT1, regT0); -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r187505 r187515 45 45 #include "JITToDFGDeferredCompilationCallback.h" 46 46 #include "JSCInlines.h" 47 #include "JSCatchScope.h"48 47 #include "JSFunctionNameScope.h" 49 48 #include "JSGlobalObjectFunctions.h" … … 1365 1364 #endif 1366 1365 1367 void JIT_OPERATION operationPushCatchScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)1368 {1369 pushNameScope<JSCatchScope>(exec, dst, symbolTable, encodedValue);1370 }1371 1372 1366 void JIT_OPERATION operationPushFunctionNameScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue) 1373 1367 { -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r187505 r187515 305 305 void JIT_OPERATION operationPutGetterSetter(ExecState*, JSCell*, Identifier*, JSCell*, JSCell*) WTF_INTERNAL; 306 306 #endif 307 void JIT_OPERATION operationPushCatchScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL;308 307 void JIT_OPERATION operationPushFunctionNameScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL; 309 308 void JIT_OPERATION operationPushWithScope(ExecState*, int32_t, EncodedJSValue) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r187351 r187515 556 556 } 557 557 558 StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine )559 { 560 TryNode* result = new (m_parserArena) TryNode(location, tryBlock, *ident, catchBlock, finallyBlock);558 StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine, VariableEnvironment& catchEnvironment) 559 { 560 TryNode* result = new (m_parserArena) TryNode(location, tryBlock, *ident, catchBlock, catchEnvironment, finallyBlock); 561 561 if (catchBlock) 562 562 usesCatch(); -
trunk/Source/JavaScriptCore/parser/NodeConstructors.h
r187108 r187515 819 819 } 820 820 821 inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier& thrownValueIdent, StatementNode* catchBlock, StatementNode* finallyBlock)821 inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier& thrownValueIdent, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock) 822 822 : StatementNode(location) 823 823 , m_tryBlock(tryBlock) … … 826 826 , m_finallyBlock(finallyBlock) 827 827 { 828 m_catchEnvironment.swap(catchEnvironment); 828 829 } 829 830 -
trunk/Source/JavaScriptCore/parser/Nodes.h
r187351 r187515 1514 1514 class TryNode : public StatementNode { 1515 1515 public: 1516 TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock);1516 TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock); 1517 1517 1518 1518 private: … … 1523 1523 StatementNode* m_catchBlock; 1524 1524 StatementNode* m_finallyBlock; 1525 VariableEnvironment m_catchEnvironment; 1525 1526 }; 1526 1527 -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r187351 r187515 1262 1262 failIfFalse(tryBlock, "Cannot parse the body of try block"); 1263 1263 int lastLine = m_lastTokenEndPosition.line; 1264 1264 VariableEnvironment catchEnvironment; 1265 1265 if (match(CATCH)) { 1266 currentScope()->setNeedsFullActivation();1267 1266 next(); 1268 1267 … … 1275 1274 next(); 1276 1275 AutoPopScopeRef catchScope(this, pushScope()); 1277 failIfTrueIfStrict(declareVariable(ident) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode"); 1278 catchScope->preventAllVariableDeclarations(); 1276 catchScope->setIsLexicalScope(); 1277 catchScope->preventVarDeclarations(); 1278 failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode"); 1279 1279 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target"); 1280 1280 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement"); 1281 1281 catchBlock = parseBlockStatement(context); 1282 1282 failIfFalse(catchBlock, "Unable to parse 'catch' block"); 1283 catchEnvironment = catchScope->finalizeLexicalEnvironment(); 1284 RELEASE_ASSERT(catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())); 1283 1285 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo); 1284 1286 } … … 1291 1293 } 1292 1294 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block"); 1293 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine );1295 return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment); 1294 1296 } 1295 1297 -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r187351 r187515 243 243 int createContinueStatement(const JSTokenLocation&, int, int) { return StatementResult; } 244 244 int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; } 245 int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int ) { return StatementResult; }245 int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int, VariableEnvironment&) { return StatementResult; } 246 246 int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; } 247 247 int createWhileStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; } -
trunk/Source/JavaScriptCore/runtime/JSFunctionNameScope.h
r180514 r187515 39 39 40 40 JSFunctionNameScope(VM& vm, JSGlobalObject* globalObject, JSScope* next, SymbolTable* symbolTable) 41 : Base(vm, globalObject-> catchScopeStructure(), next, symbolTable)41 : Base(vm, globalObject->functionNameScopeStructure(), next, symbolTable) 42 42 { 43 43 } -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r187483 r187515 65 65 #include "JSCallbackFunction.h" 66 66 #include "JSCallbackObject.h" 67 #include "JSCatchScope.h"68 67 #include "JSConsole.h" 69 68 #include "JSDataView.h" … … 303 302 m_typedArrays[toIndex(TypeDataView)].structure.set(vm, this, JSDataView::createStructure(vm, this, m_typedArrays[toIndex(TypeDataView)].prototype.get())); 304 303 305 m_catchScopeStructure.set(vm, this, JSCatchScope::createStructure(vm, this, jsNull()));306 304 m_functionNameScopeStructure.set(vm, this, JSFunctionNameScope::createStructure(vm, this, jsNull())); 307 305 m_lexicalEnvironmentStructure.set(vm, this, JSLexicalEnvironment::createStructure(vm, this)); … … 774 772 visitor.append(&thisObject->m_strictEvalActivationStructure); 775 773 visitor.append(&thisObject->m_lexicalEnvironmentStructure); 776 visitor.append(&thisObject->m_catchScopeStructure);777 774 visitor.append(&thisObject->m_functionNameScopeStructure); 778 775 visitor.append(&thisObject->m_directArgumentsStructure); -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r187483 r187515 212 212 WriteBarrier<Structure> m_strictEvalActivationStructure; 213 213 WriteBarrier<Structure> m_lexicalEnvironmentStructure; 214 WriteBarrier<Structure> m_catchScopeStructure;215 214 WriteBarrier<Structure> m_functionNameScopeStructure; 216 215 WriteBarrier<Structure> m_directArgumentsStructure; … … 424 423 Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); } 425 424 Structure* activationStructure() const { return m_lexicalEnvironmentStructure.get(); } 426 Structure* catchScopeStructure() const { return m_catchScopeStructure.get(); }427 425 Structure* functionNameScopeStructure() const { return m_functionNameScopeStructure.get(); } 428 426 Structure* directArgumentsStructure() const { return m_directArgumentsStructure.get(); } -
trunk/Source/JavaScriptCore/runtime/JSNameScope.cpp
r181993 r187515 29 29 #include "Error.h" 30 30 #include "JSCInlines.h" 31 #include "JSCatchScope.h"32 31 #include "JSFunctionNameScope.h" 33 32 … … 38 37 JSNameScope* JSNameScope::create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue value, Type type) 39 38 { 40 switch (type) { 41 case CatchScope: 42 return JSCatchScope::create(vm, globalObject, currentScope, symbolTable, value); 43 case FunctionNameScope: 44 return JSFunctionNameScope::create(vm, globalObject, currentScope, symbolTable, value); 45 } 46 RELEASE_ASSERT_NOT_REACHED(); 47 return nullptr; 39 RELEASE_ASSERT(type == FunctionNameScope); 40 return JSFunctionNameScope::create(vm, globalObject, currentScope, symbolTable, value); 48 41 } 49 42 -
trunk/Source/JavaScriptCore/runtime/JSNameScope.h
r182747 r187515 39 39 40 40 enum Type { 41 CatchScope,42 41 FunctionNameScope 43 42 }; -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r187464 r187515 36 36 #include "GetterSetter.h" 37 37 #include "IndexingHeaderInlines.h" 38 #include "JSCatchScope.h"39 38 #include "JSFunction.h" 40 39 #include "JSFunctionNameScope.h" … … 1601 1600 { 1602 1601 return jsCast<JSObject*>(cell); 1603 }1604 1605 bool JSObject::isCatchScopeObject() const1606 {1607 return inherits(JSCatchScope::info());1608 1602 } 1609 1603 -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r186776 r187515 602 602 bool isStaticScopeObject() const; 603 603 bool isNameScopeObject() const; 604 bool isCatchScopeObject() const;605 604 bool isFunctionNameScopeObject() const; 606 605 bool isActivationObject() const; -
trunk/Source/JavaScriptCore/runtime/JSScope.cpp
r186860 r187515 194 194 continue; 195 195 SymbolTable* symbolTable = jsCast<JSLexicalEnvironment*>(scope)->symbolTable(); 196 ASSERT(symbolTable-> correspondsToLexicalScope());196 ASSERT(symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope); 197 197 ConcurrentJITLocker locker(symbolTable->m_lock); 198 198 for (auto end = symbolTable->end(locker), iter = symbolTable->begin(locker); iter != end; ++iter) … … 207 207 return false; 208 208 209 return lexicalEnvironment->symbolTable()->correspondsToLexicalScope(); 210 } 209 return lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::LexicalScope; 210 } 211 212 bool JSScope::isCatchScope() 213 { 214 JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast<JSLexicalEnvironment*>(this); 215 if (!lexicalEnvironment) 216 return false; 217 return lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::CatchScope; 218 } 219 211 220 212 221 const char* resolveModeName(ResolveMode mode) -
trunk/Source/JavaScriptCore/runtime/JSScope.h
r186860 r187515 166 166 167 167 bool isLexicalScope(); 168 bool isCatchScope(); 168 169 169 170 ScopeChainIterator begin(); -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r186860 r187515 85 85 : JSCell(vm, vm.symbolTableStructure.get()) 86 86 , m_usesNonStrictEval(false) 87 , m_ correspondsToLexicalScope(false)87 , m_scopeType(VarScope) 88 88 { 89 89 } … … 143 143 144 144 result->m_usesNonStrictEval = m_usesNonStrictEval; 145 result->m_ correspondsToLexicalScope = m_correspondsToLexicalScope;145 result->m_scopeType = m_scopeType; 146 146 147 147 for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r186860 r187515 649 649 bool usesNonStrictEval() { return m_usesNonStrictEval; } 650 650 void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; } 651 ALWAYS_INLINE bool correspondsToLexicalScope() { return m_correspondsToLexicalScope; } 652 void setDoesCorrespondToLexicalScope() { m_correspondsToLexicalScope = true; } 651 652 enum ScopeType { 653 VarScope, 654 LexicalScope, 655 CatchScope 656 }; 657 void setScopeType(ScopeType type) { m_scopeType = type; } 658 ScopeType scopeType() const { return static_cast<ScopeType>(m_scopeType); } 653 659 654 660 SymbolTable* cloneScopePart(VM&); … … 679 685 680 686 bool m_usesNonStrictEval : 1; 681 bool m_correspondsToLexicalScope : 1;687 unsigned m_scopeType : 2; // ScopeType 682 688 683 689 WriteBarrier<ScopedArgumentsTable> m_arguments; -
trunk/Source/JavaScriptCore/tests/stress/const-semantics.js
r187460 r187515 189 189 const x = 20; 190 190 shouldThrowInvalidConstAssignment(function() { x = 20; }); 191 assert(x === 20); 191 192 shouldThrowInvalidConstAssignment(function() { x += 20; }); 193 assert(x === 20); 192 194 shouldThrowInvalidConstAssignment(function() { x -= 20; }); 195 assert(x === 20); 193 196 shouldThrowInvalidConstAssignment(function() { x *= 20; }); 197 assert(x === 20); 194 198 shouldThrowInvalidConstAssignment(function() { x /= 20; }); 199 assert(x === 20); 195 200 shouldThrowInvalidConstAssignment(function() { x >>= 20; }); 201 assert(x === 20); 196 202 shouldThrowInvalidConstAssignment(function() { x <<= 20; }); 203 assert(x === 20); 197 204 shouldThrowInvalidConstAssignment(function() { x ^= 20; }); 205 assert(x === 20); 198 206 shouldThrowInvalidConstAssignment(function() { x++; }); 207 assert(x === 20); 199 208 shouldThrowInvalidConstAssignment(function() { x--; }); 209 assert(x === 20); 200 210 shouldThrowInvalidConstAssignment(function() { ++x; }); 211 assert(x === 20); 201 212 shouldThrowInvalidConstAssignment(function() { --x; }); 213 assert(x === 20); 202 214 } 203 215 function jaz() {
Note:
See TracChangeset
for help on using the changeset viewer.