diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 612b957cf4a..dbe705fbe35 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -246,16 +246,37 @@ module ts { // the getLocalNameOfContainer function in the type checker to validate that the local name // used for a container is unique. function bindChildren(node: Node): void { + // Before we recurse into a node's chilren, we first save the existing parent, container + // and block-container. Then after we pop out of processing the children, we restore + // these saved values. let saveParent = parent; let saveContainer = container; let savedBlockScopeContainer = blockScopeContainer; - parent = node; + // This node will now be set as the parent of all of its children as we recurse into them. + parent = node; + + // 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 need 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 accidently move any stale data forward from + // a previous compilation. let containerFlags = getContainerFlags(node); if (containerFlags & ContainerFlags.IsContainer) { container = blockScopeContainer = node; - // If this is a container that also has locals, initialize them now. if (containerFlags & ContainerFlags.HasLocals) { container.locals = {}; }