| 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);
|
| }
|
|
|
|
|
|
|