docs/libs/typescript.js
function bindContainer(node, containerFlags) {
            // Before we recurse into a node's children, we first save the existing parent, container
            // and block-container.  Then after we pop out of processing the children, we restore
            // these saved values.
            var saveContainer = container;
            var savedBlockScopeContainer = blockScopeContainer;
            // Depending on what kind of node this is, we may have to adjust the current container
            // and block-container.   If the current node is a container, then it is automatically
            // considered the current block-container as well.  Also, for containers that we know
            // may contain locals, we proactively initialize the .locals field. We do this because
            // it's highly likely that the .locals will be needed to place some child in (for example,
            // a parameter, or variable declaration).
            //
            // However, we do not proactively create the .locals for block-containers because it's
            // totally normal and common for block-containers to never actually have a block-scoped
            // variable in them.  We don't want to end up allocating an object for every 'block' we
            // run into when most of them won't be necessary.
            //
            // Finally, if this is a block-container, then we clear out any existing .locals object
            // it may contain within it.  This happens in incremental scenarios.  Because we can be
            // reusing a node from a previous compilation, that node may have had 'locals' created
            // for it.  We must clear this so we don't accidentally move any stale data forward from
            // a previous compilation.
            if (containerFlags & 1 /* IsContainer */) {
                container = blockScopeContainer = node;
                if (containerFlags & 32 /* HasLocals */) {
                    container.locals = ts.createMap();
                }
                addToContainerChain(container);
            }
            else if (containerFlags & 2 /* IsBlockScopedContainer */) {
                blockScopeContainer = node;
                blockScopeContainer.locals = undefined;
            }
            if (containerFlags & 4 /* IsControlFlowContainer */) {
                var saveCurrentFlow = currentFlow;
                var saveBreakTarget = currentBreakTarget;
                var saveContinueTarget = currentContinueTarget;
                var saveReturnTarget = currentReturnTarget;
                var saveActiveLabels = activeLabels;
                var saveHasExplicitReturn = hasExplicitReturn;
                var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !!ts.getImmediatelyInvokedFunctionExpression(node);
                // An IIFE is considered part of the containing control flow. Return statements behave
                // similarly to break statements that exit to a label just past the statement body.
                if (isIIFE) {
                    currentReturnTarget = createBranchLabel();
                }
                else {
                    currentFlow = { flags: 2 /* Start */ };
                    if (containerFlags & 16 /* IsFunctionExpression */) {
                        currentFlow.container = node;
                    }
                    currentReturnTarget = undefined;
                }
                currentBreakTarget = undefined;
                currentContinueTarget = undefined;
                activeLabels = undefined;
                hasExplicitReturn = false;
                bindChildren(node);
                // Reset all reachability check related flags on node (for incremental scenarios)
                // Reset all emit helper flags on node (for incremental scenarios)
                node.flags &= ~4030464 /* ReachabilityAndEmitFlags */;
                if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) {
                    node.flags |= 32768 /* HasImplicitReturn */;
                    if (hasExplicitReturn)
                        node.flags |= 65536 /* HasExplicitReturn */;
                }
                if (node.kind === 256 /* SourceFile */) {
                    node.flags |= emitFlags;
                }
                if (isIIFE) {
                    addAntecedent(currentReturnTarget, currentFlow);
                    currentFlow = finishFlowLabel(currentReturnTarget);
                }
                else {
                    currentFlow = saveCurrentFlow;
                }
                currentBreakTarget = saveBreakTarget;
                currentContinueTarget = saveContinueTarget;
                currentReturnTarget = saveReturnTarget;
                activeLabels = saveActiveLabels;
                hasExplicitReturn = saveHasExplicitReturn;
            }
            else if (containerFlags & 64 /* IsInterface */) {
                seenThisKeyword = false;
                bindChildren(node);
                node.flags = seenThisKeyword ? node.flags | 16384 /* ContainsThis */ : node.flags & ~16384 /* ContainsThis */;
            }
            else {
                bindChildren(node);
            }
            container = saveContainer;
            blockScopeContainer = savedBlockScopeContainer;
        }
function bindContainer(node, containerFlags) {
            // Before we recurse into a node's children, we first save the existing parent, container
            // and block-container.  Then after we pop out of processing the children, we restore
            // these saved values.
            var saveContainer = container;
            var savedBlockScopeContainer = blockScopeContainer;
            // Depending on what kind of node this is, we may have to adjust the current container
            // and block-container.   If the current node is a container, then it is automatically
            // considered the current block-container as well.  Also, for containers that we know
            // may contain locals, we proactively initialize the .locals field. We do this because
            // it's highly likely that the .locals will be needed to place some child in (for example,
            // a parameter, or variable declaration).
            //
            // However, we do not proactively create the .locals for block-containers because it's
            // totally normal and common for block-containers to never actually have a block-scoped
            // variable in them.  We don't want to end up allocating an object for every 'block' we
            // run into when most of them won't be necessary.
            //
            // Finally, if this is a block-container, then we clear out any existing .locals object
            // it may contain within it.  This happens in incremental scenarios.  Because we can be
            // reusing a node from a previous compilation, that node may have had 'locals' created
            // for it.  We must clear this so we don't accidentally move any stale data forward from
            // a previous compilation.
            if (containerFlags & 1 /* IsContainer */) {
                container = blockScopeContainer = node;
                if (containerFlags & 32 /* HasLocals */) {
                    container.locals = ts.createMap();
                }
                addToContainerChain(container);
            }
            else if (containerFlags & 2 /* IsBlockScopedContainer */) {
                blockScopeContainer = node;
                blockScopeContainer.locals = undefined;
            }
            if (containerFlags & 4 /* IsControlFlowContainer */) {
                var saveCurrentFlow = currentFlow;
                var saveBreakTarget = currentBreakTarget;
                var saveContinueTarget = currentContinueTarget;
                var saveReturnTarget = currentReturnTarget;
                var saveActiveLabels = activeLabels;
                var saveHasExplicitReturn = hasExplicitReturn;
                var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !!ts.getImmediatelyInvokedFunctionExpression(node);
                // An IIFE is considered part of the containing control flow. Return statements behave
                // similarly to break statements that exit to a label just past the statement body.
                if (isIIFE) {
                    currentReturnTarget = createBranchLabel();
                }
                else {
                    currentFlow = { flags: 2 /* Start */ };
                    if (containerFlags & 16 /* IsFunctionExpression */) {
                        currentFlow.container = node;
                    }
                    currentReturnTarget = undefined;
                }
                currentBreakTarget = undefined;
                currentContinueTarget = undefined;
                activeLabels = undefined;
                hasExplicitReturn = false;
                bindChildren(node);
                // Reset all reachability check related flags on node (for incremental scenarios)
                // Reset all emit helper flags on node (for incremental scenarios)
                node.flags &= ~4030464 /* ReachabilityAndEmitFlags */;
                if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) {
                    node.flags |= 32768 /* HasImplicitReturn */;
                    if (hasExplicitReturn)
                        node.flags |= 65536 /* HasExplicitReturn */;
                }
                if (node.kind === 256 /* SourceFile */) {
                    node.flags |= emitFlags;
                }
                if (isIIFE) {
                    addAntecedent(currentReturnTarget, currentFlow);
                    currentFlow = finishFlowLabel(currentReturnTarget);
                }
                else {
                    currentFlow = saveCurrentFlow;
                }
                currentBreakTarget = saveBreakTarget;
                currentContinueTarget = saveContinueTarget;
                currentReturnTarget = saveReturnTarget;
                activeLabels = saveActiveLabels;
                hasExplicitReturn = saveHasExplicitReturn;
            }
            else if (containerFlags & 64 /* IsInterface */) {
                seenThisKeyword = false;
                bindChildren(node);
                node.flags = seenThisKeyword ? node.flags | 16384 /* ContainsThis */ : node.flags & ~16384 /* ContainsThis */;
            }
            else {
                bindChildren(node);
            }
            container = saveContainer;
            blockScopeContainer = savedBlockScopeContainer;
        }
function bindContainer ( node , containerFlags ) { // Before we recurse into a node's children, we first save the existing parent, container // and block-container.  Then after we pop out of processing the children, we restore // these saved values. var saveContainer = container ; var savedBlockScopeContainer = blockScopeContainer ; // Depending on what kind of node this is, we may have to adjust the current container // and block-container.   If the current node is a container, then it is automatically // considered the current block-container as well.  Also, for containers that we know // may contain locals, we proactively initialize the .locals field. We do this because // it's highly likely that the .locals will be needed to place some child in (for example, // a parameter, or variable declaration). // // However, we do not proactively create the .locals for block-containers because it's // totally normal and common for block-containers to never actually have a block-scoped // variable in them.  We don't want to end up allocating an object for every 'block' we // run into when most of them won't be necessary. // // Finally, if this is a block-container, then we clear out any existing .locals object // it may contain within it.  This happens in incremental scenarios.  Because we can be // reusing a node from a previous compilation, that node may have had 'locals' created // for it.  We must clear this so we don't accidentally move any stale data forward from // a previous compilation. if ( containerFlags & 1 /* IsContainer */ ) { container = blockScopeContainer = node ; if ( containerFlags & 32 /* HasLocals */ ) { container . locals = ts . createMap ( ) ; } addToContainerChain ( container ) ; } else if ( containerFlags & 2 /* IsBlockScopedContainer */ ) { blockScopeContainer = node ; blockScopeContainer . locals = undefined ; } if ( containerFlags & 4 /* IsControlFlowContainer */ ) { var saveCurrentFlow = currentFlow ; var saveBreakTarget = currentBreakTarget ; var saveContinueTarget = currentContinueTarget ; var saveReturnTarget = currentReturnTarget ; var saveActiveLabels = activeLabels ; var saveHasExplicitReturn = hasExplicitReturn ; var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && ! ! ts . getImmediatelyInvokedFunctionExpression ( node ) ; // An IIFE is considered part of the containing control flow. Return statements behave // similarly to break statements that exit to a label just past the statement body. if ( isIIFE ) { currentReturnTarget = createBranchLabel ( ) ; } else { currentFlow = { flags : 2 /* Start */ } ; if ( containerFlags & 16 /* IsFunctionExpression */ ) { currentFlow . container = node ; } currentReturnTarget = undefined ; } currentBreakTarget = undefined ; currentContinueTarget = undefined ; activeLabels = undefined ; hasExplicitReturn = false ; bindChildren ( node ) ; // Reset all reachability check related flags on node (for incremental scenarios) // Reset all emit helper flags on node (for incremental scenarios) node . flags &= ~ 4030464 /* ReachabilityAndEmitFlags */ ; if ( ! ( currentFlow . flags & 1 /* Unreachable */ ) && containerFlags & 8 /* IsFunctionLike */ && ts . nodeIsPresent ( node . body ) ) { node . flags |= 32768 /* HasImplicitReturn */ ; if ( hasExplicitReturn ) node . flags |= 65536 /* HasExplicitReturn */ ; } if ( node . kind === 256 /* SourceFile */ ) { node . flags |= emitFlags ; } if ( isIIFE ) { addAntecedent ( currentReturnTarget , currentFlow ) ; currentFlow = finishFlowLabel ( currentReturnTarget ) ; } else { currentFlow = saveCurrentFlow ; } currentBreakTarget = saveBreakTarget ; currentContinueTarget = saveContinueTarget ; currentReturnTarget = saveReturnTarget ; activeLabels = saveActiveLabels ; hasExplicitReturn = saveHasExplicitReturn ; } else if ( containerFlags & 64 /* IsInterface */ ) { seenThisKeyword = false ; bindChildren ( node ) ; node . flags = seenThisKeyword ? node . flags | 16384 /* ContainsThis */ : node . flags & ~ 16384 /* ContainsThis */ ; } else { bindChildren ( node ) ; } container = saveContainer ; blockScopeContainer = savedBlockScopeContainer ; }
All container nodes are kept on a linked list in declaration order. This list is used by the getLocalNameOfContainer function in the type checker to validate that the local name used for a container is unique.
All container nodes are kept on a linked list in declaration order . This list is used by the getLocalNameOfContainer function in the type checker to validate that the local name used for a container is unique .