Support class static initializers

Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg 2022-07-13 10:48:00 +00:00 committed by Hyukwoo Park
commit 1a5414a0ba
9 changed files with 139 additions and 45 deletions

View file

@ -458,6 +458,7 @@ public:
InitStaticPrivateField,
SetStaticFieldData,
SetStaticPrivateFieldData,
RunStaticInitializer,
CleanupStaticData,
};
@ -582,6 +583,17 @@ public:
{
}
enum RunStaticInitializerTag {
RunStaticInitializerTagValue
};
InitializeClass(const ByteCodeLOC& loc, const size_t classRegisterIndex, const size_t valueIndex, RunStaticInitializerTag)
: ByteCode(Opcode::InitializeClassOpcode, loc)
, m_stage(Stage::RunStaticInitializer)
, m_classConstructorRegisterIndex(classRegisterIndex)
, m_staticPropertySetRegisterIndex(valueIndex)
{
}
InitializeClass(const ByteCodeLOC& loc, const size_t classRegisterIndex)
: ByteCode(Opcode::InitializeClassOpcode, loc)
, m_stage(Stage::CleanupStaticData)
@ -666,6 +678,8 @@ public:
printf("set static field r%u.? = r%u", m_classConstructorRegisterIndex, m_staticPropertySetRegisterIndex);
} else if (m_stage == Stage::SetStaticPrivateFieldData) {
printf("set static private field r%u.? = r%u(%u)", m_classConstructorRegisterIndex, m_staticPrivatePropertySetRegisterIndex, m_setStaticPrivateFieldType);
} else if (m_stage == Stage::RunStaticInitializer) {
printf("run static initializer r%u(r%u)", m_classConstructorRegisterIndex, m_staticPropertySetRegisterIndex);
} else {
ASSERT(m_stage == Stage::CleanupStaticData);
printf("cleanup static field data r%u", m_classConstructorRegisterIndex);

View file

@ -2685,7 +2685,7 @@ NEVER_INLINE void ByteCodeInterpreter::createFunctionOperation(ExecutionState& s
Object* homeObject = (cb->isObjectMethod() || cb->isClassMethod() || cb->isClassStaticMethod()) ? registerFile[code->m_homeObjectRegisterIndex].asObject() : nullptr;
registerFile[code->m_registerIndex] = new ScriptAsyncFunctionObject(state, proto, cb, outerLexicalEnvironment, thisValue, homeObject);
} else if (cb->isArrowFunctionExpression()) {
if (UNLIKELY(cb->isOneExpressionOnlyVirtualArrowFunctionExpression())) {
if (UNLIKELY(cb->isOneExpressionOnlyVirtualArrowFunctionExpression() || cb->isFunctionBodyOnlyVirtualArrowFunctionExpression())) {
registerFile[code->m_registerIndex] = new ScriptVirtualArrowFunctionObject(state, proto, cb, outerLexicalEnvironment);
} else {
registerFile[code->m_registerIndex] = new ScriptArrowFunctionObject(state, proto, cb, outerLexicalEnvironment, registerFile[code->m_homeObjectRegisterIndex]);
@ -3041,6 +3041,9 @@ NEVER_INLINE void ByteCodeInterpreter::initializeClassOperation(ExecutionState&
} else {
classConstructor->addPrivateField(state, contextObject, AtomicString(state, Value(std::get<0>(classConstructor->m_staticFieldInitData[code->m_staticPrivateFieldSetIndex])).asString()), v);
}
} else if (code->m_stage == InitializeClass::RunStaticInitializer) {
Value v = registerFile[code->m_staticPropertySetRegisterIndex];
v = v.asPointerValue()->asScriptVirtualArrowFunctionObject()->call(state, Value(classConstructor), classConstructor);
} else {
ASSERT(code->m_stage == InitializeClass::CleanupStaticData);
classConstructor->m_staticFieldInitData.clear();

View file

@ -202,6 +202,7 @@ InterpretedCodeBlock::InterpretedCodeBlock(Context* ctx, Script* script, StringV
, m_isFunctionDeclaration(false)
, m_isArrowFunctionExpression(false)
, m_isOneExpressionOnlyVirtualArrowFunctionExpression(false)
, m_isFunctionBodyOnlyVirtualArrowFunctionExpression(false)
, m_isClassConstructor(false)
, m_isDerivedClassConstructor(false)
, m_isObjectMethod(false)
@ -263,6 +264,7 @@ InterpretedCodeBlock::InterpretedCodeBlock(Context* ctx, Script* script, StringV
, m_isFunctionDeclaration(false)
, m_isArrowFunctionExpression(false)
, m_isOneExpressionOnlyVirtualArrowFunctionExpression(false)
, m_isFunctionBodyOnlyVirtualArrowFunctionExpression(false)
, m_isClassConstructor(false)
, m_isDerivedClassConstructor(false)
, m_isObjectMethod(false)
@ -324,6 +326,7 @@ InterpretedCodeBlock::InterpretedCodeBlock(Context* ctx, Script* script)
, m_isFunctionDeclaration(false)
, m_isArrowFunctionExpression(false)
, m_isOneExpressionOnlyVirtualArrowFunctionExpression(false)
, m_isFunctionBodyOnlyVirtualArrowFunctionExpression(false)
, m_isClassConstructor(false)
, m_isDerivedClassConstructor(false)
, m_isObjectMethod(false)
@ -411,6 +414,7 @@ void InterpretedCodeBlock::recordFunctionParsingInfo(ASTScopeContext* scopeCtx,
m_isArrowFunctionExpression = scopeCtx->m_isArrowFunctionExpression;
m_isOneExpressionOnlyVirtualArrowFunctionExpression = scopeCtx->m_isOneExpressionOnlyVirtualArrowFunctionExpression;
m_isFunctionBodyOnlyVirtualArrowFunctionExpression = scopeCtx->m_isFunctionBodyOnlyVirtualArrowFunctionExpression;
m_isClassConstructor = scopeCtx->m_isClassConstructor;
m_isDerivedClassConstructor = scopeCtx->m_isDerivedClassConstructor;
m_isObjectMethod = scopeCtx->m_isObjectMethod;

View file

@ -575,6 +575,11 @@ public:
return m_isOneExpressionOnlyVirtualArrowFunctionExpression;
}
bool isFunctionBodyOnlyVirtualArrowFunctionExpression() const
{
return m_isFunctionBodyOnlyVirtualArrowFunctionExpression;
}
bool isClassConstructor() const
{
return m_isClassConstructor;
@ -893,6 +898,8 @@ protected:
bool m_isArrowFunctionExpression : 1;
// one expression only arrow function only contains one expression in body(no param, no placeholder, no brace)
bool m_isOneExpressionOnlyVirtualArrowFunctionExpression : 1;
// one function body only arrow function only contains one code block(no param, no placeholder, starts with brace)
bool m_isFunctionBodyOnlyVirtualArrowFunctionExpression : 1;
bool m_isClassConstructor : 1;
bool m_isDerivedClassConstructor : 1;
bool m_isObjectMethod : 1;

View file

@ -285,6 +285,8 @@ struct ASTScopeContext {
bool m_isArrowFunctionExpression : 1;
// one expression only arrow function only contains one expression in body(no param, no placeholder, no brace)
bool m_isOneExpressionOnlyVirtualArrowFunctionExpression : 1;
// one function body only arrow function only contains one code block(no param, no placeholder, starts with brace)
bool m_isFunctionBodyOnlyVirtualArrowFunctionExpression : 1;
bool m_isClassConstructor : 1;
bool m_isDerivedClassConstructor : 1;
bool m_isObjectMethod : 1;
@ -669,6 +671,7 @@ struct ASTScopeContext {
, m_inWith(false)
, m_isArrowFunctionExpression(false)
, m_isOneExpressionOnlyVirtualArrowFunctionExpression(false)
, m_isFunctionBodyOnlyVirtualArrowFunctionExpression(false)
, m_isClassConstructor(false)
, m_isDerivedClassConstructor(false)
, m_isObjectMethod(false)

View file

@ -211,6 +211,14 @@ public:
}
context->giveUpRegister();
continue;
} else if (p->kind() == ClassElementNode::StaticInitializer) {
ByteCodeRegisterIndex valueIndex = context->getRegister();
p->value()->generateExpressionByteCode(codeBlock, context, valueIndex);
codeBlock->pushCode(InitializeClass(ByteCodeLOC(m_loc.index), context->m_classInfo.m_constructorIndex, valueIndex,
InitializeClass::RunStaticInitializerTagValue),
context, this);
context->giveUpRegister();
continue;
}
bool hasKeyName = p->key()->isIdentifier() && !p->isComputed();

View file

@ -33,9 +33,9 @@ public:
Set,
Method,
Field,
StaticInitializer,
};
ClassElementNode(Node* key, Node* value, Kind kind, bool isComputed, bool isStatic, bool isPrivate)
: Node()
, m_key(key)

View file

@ -1104,7 +1104,7 @@ public:
switch (this->lookahead.type) {
case Token::IdentifierToken: {
if ((this->sourceType == SourceType::Module || this->currentScopeContext->m_isAsync) && this->lookahead.equalsToKeyword(AwaitKeyword)) {
if ((this->sourceType == SourceType::Module || this->currentScopeContext->m_isAsync || this->currentScopeContext->m_isFunctionBodyOnlyVirtualArrowFunctionExpression) && this->lookahead.equalsToKeyword(AwaitKeyword)) {
this->throwUnexpectedToken(this->lookahead);
}
if (this->matchAsyncFunction()) {
@ -1639,6 +1639,79 @@ public:
return expr;
}
template <class ASTBuilder>
ASTNode parseClassStaticInitializer(ASTBuilder& builder, const AtomicString& className, size_t debuggerLineStart)
{
UNUSED_VARIABLE(debuggerLineStart);
ASTNode result;
if (!this->isParsingSingleFunction) {
BEGIN_FUNCTION_SCANNING(AtomicString());
auto startNode = this->createNode();
this->currentScopeContext->m_functionStartLOC.index = startNode.index;
this->currentScopeContext->m_functionStartLOC.column = startNode.column;
this->currentScopeContext->m_functionStartLOC.line = startNode.line;
this->currentScopeContext->m_allowSuperCall = false;
this->currentScopeContext->m_allowSuperProperty = true;
this->currentScopeContext->m_allowArguments = false;
this->currentScopeContext->m_isArrowFunctionExpression = true;
this->currentScopeContext->m_isFunctionBodyOnlyVirtualArrowFunctionExpression = true;
this->currentScopeContext->m_nodeType = ASTNodeType::ArrowFunctionExpression;
#ifdef ESCARGOT_DEBUGGER
this->currentScopeContext->m_needRareData = true;
this->currentScopeContext->m_debuggerLineStart = debuggerLineStart;
#endif /* ESCARGOT_DEBUGGER */
bool allowYield = this->context->allowYield;
bool await = this->context->await;
bool arguments = this->context->allowArguments;
this->context->allowYield = false;
this->context->await = false;
this->context->allowArguments = false;
this->parseFunctionSourceElements(newBuilder);
auto lastContext = this->lastPoppedScopeContext;
this->context->allowYield = allowYield;
this->context->await = await;
this->context->allowArguments = arguments;
this->currentScopeContext->m_bodyEndLOC.index = this->lastMarker.index;
#if !(defined NDEBUG) || defined ESCARGOT_DEBUGGER
this->currentScopeContext->m_bodyEndLOC.line = this->lastMarker.lineNumber;
this->currentScopeContext->m_bodyEndLOC.column = this->lastMarker.index - this->lastMarker.lineStart;
#endif
END_FUNCTION_SCANNING();
this->lastPoppedScopeContext = lastContext;
// wrap right expression with arrow function
result = this->finalize(startNode, builder.createArrowFunctionExpressionNode(subCodeBlockIndex));
} else {
auto startNode = this->createNode();
InterpretedCodeBlock* currentTarget = this->codeBlock;
size_t orgIndex = this->lookahead.start;
InterpretedCodeBlock* childBlock = currentTarget->childBlockAt(this->subCodeBlockIndex);
this->scanner->index = childBlock->src().length() + childBlock->functionStart().index - currentTarget->functionStart().index;
this->scanner->lineNumber = childBlock->functionStart().line;
this->scanner->lineStart = childBlock->functionStart().index - childBlock->functionStart().column;
this->lookahead.lineNumber = this->scanner->lineNumber;
this->lookahead.lineStart = this->scanner->lineStart;
this->nextToken();
// increase subCodeBlockIndex because parsing of an internal function is skipped
this->subCodeBlockIndex++;
result = this->finalize(startNode, builder.createArrowFunctionExpressionNode(subCodeBlockIndex));
}
return result;
}
template <class ASTBuilder>
ASTNode parseClassFieldInitializer(ASTBuilder& builder, size_t debuggerLineStart)
{
@ -1945,6 +2018,10 @@ public:
// check if restricted words are used as target in array/object initializer
if (shorthand && this->context->strict && token->type == Token::IdentifierToken) {
if (this->currentScopeContext->m_isFunctionBodyOnlyVirtualArrowFunctionExpression && token->equalsToKeyword(AwaitKeyword)) {
this->throwUnexpectedToken(*token);
}
AtomicString name;
name = keyNode->asIdentifier()->name();
if (this->scanner->isRestrictedWord(name)) {
@ -3783,7 +3860,7 @@ public:
} else if (this->context->strict || token->type != Token::KeywordToken || !token->equalsToKeywordNoEscape(LetKeyword) || kind != VarKeyword) {
this->throwUnexpectedToken(*token);
}
} else if ((this->sourceType == Module || this->currentScopeContext->m_isAsync) && token->type == Token::IdentifierToken && token->equalsToKeyword(AwaitKeyword)) {
} else if ((this->sourceType == Module || this->currentScopeContext->m_isAsync || this->currentScopeContext->m_isFunctionBodyOnlyVirtualArrowFunctionExpression) && token->type == Token::IdentifierToken && token->equalsToKeyword(AwaitKeyword)) {
this->throwUnexpectedToken(*token);
} else if (UNLIKELY(this->context->strict && token->type == Token::IdentifierToken
&& token->hasAllocatedString && token->isStrictModeReservedWord())) {
@ -4421,7 +4498,7 @@ public:
template <class ASTBuilder>
ASTNode parseReturnStatement(ASTBuilder& builder)
{
if (!this->context->inFunctionBody) {
if (!this->context->inFunctionBody || this->currentScopeContext->m_isFunctionBodyOnlyVirtualArrowFunctionExpression) {
this->throwError(Messages::IllegalReturn);
}
@ -5283,7 +5360,7 @@ public:
ALLOC_TOKEN(token);
*token = this->lookahead;
TrackUsingNameBlocker blocker(this);
id = (!this->context->strict && !isGenerator && this->matchKeyword(YieldKeyword)) ? this->parseIdentifierName(builder) : this->parseVariableIdentifier(builder);
id = ((!this->context->strict && !isGenerator && this->matchKeyword(YieldKeyword)) || (this->currentScopeContext->m_isFunctionBodyOnlyVirtualArrowFunctionExpression && this->sourceType != Module && token->type == Token::IdentifierToken && token->equalsToKeyword(AwaitKeyword))) ? this->parseIdentifierName(builder) : this->parseVariableIdentifier(builder);
if (this->context->strict) {
if (this->scanner->isRestrictedWord(token->relatedSource(this->scanner->source))) {
@ -5760,12 +5837,16 @@ public:
computed = this->match(LeftSquareBracket);
keyNode = this->parseObjectPropertyKey(builder, !computed, &isPrivate);
if (token->type == Token::KeywordToken && token->equalsToKeywordNoEscape(StaticKeyword) && (this->qualifiedPropertyName(&this->lookahead) || this->match(Multiply) || this->match(Hash))) {
if (token->type == Token::KeywordToken && token->equalsToKeywordNoEscape(StaticKeyword) && (this->qualifiedPropertyName(&this->lookahead) || this->match(Multiply) || this->match(Hash) || this->match(LeftBrace))) {
*token = this->lookahead;
isStatic = true;
#ifdef ESCARGOT_DEBUGGER
debuggerLineStart = token->lineNumber;
#endif /* ESCARGOT_DEBUGGER */
if (this->match(LeftBrace)) {
value = this->parseClassStaticInitializer(builder, className, debuggerLineStart);
return this->finalize(node, builder.createClassElementNode(keyNode, value, ClassElementNode::Kind::StaticInitializer, false, true, false));
}
mayMethodStartNode = this->createNode();
computed = this->match(LeftSquareBracket);
if (this->match(Multiply)) {
@ -6141,7 +6222,7 @@ public:
idNode = this->parseVariableIdentifier(builder);
id = idNode->asIdentifier()->name();
if (this->sourceType == Module && idToken->equalsToKeyword(AwaitKeyword)) {
if ((this->sourceType == Module || this->currentScopeContext->m_isFunctionBodyOnlyVirtualArrowFunctionExpression) && idToken->equalsToKeyword(AwaitKeyword)) {
this->throwUnexpectedToken(*idToken, Messages::UnexpectedReserved);
}
if (idToken->isStrictModeReservedWord()) {
@ -6796,7 +6877,7 @@ public:
this->nextToken();
}
if (UNLIKELY(this->codeBlock->isOneExpressionOnlyVirtualArrowFunctionExpression())) {
if (UNLIKELY(this->codeBlock->isOneExpressionOnlyVirtualArrowFunctionExpression() || this->codeBlock->isFunctionBodyOnlyVirtualArrowFunctionExpression())) {
params = builder.createStatementContainer();
if (this->codeBlock->parameterNames().size()) {
@ -6823,13 +6904,17 @@ public:
bool previousAllowYield = this->context->allowYield;
this->context->allowYield = false;
MetaNode nodeStart = this->createNode();
Node* expr = this->isolateCoverGrammar(builder, &Parser::parseAssignmentExpression<NodeGenerator, false>);
if (this->codeBlock->isFunctionBodyOnlyVirtualArrowFunctionExpression()) {
body = parseFunctionBody(builder);
} else {
MetaNode nodeStart = this->createNode();
Node* expr = this->isolateCoverGrammar(builder, &Parser::parseAssignmentExpression<NodeGenerator, false>);
StatementContainer* container = builder.createStatementContainer();
Node* node = this->finalize(nodeStart, builder.createReturnStatementNode(expr));
container->appendChild(node, nullptr);
body = this->finalize(nodeStart, builder.createBlockStatementNode(container));
StatementContainer* container = builder.createStatementContainer();
Node* node = this->finalize(nodeStart, builder.createReturnStatementNode(expr));
container->appendChild(node, nullptr);
body = this->finalize(nodeStart, builder.createBlockStatementNode(container));
}
this->context->strict = previousStrict;
this->context->allowYield = previousAllowYield;

View file

@ -3554,7 +3554,6 @@
<test id="language/expressions/call/tco-non-eval-global"><reason>TODO</reason></test>
<test id="language/expressions/call/tco-non-eval-with"><reason>TODO</reason></test>
<test id="language/expressions/class/scope-name-lex-open-heritage"><reason>TODO</reason></test>
<test id="language/expressions/class/static-init-await-reference"><reason>TODO</reason></test>
<test id="language/expressions/coalesce/chainable-if-parenthesis-covered-logical-and"><reason>TODO</reason></test>
<test id="language/expressions/coalesce/chainable-if-parenthesis-covered-logical-or"><reason>TODO</reason></test>
<test id="language/expressions/coalesce/tco-pos-null"><reason>TODO</reason></test>
@ -3670,12 +3669,8 @@
<test id="language/expressions/dynamic-import/trailing-comma-fulfill"><reason>TODO</reason></test>
<test id="language/expressions/dynamic-import/trailing-comma-reject"><reason>TODO</reason></test>
<test id="language/expressions/function/eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/expressions/function/static-init-await-binding"><reason>TODO</reason></test>
<test id="language/expressions/function/static-init-await-reference"><reason>TODO</reason></test>
<test id="language/expressions/generators/eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/expressions/generators/generator-created-after-decl-inst"><reason>TODO</reason></test>
<test id="language/expressions/generators/static-init-await-binding"><reason>TODO</reason></test>
<test id="language/expressions/generators/static-init-await-reference"><reason>TODO</reason></test>
<test id="language/expressions/generators/yield-as-generator-expression-binding-identifier"><reason>TODO</reason></test>
<test id="language/expressions/in/private-field-presence-accessor"><reason>TODO</reason></test>
<test id="language/expressions/in/private-field-presence-accessor-shadowed"><reason>TODO</reason></test>
@ -3703,20 +3698,12 @@
<test id="language/expressions/object/dstr/object-rest-proxy-get-not-called-on-dontenum-keys"><reason>TODO</reason></test>
<test id="language/expressions/object/dstr/object-rest-proxy-gopd-not-called-on-excluded-keys"><reason>TODO</reason></test>
<test id="language/expressions/object/dstr/object-rest-proxy-ownkeys-returned-keys-order"><reason>TODO</reason></test>
<test id="language/expressions/object/ident-name-prop-name-literal-await-static-init"><reason>TODO</reason></test>
<test id="language/expressions/object/identifier-shorthand-static-init-await-valid"><reason>TODO</reason></test>
<test id="language/expressions/object/identifier-shorthand-yield-invalid-strict-mode"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/async-gen-meth-eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/early-errors-object-async-method-duplicate-parameters"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/gen-meth-eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/meth-eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/static-init-await-binding-accessor"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/static-init-await-binding-generator"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/static-init-await-binding-normal"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/static-init-await-reference-accessor"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/static-init-await-reference-generator"><reason>TODO</reason></test>
<test id="language/expressions/object/method-definition/static-init-await-reference-normal"><reason>TODO</reason></test>
<test id="language/expressions/object/object-spread-proxy-get-not-called-on-dontenum-keys"><reason>TODO</reason></test>
<test id="language/expressions/object/object-spread-proxy-no-excluded-keys"><reason>TODO</reason></test>
<test id="language/expressions/object/object-spread-proxy-ownkeys-returned-keys-order"><reason>TODO</reason></test>
@ -3913,24 +3900,13 @@
<test id="language/statements/class/private-static-getter-non-static-setter-early-error"><reason>TODO</reason></test>
<test id="language/statements/class/private-static-setter-non-static-getter-early-error"><reason>TODO</reason></test>
<test id="language/statements/class/scope-name-lex-open-heritage"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-abrupt"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-arguments-functions"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-arguments-methods"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-await-binding-valid"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-expr-new-target"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-expr-this"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-scope-lex-close"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-scope-lex-derived"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-scope-lex-open"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-scope-private"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-scope-var-close"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-scope-var-derived"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-scope-var-open"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-sequence"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-statement-list-optional"><reason>TODO</reason></test>
<test id="language/statements/class/static-init-super-property"><reason>TODO</reason></test>
<test id="language/statements/class/subclass/default-constructor-spread-override"><reason>TODO</reason></test>
<test id="language/statements/const/static-init-await-binding-valid"><reason>TODO</reason></test>
<test id="language/statements/do-while/tco-body"><reason>TODO</reason></test>
<test id="language/statements/for-await-of/async-func-decl-dstr-array-elem-target-simple-strict"><reason>TODO</reason></test>
<test id="language/statements/for-await-of/head-lhs-async"><reason>TODO</reason></test>
@ -3975,13 +3951,11 @@
<test id="language/statements/for/tco-lhs-body"><reason>TODO</reason></test>
<test id="language/statements/for/tco-var-body"><reason>TODO</reason></test>
<test id="language/statements/function/eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/statements/function/static-init-await-binding-valid"><reason>TODO</reason></test>
<test id="language/statements/generators/eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/statements/generators/generator-created-after-decl-inst"><reason>TODO</reason></test>
<test id="language/statements/if/tco-else-body"><reason>TODO</reason></test>
<test id="language/statements/if/tco-if-body"><reason>TODO</reason></test>
<test id="language/statements/labeled/tco"><reason>TODO</reason></test>
<test id="language/statements/let/static-init-await-binding-valid"><reason>TODO</reason></test>
<test id="language/statements/return/tco"><reason>TODO</reason></test>
<test id="language/statements/switch/syntax/redeclaration/var-name-redeclaration-attempt-with-function"><reason>TODO</reason></test>
<test id="language/statements/switch/tco-case-body"><reason>TODO</reason></test>
@ -3990,13 +3964,9 @@
<test id="language/statements/try/completion-values"><reason>TODO</reason></test>
<test id="language/statements/try/early-catch-function"><reason>TODO</reason></test>
<test id="language/statements/try/early-catch-lex"><reason>TODO</reason></test>
<test id="language/statements/try/static-init-await-binding-valid"><reason>TODO</reason></test>
<test id="language/statements/try/tco-catch"><reason>TODO</reason></test>
<test id="language/statements/try/tco-catch-finally"><reason>TODO</reason></test>
<test id="language/statements/try/tco-finally"><reason>TODO</reason></test>
<test id="language/statements/variable/dstr/ary-ptrn-elem-id-static-init-await-valid"><reason>TODO</reason></test>
<test id="language/statements/variable/dstr/obj-ptrn-elem-id-static-init-await-valid"><reason>TODO</reason></test>
<test id="language/statements/variable/static-init-await-binding-valid"><reason>TODO</reason></test>
<test id="language/statements/while/tco-body"><reason>TODO</reason></test>
<test id="language/statements/with/unscopables-inc-dec"><reason>TODO</reason></test>
</excludeList>