Skip to content

Commit

Permalink
Fix calculation of identifiers located in parameter scoped functions
Browse files Browse the repository at this point in the history
Signed-off-by: HyukWoo Park <[email protected]>
  • Loading branch information
clover2123 authored and ksh8281 committed Aug 30, 2024
1 parent d398f1e commit 7589396
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 48 deletions.
6 changes: 4 additions & 2 deletions src/parser/CodeBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,10 @@ std::pair<bool, size_t> InterpretedCodeBlock::tryCaptureIdentifiersFromChildCode
}


if (blockIndex < m_functionBodyBlockIndex) {
if (!isParameterName(name)) {
if (UNLIKELY(blockIndex < m_functionBodyBlockIndex)) {
// case for functions located in parameters
if (!isParameterName(name) && name != m_context->staticStrings().arguments) {
// it's possible to access parameter or arguemnts object of upper function
return std::make_pair(false, SIZE_MAX);
}
}
Expand Down
77 changes: 31 additions & 46 deletions src/parser/ScriptParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,57 +176,42 @@ InterpretedCodeBlock* ScriptParser::generateCodeBlockTreeFromASTWalker(Context*
AtomicString arguments = ctx->staticStrings().arguments;

for (size_t i = 0; i < scopeCtx->m_childBlockScopes.size(); i++) {
for (size_t j = 0; j < scopeCtx->m_childBlockScopes[i]->m_usingNames.size(); j++) {
AtomicString uname = scopeCtx->m_childBlockScopes[i]->m_usingNames[j];
auto blockIndex = scopeCtx->m_childBlockScopes[i]->m_blockIndex;
if (uname == arguments) {
if (UNLIKELY(codeBlock->hasParameterName(arguments))) {
continue;
} else {
bool hasKindOfArgumentsHolderOnAncestors = false;
ASTBlockContext* childBlockContext = scopeCtx->m_childBlockScopes[i];

InterpretedCodeBlock* argumentsObjectHolder = codeBlock;
while (argumentsObjectHolder) {
if (argumentsObjectHolder->isKindOfFunction() && !argumentsObjectHolder->isArrowFunctionExpression()) {
hasKindOfArgumentsHolderOnAncestors = true;
break;
}
argumentsObjectHolder = argumentsObjectHolder->parent();
for (size_t j = 0; j < childBlockContext->m_usingNames.size(); j++) {
AtomicString uname = childBlockContext->m_usingNames[j];
auto blockIndex = childBlockContext->m_blockIndex;

if (uname == arguments) {
// handle `arguments` object
bool needToCaptureArguments = false;
InterpretedCodeBlock* argumentsObjectHolder = codeBlock;
while (argumentsObjectHolder && !argumentsObjectHolder->isGlobalCodeBlock()) {
if (UNLIKELY(argumentsObjectHolder->hasParameterName(arguments))) {
// no need to create arguments object since it has a parameter of which name is `arguments`
break;
}
if (argumentsObjectHolder->isKindOfFunction() && !argumentsObjectHolder->isArrowFunctionExpression()) {
// find the target function of arguments object
needToCaptureArguments = true;
break;
}
argumentsObjectHolder = argumentsObjectHolder->parent();
}

if (hasKindOfArgumentsHolderOnAncestors && !argumentsObjectHolder->hasParameterName(arguments)) {
InterpretedCodeBlock* argumentsVariableHolder = nullptr;
InterpretedCodeBlock* c = codeBlock->parent();
while (c && !c->isGlobalCodeBlock()) {
if (c->hasParameterName(arguments)) {
argumentsVariableHolder = c;
break;
} else if (!c->isArrowFunctionExpression()) {
argumentsVariableHolder = c;
break;
}
c = c->parent();
}
if (needToCaptureArguments) {
ASSERT(argumentsObjectHolder->isKindOfFunction() && !argumentsObjectHolder->isArrowFunctionExpression());
argumentsObjectHolder->captureArguments();

if (LIKELY(!codeBlock->isArrowFunctionExpression())) {
codeBlock->captureArguments();
continue;
} else {
InterpretedCodeBlock* p = codeBlock;
while (p) {
if (!p->isArrowFunctionExpression()) {
break;
}
p->m_usesArgumentsObject = true;
p = p->parent();
}
if (argumentsVariableHolder) {
argumentsVariableHolder->captureArguments();
}
if (!codeBlock->isKindOfFunction() || codeBlock->isArrowFunctionExpression()) {
codeBlock->markHeapAllocatedEnvironmentFromHere(blockIndex, argumentsVariableHolder);
}
if (UNLIKELY(!codeBlock->isKindOfFunction() || codeBlock->isArrowFunctionExpression())) {
InterpretedCodeBlock* p = codeBlock;
while (p != argumentsObjectHolder) {
// mark all eval code or arrow function located to the target argumentsObjectHolder to use ArgumentsObject
p->m_usesArgumentsObject = true;
p = p->parent();
}
ASSERT(p == argumentsObjectHolder);
codeBlock->markHeapAllocatedEnvironmentFromHere(blockIndex, argumentsObjectHolder);
}
}
}
Expand Down

0 comments on commit 7589396

Please sign in to comment.