Implement catch scope using lexical scoping constructs introduced with "let" scoping patch
https://bugs.webkit.org/show_bug.cgi?id=146979
Reviewed by Geoffrey Garen.
Now that BytecodeGenerator has a notion of local scope depth,
we can easily implement a catch scope that doesn't claim that
all variables are dynamically scoped. This means that functions
that use try/catch can have local variable resolution. This also
means that all functions that use try/catch don't have all
their variables marked as being captured.
Catch scopes now behave like a "let" scope (sans the TDZ logic) with a
single variable. Catch scopes are now just JSLexicalEnvironments and the
symbol table backing the catch scope knows that it corresponds to a catch scope.
* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/EvalCodeCache.h:
(JSC::EvalCodeCache::isCacheable):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::emitLoadGlobalObject):
(JSC::BytecodeGenerator::pushLexicalScope):
(JSC::BytecodeGenerator::pushLexicalScopeInternal):
(JSC::BytecodeGenerator::popLexicalScope):
(JSC::BytecodeGenerator::popLexicalScopeInternal):
(JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration):
(JSC::BytecodeGenerator::variable):
(JSC::BytecodeGenerator::resolveType):
(JSC::BytecodeGenerator::emitResolveScope):
(JSC::BytecodeGenerator::emitPopScope):
(JSC::BytecodeGenerator::emitPopWithScope):
(JSC::BytecodeGenerator::emitDebugHook):
(JSC::BytecodeGenerator::popScopedControlFlowContext):
(JSC::BytecodeGenerator::emitPushCatchScope):
(JSC::BytecodeGenerator::emitPopCatchScope):
(JSC::BytecodeGenerator::beginSwitch):
(JSC::BytecodeGenerator::emitPopWithOrCatchScope): Deleted.
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::lastOpcodeID):
* bytecompiler/NodesCodegen.cpp:
(JSC::AssignResolveNode::emitBytecode):
(JSC::WithNode::emitBytecode):
(JSC::TryNode::emitBytecode):
* debugger/DebuggerScope.cpp:
(JSC::DebuggerScope::isCatchScope):
(JSC::DebuggerScope::isFunctionNameScope):
(JSC::DebuggerScope::isFunctionOrEvalScope):
(JSC::DebuggerScope::caughtValue):
* debugger/DebuggerScope.h:
* inspector/ScriptDebugServer.cpp:
(Inspector::ScriptDebugServer::exceptionOrCaughtValue):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_push_name_scope):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_push_name_scope):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createContinueStatement):
(JSC::ASTBuilder::createTryStatement):
* parser/NodeConstructors.h:
(JSC::ThrowNode::ThrowNode):
(JSC::TryNode::TryNode):
(JSC::FunctionParameters::FunctionParameters):
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseTryStatement):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createBreakStatement):
(JSC::SyntaxChecker::createContinueStatement):
(JSC::SyntaxChecker::createTryStatement):
(JSC::SyntaxChecker::createSwitchStatement):
(JSC::SyntaxChecker::createWhileStatement):
(JSC::SyntaxChecker::createWithStatement):
* runtime/JSCatchScope.cpp:
* runtime/JSCatchScope.h:
(JSC::JSCatchScope::JSCatchScope): Deleted.
(JSC::JSCatchScope::create): Deleted.
(JSC::JSCatchScope::createStructure): Deleted.
* runtime/JSFunctionNameScope.h:
(JSC::JSFunctionNameScope::JSFunctionNameScope):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::withScopeStructure):
(JSC::JSGlobalObject::strictEvalActivationStructure):
(JSC::JSGlobalObject::activationStructure):
(JSC::JSGlobalObject::functionNameScopeStructure):
(JSC::JSGlobalObject::directArgumentsStructure):
(JSC::JSGlobalObject::scopedArgumentsStructure):
(JSC::JSGlobalObject::catchScopeStructure): Deleted.
* runtime/JSNameScope.cpp:
(JSC::JSNameScope::create):
(JSC::JSNameScope::toThis):
* runtime/JSNameScope.h:
* runtime/JSObject.cpp:
(JSC::JSObject::toThis):
(JSC::JSObject::isFunctionNameScopeObject):
(JSC::JSObject::isCatchScopeObject): Deleted.
* runtime/JSObject.h:
* runtime/JSScope.cpp:
(JSC::JSScope::collectVariablesUnderTDZ):
(JSC::JSScope::isLexicalScope):
(JSC::JSScope::isCatchScope):
(JSC::resolveModeName):
* runtime/JSScope.h:
* runtime/SymbolTable.cpp:
(JSC::SymbolTable::SymbolTable):
(JSC::SymbolTable::cloneScopePart):
* runtime/SymbolTable.h:
* tests/stress/const-semantics.js:
(.):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@187515 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt
index c365475..a273e40 100644
--- a/Source/JavaScriptCore/CMakeLists.txt
+++ b/Source/JavaScriptCore/CMakeLists.txt
@@ -490,7 +490,6 @@
runtime/JSBoundFunction.cpp
runtime/JSCJSValue.cpp
runtime/JSCallee.cpp
- runtime/JSCatchScope.cpp
runtime/JSCell.cpp
runtime/JSConsole.cpp
runtime/JSDataView.cpp
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 6b5431c..c1a0597 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,127 @@
+2015-07-28 Saam barati <saambarati1@gmail.com>
+
+ Implement catch scope using lexical scoping constructs introduced with "let" scoping patch
+ https://bugs.webkit.org/show_bug.cgi?id=146979
+
+ Reviewed by Geoffrey Garen.
+
+ Now that BytecodeGenerator has a notion of local scope depth,
+ we can easily implement a catch scope that doesn't claim that
+ all variables are dynamically scoped. This means that functions
+ that use try/catch can have local variable resolution. This also
+ means that all functions that use try/catch don't have all
+ their variables marked as being captured.
+
+ Catch scopes now behave like a "let" scope (sans the TDZ logic) with a
+ single variable. Catch scopes are now just JSLexicalEnvironments and the
+ symbol table backing the catch scope knows that it corresponds to a catch scope.
+
+ * CMakeLists.txt:
+ * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+ * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dumpBytecode):
+ * bytecode/EvalCodeCache.h:
+ (JSC::EvalCodeCache::isCacheable):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+ (JSC::BytecodeGenerator::emitLoadGlobalObject):
+ (JSC::BytecodeGenerator::pushLexicalScope):
+ (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+ (JSC::BytecodeGenerator::popLexicalScope):
+ (JSC::BytecodeGenerator::popLexicalScopeInternal):
+ (JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration):
+ (JSC::BytecodeGenerator::variable):
+ (JSC::BytecodeGenerator::resolveType):
+ (JSC::BytecodeGenerator::emitResolveScope):
+ (JSC::BytecodeGenerator::emitPopScope):
+ (JSC::BytecodeGenerator::emitPopWithScope):
+ (JSC::BytecodeGenerator::emitDebugHook):
+ (JSC::BytecodeGenerator::popScopedControlFlowContext):
+ (JSC::BytecodeGenerator::emitPushCatchScope):
+ (JSC::BytecodeGenerator::emitPopCatchScope):
+ (JSC::BytecodeGenerator::beginSwitch):
+ (JSC::BytecodeGenerator::emitPopWithOrCatchScope): Deleted.
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::lastOpcodeID):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::WithNode::emitBytecode):
+ (JSC::TryNode::emitBytecode):
+ * debugger/DebuggerScope.cpp:
+ (JSC::DebuggerScope::isCatchScope):
+ (JSC::DebuggerScope::isFunctionNameScope):
+ (JSC::DebuggerScope::isFunctionOrEvalScope):
+ (JSC::DebuggerScope::caughtValue):
+ * debugger/DebuggerScope.h:
+ * inspector/ScriptDebugServer.cpp:
+ (Inspector::ScriptDebugServer::exceptionOrCaughtValue):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::execute):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_push_name_scope):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_push_name_scope):
+ * jit/JITOperations.cpp:
+ * jit/JITOperations.h:
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createContinueStatement):
+ (JSC::ASTBuilder::createTryStatement):
+ * parser/NodeConstructors.h:
+ (JSC::ThrowNode::ThrowNode):
+ (JSC::TryNode::TryNode):
+ (JSC::FunctionParameters::FunctionParameters):
+ * parser/Nodes.h:
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::parseTryStatement):
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::createBreakStatement):
+ (JSC::SyntaxChecker::createContinueStatement):
+ (JSC::SyntaxChecker::createTryStatement):
+ (JSC::SyntaxChecker::createSwitchStatement):
+ (JSC::SyntaxChecker::createWhileStatement):
+ (JSC::SyntaxChecker::createWithStatement):
+ * runtime/JSCatchScope.cpp:
+ * runtime/JSCatchScope.h:
+ (JSC::JSCatchScope::JSCatchScope): Deleted.
+ (JSC::JSCatchScope::create): Deleted.
+ (JSC::JSCatchScope::createStructure): Deleted.
+ * runtime/JSFunctionNameScope.h:
+ (JSC::JSFunctionNameScope::JSFunctionNameScope):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ (JSC::JSGlobalObject::visitChildren):
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::withScopeStructure):
+ (JSC::JSGlobalObject::strictEvalActivationStructure):
+ (JSC::JSGlobalObject::activationStructure):
+ (JSC::JSGlobalObject::functionNameScopeStructure):
+ (JSC::JSGlobalObject::directArgumentsStructure):
+ (JSC::JSGlobalObject::scopedArgumentsStructure):
+ (JSC::JSGlobalObject::catchScopeStructure): Deleted.
+ * runtime/JSNameScope.cpp:
+ (JSC::JSNameScope::create):
+ (JSC::JSNameScope::toThis):
+ * runtime/JSNameScope.h:
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::toThis):
+ (JSC::JSObject::isFunctionNameScopeObject):
+ (JSC::JSObject::isCatchScopeObject): Deleted.
+ * runtime/JSObject.h:
+ * runtime/JSScope.cpp:
+ (JSC::JSScope::collectVariablesUnderTDZ):
+ (JSC::JSScope::isLexicalScope):
+ (JSC::JSScope::isCatchScope):
+ (JSC::resolveModeName):
+ * runtime/JSScope.h:
+ * runtime/SymbolTable.cpp:
+ (JSC::SymbolTable::SymbolTable):
+ (JSC::SymbolTable::cloneScopePart):
+ * runtime/SymbolTable.h:
+ * tests/stress/const-semantics.js:
+ (.):
+
2015-07-28 Filip Pizlo <fpizlo@apple.com>
DFG::ArgumentsEliminationPhase has a redundant check for inserting CheckInBounds when converting GetByVal to GetStack in the inline non-varargs case
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
index 244ba19..a45ab66 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
@@ -745,7 +745,6 @@
<ClCompile Include="..\runtime\JSBoundFunction.cpp" />
<ClCompile Include="..\runtime\JSCJSValue.cpp" />
<ClCompile Include="..\runtime\JSCallee.cpp" />
- <ClCompile Include="..\runtime\JSCatchScope.cpp" />
<ClCompile Include="..\runtime\JSCell.cpp" />
<ClCompile Include="..\runtime\JSConsole.cpp" />
<ClCompile Include="..\runtime\JSDataView.cpp" />
@@ -1557,7 +1556,6 @@
<ClInclude Include="..\runtime\JSCJSValue.h" />
<ClInclude Include="..\runtime\JSCJSValueInlines.h" />
<ClInclude Include="..\runtime\JSCallee.h" />
- <ClInclude Include="..\runtime\JSCatchScope.h" />
<ClInclude Include="..\runtime\JSCell.h" />
<ClInclude Include="..\runtime\JSConsole.h" />
<ClInclude Include="..\runtime\JSDataView.h" />
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
index c5bd549..6ce3677 100644
--- a/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
+++ b/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
@@ -1771,7 +1771,6 @@
<ClCompile Include="..\dfg\DFGPutStackSinkingPhase.cpp" />
<ClCompile Include="..\ftl\FTLJSCallBase.cpp" />
<ClCompile Include="..\ftl\FTLJSCallVarargs.cpp" />
- <ClCompile Include="..\runtime\JSCatchScope.cpp" />
<ClCompile Include="..\runtime\JSFunctionNameScope.cpp" />
<ClCompile Include="..\jit\ExecutableAllocatorFixedVMPool.cpp">
<Filter>jit</Filter>
@@ -4272,7 +4271,6 @@
<ClInclude Include="..\dfg\DFGPutStackSinkingPhase.h" />
<ClInclude Include="..\ftl\FTLJSCallBase.h" />
<ClInclude Include="..\ftl\FTLJSCallVarargs.h" />
- <ClInclude Include="..\runtime\JSCatchScope.h" />
<ClInclude Include="..\runtime\JSFunctionNameScope.h" />
<ClInclude Include="..\runtime\MathCommon.h" />
<ClInclude Include="..\bytecode\BytecodeKills.h" />
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index b4acc194..699e7a6 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -610,8 +610,6 @@
0FD8A32A17D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD8A32217D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD8A32317D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp */; };
0FD8A32C17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD8A32417D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 0FD949821A97DB9600E28966 /* JSCatchScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */; };
- 0FD949831A97DB9600E28966 /* JSCatchScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD9497F1A97DB9600E28966 /* JSCatchScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FD949841A97DB9600E28966 /* JSFunctionNameScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD949801A97DB9600E28966 /* JSFunctionNameScope.cpp */; };
0FD949851A97DB9600E28966 /* JSFunctionNameScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD949811A97DB9600E28966 /* JSFunctionNameScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FDB2CC9173DA520007B3C1B /* FTLAbbreviatedTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDB2CC7173DA51E007B3C1B /* FTLAbbreviatedTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2372,8 +2370,6 @@
0FD8A32217D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGToFTLDeferredCompilationCallback.h; path = dfg/DFGToFTLDeferredCompilationCallback.h; sourceTree = "<group>"; };
0FD8A32317D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGToFTLForOSREntryDeferredCompilationCallback.cpp; path = dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp; sourceTree = "<group>"; };
0FD8A32417D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGToFTLForOSREntryDeferredCompilationCallback.h; path = dfg/DFGToFTLForOSREntryDeferredCompilationCallback.h; sourceTree = "<group>"; };
- 0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCatchScope.cpp; sourceTree = "<group>"; };
- 0FD9497F1A97DB9600E28966 /* JSCatchScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCatchScope.h; sourceTree = "<group>"; };
0FD949801A97DB9600E28966 /* JSFunctionNameScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFunctionNameScope.cpp; sourceTree = "<group>"; };
0FD949811A97DB9600E28966 /* JSFunctionNameScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFunctionNameScope.h; sourceTree = "<group>"; };
0FDB2CC7173DA51E007B3C1B /* FTLAbbreviatedTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FTLAbbreviatedTypes.h; path = ftl/FTLAbbreviatedTypes.h; sourceTree = "<group>"; };
@@ -4530,8 +4526,6 @@
86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
657CF45719BF6662004ACBF2 /* JSCallee.h */,
- 0FD9497E1A97DB9600E28966 /* JSCatchScope.cpp */,
- 0FD9497F1A97DB9600E28966 /* JSCatchScope.h */,
BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
BC1167D80E19BCC9008066DD /* JSCell.h */,
0F97496F1687ADE200A4FF6A /* JSCellInlines.h */,
@@ -6292,7 +6286,6 @@
0F2B9CE719D0BA7D00B1D1B5 /* DFGObjectAllocationSinkingPhase.h in Headers */,
A7CA3AE817DA41AE006538AF /* JSWeakMap.h in Headers */,
A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */,
- 0FD949831A97DB9600E28966 /* JSCatchScope.h in Headers */,
A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */,
1442566215EDE98D0066A49B /* JSWithScope.h in Headers */,
86E3C619167BABEE006D760A /* JSWrapperMap.h in Headers */,
@@ -7435,7 +7428,6 @@
86E3C616167BABEE006D760A /* JSContext.mm in Sources */,
14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */,
70DC3E091B2DF2C700054299 /* IteratorPrototype.cpp in Sources */,
- 0FD949821A97DB9600E28966 /* JSCatchScope.cpp in Sources */,
A72028B61797601E0098028C /* JSCTestRunnerUtils.cpp in Sources */,
0F2B66EB17B6B5AB00A7AE3F /* JSDataView.cpp in Sources */,
0F2B66ED17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp in Sources */,
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 041ff08..8668394 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1457,7 +1457,7 @@
int k0 = (++it)->u.operand;
JSNameScope::Type scopeType = (JSNameScope::Type)(++it)->u.operand;
printLocationAndOp(out, exec, location, it, "push_name_scope");
- out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(r1).data(), constantName(k0).data(), (scopeType == JSNameScope::FunctionNameScope) ? "functionScope" : ((scopeType == JSNameScope::CatchScope) ? "catchScope" : "unknownScopeType"));
+ out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(r1).data(), constantName(k0).data(), (scopeType == JSNameScope::FunctionNameScope) ? "functionScope" : "unknownScopeType");
break;
}
case op_create_lexical_environment: {
diff --git a/Source/JavaScriptCore/bytecode/EvalCodeCache.h b/Source/JavaScriptCore/bytecode/EvalCodeCache.h
index 3a02ef9..4d59093 100644
--- a/Source/JavaScriptCore/bytecode/EvalCodeCache.h
+++ b/Source/JavaScriptCore/bytecode/EvalCodeCache.h
@@ -81,7 +81,8 @@
return !inStrictContext
&& evalSource.length() < Options::maximumEvalCacheableSourceLength()
&& scope->begin()->isVariableObject()
- && !scope->isLexicalScope();
+ && !scope->isLexicalScope()
+ && !scope->isCatchScope();
}
static const int maxCacheEntries = 64;
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 7f31274..548ae44 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -578,7 +578,7 @@
}
// This implements step 25 of section 9.2.12.
- pushLexicalScopeInternal(environment, true, nullptr);
+ pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope);
RefPtr<RegisterID> temp = newTemporary();
for (unsigned i = 0; i < parameters.size(); i++) {
@@ -1357,7 +1357,13 @@
return m_globalObjectRegister;
}
-void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
+void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
+{
+ VariableEnvironment& environment = node->lexicalVariables();
+ pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope);
+}
+
+void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType)
{
if (!environment.size())
return;
@@ -1366,11 +1372,19 @@
environment.markAllVariablesAsCaptured();
Strong<SymbolTable> symbolTable(*m_vm, SymbolTable::create(*m_vm));
- symbolTable->setDoesCorrespondToLexicalScope();
+ switch (scopeType) {
+ case ScopeType::CatchScope:
+ symbolTable->setScopeType(SymbolTable::ScopeType::CatchScope);
+ break;
+ case ScopeType::LetConstScope:
+ symbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope);
+ break;
+ }
+
bool hasCapturedVariables = false;
{
ConcurrentJITLocker locker(symbolTable->m_lock);
- for (auto entry : environment) {
+ for (auto& entry : environment) {
ASSERT(entry.value.isLet() || entry.value.isConst());
ASSERT(!entry.value.isVar());
SymbolTableEntry symbolTableEntry = symbolTable->get(locker, entry.key.get());
@@ -1408,7 +1422,7 @@
instructions().append(newScope->index());
instructions().append(scopeRegister()->index());
instructions().append(constantSymbolTable->index());
- instructions().append(addConstantValue(jsTDZValue())->index());
+ instructions().append(addConstantValue(tdzRequirement == TDZRequirement::UnderTDZ ? jsTDZValue() : jsUndefined())->index());
emitMove(scopeRegister(), newScope);
@@ -1416,31 +1430,34 @@
}
m_symbolTableStack.append(SymbolTableStackEntry{ symbolTable, newScope, false, symbolTableConstantIndex });
- m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks));
- // Prefill stack variables with the TDZ empty value.
- // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated.
- for (auto entry : environment) {
- SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get());
- ASSERT(!symbolTableEntry.isNull());
- VarOffset offset = symbolTableEntry.varOffset();
- if (offset.isScope()) {
- ASSERT(newScope);
- continue;
- }
- ASSERT(offset.isStack());
- emitMoveEmptyValue(®isterFor(offset.stackOffset()));
- }
-}
+ if (tdzRequirement == TDZRequirement::UnderTDZ)
+ m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks));
-void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
-{
- VariableEnvironment& environment = node->lexicalVariables();
- pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult);
+ if (tdzRequirement == TDZRequirement::UnderTDZ) {
+ // Prefill stack variables with the TDZ empty value.
+ // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated.
+ for (auto& entry : environment) {
+ SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get());
+ ASSERT(!symbolTableEntry.isNull());
+ VarOffset offset = symbolTableEntry.varOffset();
+ if (offset.isScope()) {
+ ASSERT(newScope);
+ continue;
+ }
+ ASSERT(offset.isStack());
+ emitMoveEmptyValue(®isterFor(offset.stackOffset()));
+ }
+ }
}
void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node)
{
VariableEnvironment& environment = node->lexicalVariables();
+ popLexicalScopeInternal(environment, TDZRequirement::UnderTDZ);
+}
+
+void BytecodeGenerator::popLexicalScopeInternal(VariableEnvironment& environment, TDZRequirement tdzRequirement)
+{
if (!environment.size())
return;
@@ -1451,7 +1468,7 @@
Strong<SymbolTable> symbolTable = stackEntry.m_symbolTable;
ConcurrentJITLocker locker(symbolTable->m_lock);
bool hasCapturedVariables = false;
- for (auto entry : environment) {
+ for (auto& entry : environment) {
if (entry.value.isCaptured()) {
hasCapturedVariables = true;
continue;
@@ -1471,7 +1488,8 @@
stackEntry.m_scope->deref();
}
- m_TDZStack.removeLast();
+ if (tdzRequirement == TDZRequirement::UnderTDZ)
+ m_TDZStack.removeLast();
}
void BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode* node, RegisterID* loopSymbolTable)
@@ -1576,14 +1594,14 @@
// }
for (unsigned i = m_symbolTableStack.size(); i--; ) {
SymbolTableStackEntry& stackEntry = m_symbolTableStack[i];
- if (stackEntry.m_isWithOrCatch)
+ if (stackEntry.m_isWithScope)
return 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, symbolTable->correspondsToLexicalScope());
+ return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope);
}
return Variable(property);
@@ -1661,7 +1679,7 @@
ResolveType BytecodeGenerator::resolveType()
{
for (unsigned i = m_symbolTableStack.size(); i--; ) {
- if (m_symbolTableStack[i].m_isWithOrCatch)
+ if (m_symbolTableStack[i].m_isWithScope)
return Dynamic;
}
@@ -1688,9 +1706,9 @@
// that code sensible and obviate the need for us to do bad things.
for (unsigned i = m_symbolTableStack.size(); i--; ) {
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
+ // We should not resolve a variable to VarKind::Scope if a "with" scope lies in between the current
// scope and the resolved scope.
- RELEASE_ASSERT(!stackEntry.m_isWithOrCatch);
+ RELEASE_ASSERT(!stackEntry.m_isWithScope);
if (stackEntry.m_symbolTable->get(variable.ident().impl()).isNull())
continue;
@@ -2567,12 +2585,12 @@
emitMove(dst, parentScope.get());
}
-void BytecodeGenerator::emitPopWithOrCatchScope(RegisterID* srcDst)
+void BytecodeGenerator::emitPopWithScope(RegisterID* srcDst)
{
emitPopScope(srcDst, srcDst);
popScopedControlFlowContext();
SymbolTableStackEntry stackEntry = m_symbolTableStack.takeLast();
- RELEASE_ASSERT(stackEntry.m_isWithOrCatch);
+ RELEASE_ASSERT(stackEntry.m_isWithScope);
}
void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, unsigned line, unsigned charOffset, unsigned lineStart)
@@ -3007,17 +3025,19 @@
m_localScopeDepth--;
}
-void BytecodeGenerator::emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)
+void BytecodeGenerator::emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment& environment)
{
- pushScopedControlFlowContext();
+ RELEASE_ASSERT(environment.contains(property.impl()));
+ pushLexicalScopeInternal(environment, true, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::CatchScope);
+ Variable exceptionVar = variable(property);
+ RELEASE_ASSERT(exceptionVar.isResolved());
+ RefPtr<RegisterID> scope = emitResolveScope(nullptr, exceptionVar);
+ emitPutToScope(scope.get(), exceptionVar, exceptionValue, ThrowIfNotFound);
+}
- emitOpcode(op_push_name_scope);
- instructions().append(dst->index());
- instructions().append(value->index());
- instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property, attributes))->index());
- instructions().append(JSNameScope::CatchScope);
-
- m_symbolTableStack.append(SymbolTableStackEntry{ Strong<SymbolTable>(), nullptr, true, 0 });
+void BytecodeGenerator::emitPopCatchScope(VariableEnvironment& environment)
+{
+ popLexicalScopeInternal(environment, TDZRequirement::NotUnderTDZ);
}
void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 3adc510..347f0fe 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -581,12 +581,13 @@
void emitThrowTypeError(const String& message);
void emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
- void emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
+ void emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment&);
+ void emitPopCatchScope(VariableEnvironment&);
void emitGetScope();
RegisterID* emitPushWithScope(RegisterID* dst, RegisterID* scope);
void emitPopScope(RegisterID* dst, RegisterID* scope);
- void emitPopWithOrCatchScope(RegisterID* srcDst);
+ void emitPopWithScope(RegisterID* srcDst);
RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
@@ -622,7 +623,10 @@
OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
private:
- void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult);
+ enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
+ enum class ScopeType { CatchScope, LetConstScope };
+ void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType);
+ void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement);
public:
void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr);
void popLexicalScope(VariableEnvironmentNode*);
@@ -738,7 +742,7 @@
struct SymbolTableStackEntry {
Strong<SymbolTable> m_symbolTable;
RegisterID* m_scope;
- bool m_isWithOrCatch;
+ bool m_isWithScope;
int m_symbolTableConstantIndex;
};
Vector<SymbolTableStackEntry> m_symbolTableStack;
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index da46b9f..7c4ea62 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -1858,8 +1858,8 @@
generator.emitTDZCheckIfNecessary(var, local, nullptr);
if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) {
+ result = generator.emitNode(dst, m_right); // Execute side effects first.
generator.emitReadOnlyExceptionIfNeeded(var);
- result = generator.emitNode(dst, m_right);
} else if (var.isSpecial() || generator.vm()->typeProfiler()) {
RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
generator.emitNode(tempDst.get(), m_right);
@@ -1888,9 +1888,10 @@
dst = 0;
RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) {
+ RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
if (threwException)
- return generator.emitNode(dst, m_right);
+ return result;
}
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
@@ -2683,7 +2684,7 @@
generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
generator.emitPushWithScope(generator.scopeRegister(), scope.get());
generator.emitNode(dst, m_statement);
- generator.emitPopWithOrCatchScope(generator.scopeRegister());
+ generator.emitPopWithScope(generator.scopeRegister());
}
// ------------------------------ CaseClauseNode --------------------------------
@@ -2933,10 +2934,10 @@
tryData = generator.pushTry(here.get());
}
- generator.emitPushCatchScope(generator.scopeRegister(), m_thrownValueIdent, thrownValueRegister.get(), DontDelete);
+ generator.emitPushCatchScope(m_thrownValueIdent, thrownValueRegister.get(), m_catchEnvironment);
generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
generator.emitNode(dst, m_catchBlock);
- generator.emitPopWithOrCatchScope(generator.scopeRegister());
+ generator.emitPopCatchScope(m_catchEnvironment);
generator.emitLabel(catchEndLabel.get());
}
diff --git a/Source/JavaScriptCore/debugger/DebuggerScope.cpp b/Source/JavaScriptCore/debugger/DebuggerScope.cpp
index 6373223..e4788da 100644
--- a/Source/JavaScriptCore/debugger/DebuggerScope.cpp
+++ b/Source/JavaScriptCore/debugger/DebuggerScope.cpp
@@ -167,7 +167,7 @@
bool DebuggerScope::isCatchScope() const
{
- return m_scope->isCatchScopeObject();
+ return m_scope->isCatchScope();
}
bool DebuggerScope::isFunctionNameScope() const
@@ -190,13 +190,20 @@
// In the current debugger implementation, every function or eval will create an
// lexical environment object. Hence, a lexical environment object implies a
// function or eval scope.
- return m_scope->isActivationObject();
+ return m_scope->isActivationObject() && !isCatchScope();
}
-JSValue DebuggerScope::caughtValue() const
+JSValue DebuggerScope::caughtValue(ExecState* exec) const
{
ASSERT(isCatchScope());
- return reinterpret_cast<JSNameScope*>(m_scope.get())->value();
+ JSLexicalEnvironment* catchEnvironment = jsCast<JSLexicalEnvironment*>(m_scope.get());
+ SymbolTable* catchSymbolTable = catchEnvironment->symbolTable();
+ RELEASE_ASSERT(catchSymbolTable->size() == 1);
+ PropertyName errorName(catchSymbolTable->begin(catchSymbolTable->m_lock)->key.get());
+ PropertySlot slot(m_scope.get());
+ bool success = catchEnvironment->getOwnPropertySlot(catchEnvironment, exec, errorName, slot);
+ RELEASE_ASSERT(success && slot.isValue());
+ return slot.getValue(exec, errorName);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/debugger/DebuggerScope.h b/Source/JavaScriptCore/debugger/DebuggerScope.h
index 4416684..e1edb92 100644
--- a/Source/JavaScriptCore/debugger/DebuggerScope.h
+++ b/Source/JavaScriptCore/debugger/DebuggerScope.h
@@ -91,7 +91,7 @@
bool isGlobalScope() const;
bool isFunctionOrEvalScope() const;
- JSValue caughtValue() const;
+ JSValue caughtValue(ExecState*) const;
private:
JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*);
diff --git a/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp b/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
index 74602c5..356de1c 100644
--- a/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
+++ b/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp
@@ -340,7 +340,7 @@
while (debuggerCallFrame) {
DebuggerScope* scope = debuggerCallFrame->scope();
if (scope->isCatchScope())
- return Deprecated::ScriptValue(state->vm(), scope->caughtValue());
+ return Deprecated::ScriptValue(state->vm(), scope->caughtValue(state));
debuggerCallFrame = debuggerCallFrame->callerFrame();
}
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index bf94b90..a25f583 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -1140,7 +1140,7 @@
break;
}
if (JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast<JSLexicalEnvironment*>(node)) {
- if (!lexicalEnvironment->symbolTable()->correspondsToLexicalScope()) {
+ if (lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::VarScope) {
variableObject = node;
break;
}
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index c85871b..54db327 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -497,11 +497,6 @@
{
int dst = currentInstruction[1].u.operand;
emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
- if (currentInstruction[4].u.operand == JSNameScope::CatchScope) {
- callOperation(operationPushCatchScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT0);
- return;
- }
-
RELEASE_ASSERT(currentInstruction[4].u.operand == JSNameScope::FunctionNameScope);
callOperation(operationPushFunctionNameScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT0);
}
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 932657f..2863508 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -804,11 +804,6 @@
{
int dst = currentInstruction[1].u.operand;
emitLoad(currentInstruction[2].u.operand, regT1, regT0);
- if (currentInstruction[4].u.operand == JSNameScope::CatchScope) {
- callOperation(operationPushCatchScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT1, regT0);
- return;
- }
-
RELEASE_ASSERT(currentInstruction[4].u.operand == JSNameScope::FunctionNameScope);
callOperation(operationPushFunctionNameScope, dst, jsCast<SymbolTable*>(getConstantOperand(currentInstruction[3].u.operand)), regT1, regT0);
}
diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp
index a01f2a8..4b58b44 100644
--- a/Source/JavaScriptCore/jit/JITOperations.cpp
+++ b/Source/JavaScriptCore/jit/JITOperations.cpp
@@ -44,7 +44,6 @@
#include "JIT.h"
#include "JITToDFGDeferredCompilationCallback.h"
#include "JSCInlines.h"
-#include "JSCatchScope.h"
#include "JSFunctionNameScope.h"
#include "JSGlobalObjectFunctions.h"
#include "JSLexicalEnvironment.h"
@@ -1364,11 +1363,6 @@
}
#endif
-void JIT_OPERATION operationPushCatchScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
-{
- pushNameScope<JSCatchScope>(exec, dst, symbolTable, encodedValue);
-}
-
void JIT_OPERATION operationPushFunctionNameScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
{
pushNameScope<JSFunctionNameScope>(exec, dst, symbolTable, encodedValue);
diff --git a/Source/JavaScriptCore/jit/JITOperations.h b/Source/JavaScriptCore/jit/JITOperations.h
index 299184b..1709d25 100644
--- a/Source/JavaScriptCore/jit/JITOperations.h
+++ b/Source/JavaScriptCore/jit/JITOperations.h
@@ -304,7 +304,6 @@
void JIT_OPERATION operationPutSetterById(ExecState*, JSCell*, Identifier*, JSCell*) WTF_INTERNAL;
void JIT_OPERATION operationPutGetterSetter(ExecState*, JSCell*, Identifier*, JSCell*, JSCell*) WTF_INTERNAL;
#endif
-void JIT_OPERATION operationPushCatchScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL;
void JIT_OPERATION operationPushFunctionNameScope(ExecState*, int32_t, SymbolTable*, EncodedJSValue) WTF_INTERNAL;
void JIT_OPERATION operationPushWithScope(ExecState*, int32_t, EncodedJSValue) WTF_INTERNAL;
void JIT_OPERATION operationPopScope(ExecState*, int32_t) WTF_INTERNAL;
diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h
index c28c62e..36216d4 100644
--- a/Source/JavaScriptCore/parser/ASTBuilder.h
+++ b/Source/JavaScriptCore/parser/ASTBuilder.h
@@ -555,9 +555,9 @@
return result;
}
- StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
+ StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine, VariableEnvironment& catchEnvironment)
{
- TryNode* result = new (m_parserArena) TryNode(location, tryBlock, *ident, catchBlock, finallyBlock);
+ TryNode* result = new (m_parserArena) TryNode(location, tryBlock, *ident, catchBlock, catchEnvironment, finallyBlock);
if (catchBlock)
usesCatch();
result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset);
diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h
index 6cd7627..dd20b8f 100644
--- a/Source/JavaScriptCore/parser/NodeConstructors.h
+++ b/Source/JavaScriptCore/parser/NodeConstructors.h
@@ -818,13 +818,14 @@
{
}
- inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier& thrownValueIdent, StatementNode* catchBlock, StatementNode* finallyBlock)
+ inline TryNode::TryNode(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier& thrownValueIdent, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock)
: StatementNode(location)
, m_tryBlock(tryBlock)
, m_thrownValueIdent(thrownValueIdent)
, m_catchBlock(catchBlock)
, m_finallyBlock(finallyBlock)
{
+ m_catchEnvironment.swap(catchEnvironment);
}
inline FunctionParameters::FunctionParameters()
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h
index 92fa7e6..000d860 100644
--- a/Source/JavaScriptCore/parser/Nodes.h
+++ b/Source/JavaScriptCore/parser/Nodes.h
@@ -1513,7 +1513,7 @@
class TryNode : public StatementNode {
public:
- TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock);
+ TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, VariableEnvironment& catchEnvironment, StatementNode* finallyBlock);
private:
virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
@@ -1522,6 +1522,7 @@
const Identifier& m_thrownValueIdent;
StatementNode* m_catchBlock;
StatementNode* m_finallyBlock;
+ VariableEnvironment m_catchEnvironment;
};
class ScopeNode : public StatementNode, public ParserArenaRoot, public VariableEnvironmentNode {
diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp
index e00a73a..289f38e 100644
--- a/Source/JavaScriptCore/parser/Parser.cpp
+++ b/Source/JavaScriptCore/parser/Parser.cpp
@@ -1261,9 +1261,8 @@
tryBlock = parseBlockStatement(context);
failIfFalse(tryBlock, "Cannot parse the body of try block");
int lastLine = m_lastTokenEndPosition.line;
-
+ VariableEnvironment catchEnvironment;
if (match(CATCH)) {
- currentScope()->setNeedsFullActivation();
next();
handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
@@ -1274,12 +1273,15 @@
ident = m_token.m_data.ident;
next();
AutoPopScopeRef catchScope(this, pushScope());
- failIfTrueIfStrict(declareVariable(ident) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
- catchScope->preventAllVariableDeclarations();
+ catchScope->setIsLexicalScope();
+ catchScope->preventVarDeclarations();
+ failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
catchBlock = parseBlockStatement(context);
failIfFalse(catchBlock, "Unable to parse 'catch' block");
+ catchEnvironment = catchScope->finalizeLexicalEnvironment();
+ RELEASE_ASSERT(catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl()));
popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
}
@@ -1290,7 +1292,7 @@
failIfFalse(finallyBlock, "Cannot parse finally body");
}
failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
- return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
+ return context.createTryStatement(location, tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
}
template <typename LexerType>
diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h
index 23f448f..786ca8c 100644
--- a/Source/JavaScriptCore/parser/SyntaxChecker.h
+++ b/Source/JavaScriptCore/parser/SyntaxChecker.h
@@ -242,7 +242,7 @@
int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
int createContinueStatement(const JSTokenLocation&, int, int) { return StatementResult; }
int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int) { return StatementResult; }
- int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int) { return StatementResult; }
+ int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int, VariableEnvironment&) { return StatementResult; }
int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int, VariableEnvironment&) { return StatementResult; }
int createWhileStatement(const JSTokenLocation&, int, int, int, int) { return StatementResult; }
int createWithStatement(const JSTokenLocation&, int, int, int, int, int, int) { return StatementResult; }
diff --git a/Source/JavaScriptCore/runtime/JSCatchScope.cpp b/Source/JavaScriptCore/runtime/JSCatchScope.cpp
deleted file mode 100644
index 15e49dd..0000000
--- a/Source/JavaScriptCore/runtime/JSCatchScope.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSCatchScope.h"
-
-#include "JSCInlines.h"
-
-namespace JSC {
-
-const ClassInfo JSCatchScope::s_info = { "CatchScope", &Base::s_info, 0, CREATE_METHOD_TABLE(JSCatchScope) };
-
-} // namespace JSC
-
diff --git a/Source/JavaScriptCore/runtime/JSCatchScope.h b/Source/JavaScriptCore/runtime/JSCatchScope.h
deleted file mode 100644
index 0eeab90..0000000
--- a/Source/JavaScriptCore/runtime/JSCatchScope.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSCatchScope_h
-#define JSCatchScope_h
-
-#include "JSNameScope.h"
-
-namespace JSC {
-
-class JSCatchScope : public JSNameScope {
-public:
- typedef JSNameScope Base;
-
-private:
- friend class JSNameScope;
-
- JSCatchScope(VM& vm, JSGlobalObject* globalObject, JSScope* next, SymbolTable* symbolTable)
- : Base(vm, globalObject->catchScopeStructure(), next, symbolTable)
- {
- }
-
-public:
- static JSCatchScope* create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue value)
- {
- return Base::create<JSCatchScope>(vm, globalObject, currentScope, symbolTable, value);
- }
-
- static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
- {
- return Structure::create(vm, globalObject, proto, TypeInfo(NameScopeObjectType, StructureFlags), info());
- }
-
- DECLARE_INFO;
-};
-
-} // namespace JSC
-
-#endif // JSCatchScope_h
-
diff --git a/Source/JavaScriptCore/runtime/JSFunctionNameScope.h b/Source/JavaScriptCore/runtime/JSFunctionNameScope.h
index 922e89a..7de66ee 100644
--- a/Source/JavaScriptCore/runtime/JSFunctionNameScope.h
+++ b/Source/JavaScriptCore/runtime/JSFunctionNameScope.h
@@ -38,7 +38,7 @@
friend class JSNameScope;
JSFunctionNameScope(VM& vm, JSGlobalObject* globalObject, JSScope* next, SymbolTable* symbolTable)
- : Base(vm, globalObject->catchScopeStructure(), next, symbolTable)
+ : Base(vm, globalObject->functionNameScopeStructure(), next, symbolTable)
{
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 26183ef..29f1037 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -64,7 +64,6 @@
#include "JSCallbackConstructor.h"
#include "JSCallbackFunction.h"
#include "JSCallbackObject.h"
-#include "JSCatchScope.h"
#include "JSConsole.h"
#include "JSDataView.h"
#include "JSDataViewPrototype.h"
@@ -302,7 +301,6 @@
m_typedArrays[toIndex(TypeFloat64)].structure.set(vm, this, JSFloat64Array::createStructure(vm, this, m_typedArrays[toIndex(TypeFloat64)].prototype.get()));
m_typedArrays[toIndex(TypeDataView)].structure.set(vm, this, JSDataView::createStructure(vm, this, m_typedArrays[toIndex(TypeDataView)].prototype.get()));
- m_catchScopeStructure.set(vm, this, JSCatchScope::createStructure(vm, this, jsNull()));
m_functionNameScopeStructure.set(vm, this, JSFunctionNameScope::createStructure(vm, this, jsNull()));
m_lexicalEnvironmentStructure.set(vm, this, JSLexicalEnvironment::createStructure(vm, this));
m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
@@ -773,7 +771,6 @@
visitor.append(&thisObject->m_withScopeStructure);
visitor.append(&thisObject->m_strictEvalActivationStructure);
visitor.append(&thisObject->m_lexicalEnvironmentStructure);
- visitor.append(&thisObject->m_catchScopeStructure);
visitor.append(&thisObject->m_functionNameScopeStructure);
visitor.append(&thisObject->m_directArgumentsStructure);
visitor.append(&thisObject->m_scopedArgumentsStructure);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 99879d1..5792ac2 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -211,7 +211,6 @@
WriteBarrier<Structure> m_withScopeStructure;
WriteBarrier<Structure> m_strictEvalActivationStructure;
WriteBarrier<Structure> m_lexicalEnvironmentStructure;
- WriteBarrier<Structure> m_catchScopeStructure;
WriteBarrier<Structure> m_functionNameScopeStructure;
WriteBarrier<Structure> m_directArgumentsStructure;
WriteBarrier<Structure> m_scopedArgumentsStructure;
@@ -423,7 +422,6 @@
Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
Structure* activationStructure() const { return m_lexicalEnvironmentStructure.get(); }
- Structure* catchScopeStructure() const { return m_catchScopeStructure.get(); }
Structure* functionNameScopeStructure() const { return m_functionNameScopeStructure.get(); }
Structure* directArgumentsStructure() const { return m_directArgumentsStructure.get(); }
Structure* scopedArgumentsStructure() const { return m_scopedArgumentsStructure.get(); }
diff --git a/Source/JavaScriptCore/runtime/JSNameScope.cpp b/Source/JavaScriptCore/runtime/JSNameScope.cpp
index d159f69..3d4a371 100644
--- a/Source/JavaScriptCore/runtime/JSNameScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSNameScope.cpp
@@ -28,7 +28,6 @@
#include "Error.h"
#include "JSCInlines.h"
-#include "JSCatchScope.h"
#include "JSFunctionNameScope.h"
namespace JSC {
@@ -37,14 +36,8 @@
JSNameScope* JSNameScope::create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue value, Type type)
{
- switch (type) {
- case CatchScope:
- return JSCatchScope::create(vm, globalObject, currentScope, symbolTable, value);
- case FunctionNameScope:
- return JSFunctionNameScope::create(vm, globalObject, currentScope, symbolTable, value);
- }
- RELEASE_ASSERT_NOT_REACHED();
- return nullptr;
+ RELEASE_ASSERT(type == FunctionNameScope);
+ return JSFunctionNameScope::create(vm, globalObject, currentScope, symbolTable, value);
}
JSValue JSNameScope::toThis(JSCell*, ExecState* exec, ECMAMode ecmaMode)
diff --git a/Source/JavaScriptCore/runtime/JSNameScope.h b/Source/JavaScriptCore/runtime/JSNameScope.h
index db8d008..54a77b8 100644
--- a/Source/JavaScriptCore/runtime/JSNameScope.h
+++ b/Source/JavaScriptCore/runtime/JSNameScope.h
@@ -38,7 +38,6 @@
static const unsigned StructureFlags = Base::StructureFlags| OverridesGetOwnPropertySlot;
enum Type {
- CatchScope,
FunctionNameScope
};
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 9d49849..01500a6 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -35,7 +35,6 @@
#include "Executable.h"
#include "GetterSetter.h"
#include "IndexingHeaderInlines.h"
-#include "JSCatchScope.h"
#include "JSFunction.h"
#include "JSFunctionNameScope.h"
#include "JSGlobalObject.h"
@@ -1602,11 +1601,6 @@
return jsCast<JSObject*>(cell);
}
-bool JSObject::isCatchScopeObject() const
-{
- return inherits(JSCatchScope::info());
-}
-
bool JSObject::isFunctionNameScopeObject() const
{
return inherits(JSFunctionNameScope::info());
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index d5c61ba..5e1b35a 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -601,7 +601,6 @@
bool isVariableObject() const;
bool isStaticScopeObject() const;
bool isNameScopeObject() const;
- bool isCatchScopeObject() const;
bool isFunctionNameScopeObject() const;
bool isActivationObject() const;
bool isErrorInstance() const;
diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp
index 5022b5d..9ef9df0 100644
--- a/Source/JavaScriptCore/runtime/JSScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSScope.cpp
@@ -193,7 +193,7 @@
if (!scope->isLexicalScope())
continue;
SymbolTable* symbolTable = jsCast<JSLexicalEnvironment*>(scope)->symbolTable();
- ASSERT(symbolTable->correspondsToLexicalScope());
+ ASSERT(symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope);
ConcurrentJITLocker locker(symbolTable->m_lock);
for (auto end = symbolTable->end(locker), iter = symbolTable->begin(locker); iter != end; ++iter)
result.add(iter->key);
@@ -206,9 +206,18 @@
if (!lexicalEnvironment) // Global object does not hold any lexical variables so we can ignore it.
return false;
- return lexicalEnvironment->symbolTable()->correspondsToLexicalScope();
+ return lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::LexicalScope;
}
+bool JSScope::isCatchScope()
+{
+ JSLexicalEnvironment* lexicalEnvironment = jsDynamicCast<JSLexicalEnvironment*>(this);
+ if (!lexicalEnvironment)
+ return false;
+ return lexicalEnvironment->symbolTable()->scopeType() == SymbolTable::ScopeType::CatchScope;
+}
+
+
const char* resolveModeName(ResolveMode mode)
{
static const char* const names[] = {
diff --git a/Source/JavaScriptCore/runtime/JSScope.h b/Source/JavaScriptCore/runtime/JSScope.h
index feb8832..5117f2a 100644
--- a/Source/JavaScriptCore/runtime/JSScope.h
+++ b/Source/JavaScriptCore/runtime/JSScope.h
@@ -165,6 +165,7 @@
static void visitChildren(JSCell*, SlotVisitor&);
bool isLexicalScope();
+ bool isCatchScope();
ScopeChainIterator begin();
ScopeChainIterator end();
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp
index e62599f..02f943f 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.cpp
+++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp
@@ -84,7 +84,7 @@
SymbolTable::SymbolTable(VM& vm)
: JSCell(vm, vm.symbolTableStructure.get())
, m_usesNonStrictEval(false)
- , m_correspondsToLexicalScope(false)
+ , m_scopeType(VarScope)
{
}
@@ -142,7 +142,7 @@
SymbolTable* result = SymbolTable::create(vm);
result->m_usesNonStrictEval = m_usesNonStrictEval;
- result->m_correspondsToLexicalScope = m_correspondsToLexicalScope;
+ result->m_scopeType = m_scopeType;
for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
if (!iter->value.varOffset().isScope())
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index fa2cf93..6849150 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -648,8 +648,14 @@
bool usesNonStrictEval() { return m_usesNonStrictEval; }
void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
- ALWAYS_INLINE bool correspondsToLexicalScope() { return m_correspondsToLexicalScope; }
- void setDoesCorrespondToLexicalScope() { m_correspondsToLexicalScope = true; }
+
+ enum ScopeType {
+ VarScope,
+ LexicalScope,
+ CatchScope
+ };
+ void setScopeType(ScopeType type) { m_scopeType = type; }
+ ScopeType scopeType() const { return static_cast<ScopeType>(m_scopeType); }
SymbolTable* cloneScopePart(VM&);
@@ -678,7 +684,7 @@
std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData;
bool m_usesNonStrictEval : 1;
- bool m_correspondsToLexicalScope : 1;
+ unsigned m_scopeType : 2; // ScopeType
WriteBarrier<ScopedArgumentsTable> m_arguments;
WriteBarrier<InferredValue> m_singletonScope;
diff --git a/Source/JavaScriptCore/tests/stress/const-semantics.js b/Source/JavaScriptCore/tests/stress/const-semantics.js
index b7079a9..d24e066 100644
--- a/Source/JavaScriptCore/tests/stress/const-semantics.js
+++ b/Source/JavaScriptCore/tests/stress/const-semantics.js
@@ -188,17 +188,29 @@
function taz() {
const x = 20;
shouldThrowInvalidConstAssignment(function() { x = 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x += 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x -= 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x *= 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x /= 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x >>= 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x <<= 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x ^= 20; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x++; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { x--; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { ++x; });
+ assert(x === 20);
shouldThrowInvalidConstAssignment(function() { --x; });
+ assert(x === 20);
}
function jaz() {
const x = 20;