Beispiel #1
0
Symbol * Symbol::GetFuncScopeVarSym() const
{
    if (!this->GetIsBlockVar())
    {
        return nullptr;
    }
    FuncInfo * parentFuncInfo = this->GetScope()->GetFunc();
    if (parentFuncInfo->GetIsStrictMode())
    {
        return nullptr;
    }
    Symbol *fncScopeSym = parentFuncInfo->GetBodyScope()->FindLocalSymbol(this->GetName());
    if (fncScopeSym == nullptr && parentFuncInfo->GetParamScope() != nullptr)
    {
        // We couldn't find the sym in the body scope, try finding it in the parameter scope.
        Scope* paramScope = parentFuncInfo->GetParamScope();
        fncScopeSym = paramScope->FindLocalSymbol(this->GetName());
        if (fncScopeSym == nullptr)
        {
            FuncInfo* parentParentFuncInfo = paramScope->GetEnclosingScope()->GetFunc();
            if (parentParentFuncInfo->root->sxFnc.IsAsync())
            {
                // In the case of async functions the func-scope var sym might have
                // come from the parent function parameter scope due to the syntax
                // desugaring implementation of async functions.
                fncScopeSym = parentParentFuncInfo->GetBodyScope()->FindLocalSymbol(this->GetName());
                if (fncScopeSym == nullptr)
                {
                    fncScopeSym = parentParentFuncInfo->GetParamScope()->FindLocalSymbol(this->GetName());
                }
            }
        }
    }
    Assert(fncScopeSym);
    // Parser should have added a fake var decl node for block scoped functions in non-strict mode
    // IsBlockVar() indicates a user let declared variable at function scope which
    // shadows the function's var binding, thus only emit the var binding init if
    // we do not have a block var symbol.
    if (!fncScopeSym || fncScopeSym->GetIsBlockVar())
    {
        return nullptr;
    }
    return fncScopeSym;
}
Beispiel #2
0
void Scope::MergeParamAndBodyScopes(ParseNode *pnodeScope, ByteCodeGenerator *byteCodeGenerator)
{
    Assert(pnodeScope->sxFnc.funcInfo);
    Scope *paramScope = pnodeScope->sxFnc.pnodeScopes->sxBlock.scope;
    Scope *bodyScope = pnodeScope->sxFnc.pnodeBodyScope->sxBlock.scope;

    Assert(paramScope->m_symList == nullptr || paramScope->symbolTable == nullptr);
    Assert(bodyScope->m_symList == nullptr || bodyScope->symbolTable == nullptr);

    if (paramScope->Count() == 0)
    {
        // Once the scopes are merged, there's no reason to instantiate the param scope.
        paramScope->SetMustInstantiate(false);

        // Scopes are already merged or we don't have an arguments object. Go ahead and
        // remove the param scope from the scope chain.
        bodyScope->SetEnclosingScope(paramScope->GetEnclosingScope());
        return;
    }

    bodyScope->ForEachSymbol([&](Symbol * sym)
    {
        // Duplicate 'arguments' - param scope arguments wins.
        if (byteCodeGenerator->UseParserBindings()
            && sym->GetDecl()->sxVar.pid == byteCodeGenerator->GetParser()->names()->arguments)
        {
            return;
        }

        Assert(paramScope->m_symList == nullptr || paramScope->FindLocalSymbol(sym->GetName()) == nullptr);
        paramScope->AddNewSymbol(sym);
    });

    // Reassign non-formal slot positions. Formals need to keep their slot positions to ensure
    // the argument object works properly. Other symbols need to be reassigned slot positions.
    paramScope->ForEachSymbol([&](Symbol * sym)
    {
        if (sym->GetSymbolType() != STFormal && sym->GetScopeSlot() != Js::Constants::NoProperty)
        {
            sym->SetScopeSlot(Js::Constants::NoProperty);
            sym->EnsureScopeSlot(pnodeScope->sxFnc.funcInfo);
        }
        sym->SetScope(bodyScope);
    });

    bodyScope->m_count = paramScope->m_count;
    bodyScope->m_symList = paramScope->m_symList;
    bodyScope->scopeSlotCount = paramScope->scopeSlotCount;
    if (bodyScope->symbolTable != nullptr)
    {
        Adelete(byteCodeGenerator->GetAllocator(), bodyScope->symbolTable);
        bodyScope->symbolTable = nullptr;
    }
    bodyScope->symbolTable = paramScope->symbolTable;
    if (paramScope->GetIsObject())
    {
        bodyScope->SetIsObject();
    }
    if (paramScope->GetMustInstantiate())
    {
        bodyScope->SetMustInstantiate(true);
    }

    // Once the scopes are merged, there's no reason to instantiate the param scope.
    paramScope->SetMustInstantiate(false);

    paramScope->m_count = 0;
    paramScope->scopeSlotCount = 0;
    paramScope->m_symList = nullptr;
    paramScope->symbolTable = nullptr;

    // Remove the parameter scope from the scope chain.
    bodyScope->SetEnclosingScope(paramScope->GetEnclosingScope());
}