| Index: tools/gn/template.cc
 | 
| diff --git a/tools/gn/template.cc b/tools/gn/template.cc
 | 
| index cae5e0c2d092c4439fa1028624d79fc286e2dd5c..fa0ccf31c64c4e3a43b5a4a8b1e24d51e87deea6 100644
 | 
| --- a/tools/gn/template.cc
 | 
| +++ b/tools/gn/template.cc
 | 
| @@ -39,22 +39,33 @@ Value Template::Invoke(Scope* scope,
 | 
|    if (!EnsureNotProcessingImport(invocation, scope, err))
 | 
|      return Value();
 | 
|  
 | 
| -  // First run the invocation's block.
 | 
| -  Scope invocation_scope(scope);
 | 
| +  // First run the invocation's block. Need to allocate the scope on the heap
 | 
| +  // so we can pass ownership to the template.
 | 
| +  scoped_ptr<Scope> invocation_scope(new Scope(scope));
 | 
|    if (!FillTargetBlockScope(scope, invocation,
 | 
|                              invocation->function().value().as_string(),
 | 
| -                            block, args, &invocation_scope, err))
 | 
| +                            block, args, invocation_scope.get(), err))
 | 
|      return Value();
 | 
| -  block->ExecuteBlockInScope(&invocation_scope, err);
 | 
| +  block->ExecuteBlockInScope(invocation_scope.get(), err);
 | 
|    if (err->has_error())
 | 
|      return Value();
 | 
|  
 | 
|    // Set up the scope to run the template. This should be dependent on the
 | 
|    // closure, but have the "invoker" and "target_name" values injected, and the
 | 
| -  // current dir matching the invoker.
 | 
| +  // current dir matching the invoker. We jump through some hoops to avoid
 | 
| +  // copying the invocation scope when setting it in the template scope (since
 | 
| +  // the invocation scope may have large lists of source files in it and could
 | 
| +  // be expensive to copy).
 | 
| +  //
 | 
| +  // Scope.SetValue will copy the value which will in turn copy the scope, but
 | 
| +  // if we instead create a value and then set the scope on it, the copy can
 | 
| +  // be avoided.
 | 
|    Scope template_scope(closure_.get());
 | 
| -  template_scope.SetValue("invoker", Value(NULL, &invocation_scope),
 | 
| +  const char kInvoker[] = "invoker";
 | 
| +  template_scope.SetValue(kInvoker, Value(NULL, scoped_ptr<Scope>()),
 | 
|                            invocation);
 | 
| +  Value* invoker_value = template_scope.GetMutableValue(kInvoker, false);
 | 
| +  invoker_value->SetScopeValue(invocation_scope.Pass());
 | 
|    template_scope.set_source_dir(scope->GetSourceDir());
 | 
|  
 | 
|    const base::StringPiece target_name("target_name");
 | 
| @@ -65,7 +76,28 @@ Value Template::Invoke(Scope* scope,
 | 
|    // Run the template code. Don't check for unused variables since the
 | 
|    // template could be executed in many different ways and it could be that
 | 
|    // not all executions use all values in the closure.
 | 
| -  return definition_->block()->ExecuteBlockInScope(&template_scope, err);
 | 
| +  Value result =
 | 
| +      definition_->block()->ExecuteBlockInScope(&template_scope, err);
 | 
| +
 | 
| +  // Check for unused variables in the invocation scope. This will find typos
 | 
| +  // of things the caller meant to pass to the template but the template didn't
 | 
| +  // read out.
 | 
| +  //
 | 
| +  // This is a bit tricky because it's theoretically possible for the template
 | 
| +  // to overwrite the value of "invoker" and free the Scope owned by the
 | 
| +  // value. So we need to look it up again and don't do anything if it doesn't
 | 
| +  // exist.
 | 
| +  invoker_value = template_scope.GetMutableValue(kInvoker, false);
 | 
| +  if (invoker_value && invoker_value->type() == Value::SCOPE) {
 | 
| +    if (!invoker_value->scope_value()->CheckForUnusedVars(err))
 | 
| +      return Value();
 | 
| +  }
 | 
| +
 | 
| +  // Check for unused variables in the template itself.
 | 
| +  if (!template_scope.CheckForUnusedVars(err))
 | 
| +    return Value();
 | 
| +
 | 
| +  return result;
 | 
|  }
 | 
|  
 | 
|  LocationRange Template::GetDefinitionRange() const {
 | 
| 
 |