Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 934c82eb10566973cd6fead748b1144f10b20989..0b5d2095aac4713d4d1828519f2bfc6159e0d729 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -9015,7 +9015,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, |
// and return the compiled function bound in the local context. |
Handle<SharedFunctionInfo> shared = Compiler::CompileEval( |
source, |
- Handle<Context>(isolate->context()), |
+ context, |
context->IsNativeContext(), |
language_mode, |
NO_PARSE_RESTRICTION, |
@@ -11919,21 +11919,58 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate, |
} |
-static const char kSourceStr[] = |
- "(function(arguments,__source__){return eval(__source__);})"; |
+// Compile and evaluate source for the given context. |
+static MaybeObject* DebugEvaluate(Isolate* isolate, |
+ Handle<Context> context, |
+ Handle<Object> context_extension, |
+ Handle<Object> receiver, |
+ Handle<String> source) { |
+ if (context_extension->IsJSObject()) { |
+ Handle<JSObject> extension = Handle<JSObject>::cast(context_extension); |
+ Handle<JSFunction> closure(context->closure(), isolate); |
+ context = isolate->factory()->NewWithContext(closure, context, extension); |
+ } |
+ |
+ Handle<SharedFunctionInfo> shared = Compiler::CompileEval( |
+ source, |
+ context, |
+ context->IsNativeContext(), |
+ CLASSIC_MODE, |
+ NO_PARSE_RESTRICTION, |
+ RelocInfo::kNoPosition); |
+ if (shared.is_null()) return Failure::Exception(); |
+ |
+ Handle<JSFunction> eval_fun = |
+ isolate->factory()->NewFunctionFromSharedFunctionInfo( |
+ shared, context, NOT_TENURED); |
+ bool pending_exception; |
+ Handle<Object> result = Execution::Call( |
+ eval_fun, receiver, 0, NULL, &pending_exception); |
+ |
+ if (pending_exception) return Failure::Exception(); |
+ |
+ // Skip the global proxy as it has no properties and always delegates to the |
+ // real global object. |
+ if (result->IsJSGlobalProxy()) { |
+ result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate))); |
+ } |
+ |
+ // Clear the oneshot breakpoints so that the debugger does not step further. |
+ isolate->debug()->ClearStepping(); |
+ return *result; |
+} |
// Evaluate a piece of JavaScript in the context of a stack frame for |
-// debugging. This is accomplished by creating a new context which in its |
-// extension part has all the parameters and locals of the function on the |
-// stack frame. A function which calls eval with the code to evaluate is then |
-// compiled in this context and called in this context. As this context |
-// replaces the context of the function on the stack frame a new (empty) |
-// function is created as well to be used as the closure for the context. |
-// This function and the context acts as replacements for the function on the |
-// stack frame presenting the same view of the values of parameters and |
-// local variables as if the piece of JavaScript was evaluated at the point |
-// where the function on the stack frame is currently stopped. |
+// debugging. This is done by creating a new context which in its extension |
+// part has all the parameters and locals of the function on the stack frame |
+// as well as a materialized arguments object. As this context replaces |
+// the context of the function on the stack frame a new (empty) function |
+// is created as well to be used as the closure for the context. |
+// This closure as replacements for the one on the stack frame presenting |
+// the same view of the values of parameters and local variables as if the |
+// piece of JavaScript was evaluated at the point where the function on the |
+// stack frame is currently stopped when we compile and run the (direct) eval. |
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { |
HandleScope scope(isolate); |
@@ -11941,17 +11978,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { |
// evaluated. |
ASSERT(args.length() == 6); |
Object* check_result; |
- { MaybeObject* maybe_check_result = Runtime_CheckExecutionState( |
+ { MaybeObject* maybe_result = Runtime_CheckExecutionState( |
RUNTIME_ARGUMENTS(isolate, args)); |
- if (!maybe_check_result->ToObject(&check_result)) { |
- return maybe_check_result; |
- } |
+ if (!maybe_result->ToObject(&check_result)) return maybe_result; |
} |
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); |
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); |
CONVERT_ARG_HANDLE_CHECKED(String, source, 3); |
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4); |
- Handle<Object> additional_context(args[5], isolate); |
+ Handle<Object> context_extension(args[5], isolate); |
// Handle the processing of break. |
DisableBreak disable_break_save(disable_break); |
@@ -11962,7 +11997,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { |
JavaScriptFrame* frame = it.frame(); |
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); |
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); |
- Handle<ScopeInfo> scope_info(function->shared()->scope_info()); |
// Traverse the saved contexts chain to find the active context for the |
// selected frame. |
@@ -11987,28 +12021,39 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { |
ASSERT(go_between_scope_info->ContextLocalCount() == 0); |
#endif |
- // Materialize the content of the local scope into a JSObject. |
+ // Materialize the content of the local scope including the arguments object. |
Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector( |
isolate, frame, &frame_inspector); |
RETURN_IF_EMPTY_HANDLE(isolate, local_scope); |
+ Handle<Context> frame_context(Context::cast(frame->context())); |
+ Handle<Context> function_context; |
+ Handle<ScopeInfo> scope_info(function->shared()->scope_info()); |
+ if (scope_info->HasContext()) { |
+ function_context = Handle<Context>(frame_context->declaration_context()); |
+ } |
+ Handle<Object> arguments = GetArgumentsObject(isolate, |
+ frame, |
+ &frame_inspector, |
+ scope_info, |
+ function_context); |
+ SetProperty(isolate, |
+ local_scope, |
+ isolate->factory()->arguments_string(), |
+ arguments, |
+ ::NONE, |
+ kNonStrictMode); |
+ |
// Allocate a new context for the debug evaluation and set the extension |
// object build. |
- Handle<Context> context = |
- isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, |
- go_between); |
+ Handle<Context> context = isolate->factory()->NewFunctionContext( |
+ Context::MIN_CONTEXT_SLOTS, go_between); |
// Use the materialized local scope in a with context. |
context = |
isolate->factory()->NewWithContext(go_between, context, local_scope); |
// Copy any with contexts present and chain them in front of this context. |
- Handle<Context> frame_context(Context::cast(frame->context())); |
- Handle<Context> function_context; |
- // Get the function's context if it has one. |
- if (scope_info->HasContext()) { |
- function_context = Handle<Context>(frame_context->declaration_context()); |
- } |
context = CopyNestedScopeContextChain(isolate, |
go_between, |
context, |
@@ -12021,79 +12066,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { |
return exception; |
} |
- if (additional_context->IsJSObject()) { |
- Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); |
- context = |
- isolate->factory()->NewWithContext(go_between, context, extension); |
- } |
- |
- // Wrap the evaluation statement in a new function compiled in the newly |
- // created context. The function has one parameter which has to be called |
- // 'arguments'. This it to have access to what would have been 'arguments' in |
- // the function being debugged. |
- // function(arguments,__source__) {return eval(__source__);} |
- |
- Handle<String> function_source = |
- isolate->factory()->NewStringFromAscii( |
- Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1)); |
- |
- // Currently, the eval code will be executed in non-strict mode, |
- // even in the strict code context. |
- Handle<SharedFunctionInfo> shared = |
- Compiler::CompileEval(function_source, |
- context, |
- context->IsNativeContext(), |
- CLASSIC_MODE, |
- NO_PARSE_RESTRICTION, |
- RelocInfo::kNoPosition); |
- if (shared.is_null()) return Failure::Exception(); |
- Handle<JSFunction> compiled_function = |
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context); |
- |
- // Invoke the result of the compilation to get the evaluation function. |
- bool has_pending_exception; |
Handle<Object> receiver(frame->receiver(), isolate); |
- Handle<Object> evaluation_function = |
- Execution::Call(compiled_function, receiver, 0, NULL, |
- &has_pending_exception); |
- if (has_pending_exception) return Failure::Exception(); |
- |
- Handle<Object> arguments = GetArgumentsObject(isolate, |
- frame, |
- &frame_inspector, |
- scope_info, |
- function_context); |
- |
- // Check if eval is blocked in the context and temporarily allow it |
- // for debugger. |
- Handle<Context> native_context = Handle<Context>(context->native_context()); |
- bool eval_disabled = |
- native_context->allow_code_gen_from_strings()->IsFalse(); |
- if (eval_disabled) { |
- native_context->set_allow_code_gen_from_strings( |
- isolate->heap()->true_value()); |
- } |
- // Invoke the evaluation function and return the result. |
- Handle<Object> argv[] = { arguments, source }; |
- Handle<Object> result = |
- Execution::Call(Handle<JSFunction>::cast(evaluation_function), |
- receiver, |
- ARRAY_SIZE(argv), |
- argv, |
- &has_pending_exception); |
- if (eval_disabled) { |
- native_context->set_allow_code_gen_from_strings( |
- isolate->heap()->false_value()); |
- } |
- if (has_pending_exception) return Failure::Exception(); |
- |
- // Skip the global proxy as it has no properties and always delegates to the |
- // real global object. |
- if (result->IsJSGlobalProxy()) { |
- result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate))); |
- } |
- |
- return *result; |
+ return DebugEvaluate(isolate, context, context_extension, receiver, source); |
} |
@@ -12104,15 +12078,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) { |
// evaluated. |
ASSERT(args.length() == 4); |
Object* check_result; |
- { MaybeObject* maybe_check_result = Runtime_CheckExecutionState( |
+ { MaybeObject* maybe_result = Runtime_CheckExecutionState( |
RUNTIME_ARGUMENTS(isolate, args)); |
- if (!maybe_check_result->ToObject(&check_result)) { |
- return maybe_check_result; |
- } |
+ if (!maybe_result->ToObject(&check_result)) return maybe_result; |
} |
CONVERT_ARG_HANDLE_CHECKED(String, source, 1); |
CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2); |
- Handle<Object> additional_context(args[3], isolate); |
+ Handle<Object> context_extension(args[3], isolate); |
// Handle the processing of break. |
DisableBreak disable_break_save(disable_break); |
@@ -12130,45 +12102,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) { |
// Get the native context now set to the top context from before the |
// debugger was invoked. |
Handle<Context> context = isolate->native_context(); |
- |
- bool is_global = true; |
- |
- if (additional_context->IsJSObject()) { |
- // Create a new with context with the additional context information between |
- // the context of the debugged function and the eval code to be executed. |
- context = isolate->factory()->NewWithContext( |
- Handle<JSFunction>(context->closure()), |
- context, |
- Handle<JSObject>::cast(additional_context)); |
- is_global = false; |
- } |
- |
- // Compile the source to be evaluated. |
- // Currently, the eval code will be executed in non-strict mode, |
- // even in the strict code context. |
- Handle<SharedFunctionInfo> shared = |
- Compiler::CompileEval(source, |
- context, |
- is_global, |
- CLASSIC_MODE, |
- NO_PARSE_RESTRICTION, |
- RelocInfo::kNoPosition); |
- if (shared.is_null()) return Failure::Exception(); |
- Handle<JSFunction> compiled_function = |
- Handle<JSFunction>( |
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
- context)); |
- |
- // Invoke the result of the compilation to get the evaluation function. |
- bool has_pending_exception; |
Handle<Object> receiver = isolate->global_object(); |
- Handle<Object> result = |
- Execution::Call(compiled_function, receiver, 0, NULL, |
- &has_pending_exception); |
- // Clear the oneshot breakpoints so that the debugger does not step further. |
- isolate->debug()->ClearStepping(); |
- if (has_pending_exception) return Failure::Exception(); |
- return *result; |
+ return DebugEvaluate(isolate, context, context_extension, receiver, source); |
} |