| Index: src/runtime.cc | 
| diff --git a/src/runtime.cc b/src/runtime.cc | 
| index 7b7a3e48ab809102e771d19723713eb4b9409da4..627e0d38360c1a5e1f32f6d2b42993cf49832f20 100644 | 
| --- a/src/runtime.cc | 
| +++ b/src/runtime.cc | 
| @@ -11015,10 +11015,10 @@ static Handle<JSObject> MaterializeModuleScope( | 
| } | 
|  | 
|  | 
| -// Iterate over the actual scopes visible from a stack frame. The iteration | 
| -// proceeds from the innermost visible nested scope outwards. All scopes are | 
| -// backed by an actual context except the local scope, which is inserted | 
| -// "artificially" in the context chain. | 
| +// Iterate over the actual scopes visible from a stack frame or from a closure. | 
| +// The iteration proceeds from the innermost visible nested scope outwards. | 
| +// All scopes are backed by an actual context except the local scope, | 
| +// which is inserted "artificially" in the context chain. | 
| class ScopeIterator { | 
| public: | 
| enum ScopeType { | 
| @@ -11119,6 +11119,18 @@ class ScopeIterator { | 
| } | 
| } | 
|  | 
| +  ScopeIterator(Isolate* isolate, | 
| +                Handle<JSFunction> function) | 
| +    : isolate_(isolate), | 
| +      frame_(NULL), | 
| +      inlined_jsframe_index_(0), | 
| +      function_(function), | 
| +      context_(function->context()) { | 
| +    if (function->IsBuiltin()) { | 
| +      context_ = Handle<Context>(); | 
| +    } | 
| +  } | 
| + | 
| // More scopes? | 
| bool Done() { return context_.is_null(); } | 
|  | 
| @@ -11339,6 +11351,22 @@ static const int kScopeDetailsTypeIndex = 0; | 
| static const int kScopeDetailsObjectIndex = 1; | 
| static const int kScopeDetailsSize = 2; | 
|  | 
| + | 
| +static MaybeObject* MaterializeScopeDetails(Isolate* isolate, | 
| +    ScopeIterator* it) { | 
| +  // Calculate the size of the result. | 
| +  int details_size = kScopeDetailsSize; | 
| +  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); | 
| + | 
| +  // Fill in scope details. | 
| +  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type())); | 
| +  Handle<JSObject> scope_object = it->ScopeObject(); | 
| +  RETURN_IF_EMPTY_HANDLE(isolate, scope_object); | 
| +  details->set(kScopeDetailsObjectIndex, *scope_object); | 
| + | 
| +  return *isolate->factory()->NewJSArrayWithElements(details); | 
| +} | 
| + | 
| // Return an array with scope details | 
| // args[0]: number: break id | 
| // args[1]: number: frame index | 
| @@ -11376,18 +11404,46 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) { | 
| if (it.Done()) { | 
| return isolate->heap()->undefined_value(); | 
| } | 
| +  return MaterializeScopeDetails(isolate, &it); | 
| +} | 
|  | 
| -  // Calculate the size of the result. | 
| -  int details_size = kScopeDetailsSize; | 
| -  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); | 
|  | 
| -  // Fill in scope details. | 
| -  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type())); | 
| -  Handle<JSObject> scope_object = it.ScopeObject(); | 
| -  RETURN_IF_EMPTY_HANDLE(isolate, scope_object); | 
| -  details->set(kScopeDetailsObjectIndex, *scope_object); | 
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) { | 
| +  HandleScope scope(isolate); | 
| +  ASSERT(args.length() == 1); | 
|  | 
| -  return *isolate->factory()->NewJSArrayWithElements(details); | 
| +  // Check arguments. | 
| +  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); | 
| + | 
| +  // Count the visible scopes. | 
| +  int n = 0; | 
| +  for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) { | 
| +    n++; | 
| +  } | 
| + | 
| +  return Smi::FromInt(n); | 
| +} | 
| + | 
| + | 
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) { | 
| +  HandleScope scope(isolate); | 
| +  ASSERT(args.length() == 2); | 
| + | 
| +  // Check arguments. | 
| +  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); | 
| +  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | 
| + | 
| +  // Find the requested scope. | 
| +  int n = 0; | 
| +  ScopeIterator it(isolate, fun); | 
| +  for (; !it.Done() && n < index; it.Next()) { | 
| +    n++; | 
| +  } | 
| +  if (it.Done()) { | 
| +    return isolate->heap()->undefined_value(); | 
| +  } | 
| + | 
| +  return MaterializeScopeDetails(isolate, &it); | 
| } | 
|  | 
|  | 
|  |