| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 854)
|
| +++ src/runtime.cc (working copy)
|
| @@ -3934,57 +3934,6 @@
|
| }
|
|
|
|
|
| -static Object* EvalContext() {
|
| - // The topmost JS frame belongs to the eval function which called
|
| - // the CompileString runtime function. We need to unwind one level
|
| - // to get to the caller of eval.
|
| - StackFrameLocator locator;
|
| - JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
|
| -
|
| - // TODO(900055): Right now we check if the caller of eval() supports
|
| - // eval to determine if it's an aliased eval or not. This may not be
|
| - // entirely correct in the unlikely case where a function uses both
|
| - // aliased and direct eval calls.
|
| - HandleScope scope;
|
| - if (!ScopeInfo<>::SupportsEval(frame->FindCode())) {
|
| - // Aliased eval: Evaluate in the global context of the eval
|
| - // function to support aliased, cross environment evals.
|
| - return *Top::global_context();
|
| - }
|
| -
|
| - // Fetch the caller context from the frame.
|
| - Handle<Context> caller(Context::cast(frame->context()));
|
| -
|
| - // Check for eval() invocations that cross environments. Use the
|
| - // context from the stack if evaluating in current environment.
|
| - Handle<Context> target = Top::global_context();
|
| - if (caller->global_context() == *target) return *caller;
|
| -
|
| - // Otherwise, use the global context from the other environment.
|
| - return *target;
|
| -}
|
| -
|
| -
|
| -static Object* Runtime_EvalReceiver(Arguments args) {
|
| - ASSERT(args.length() == 1);
|
| - StackFrameLocator locator;
|
| - JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
|
| - // Fetch the caller context from the frame.
|
| - Context* caller = Context::cast(frame->context());
|
| -
|
| - // Check for eval() invocations that cross environments. Use the
|
| - // top frames receiver if evaluating in current environment.
|
| - Context* global_context = Top::context()->global()->global_context();
|
| - if (caller->global_context() == global_context) {
|
| - return frame->receiver();
|
| - }
|
| -
|
| - // Otherwise use the given argument (the global object of the
|
| - // receiving context).
|
| - return args[0];
|
| -}
|
| -
|
| -
|
| static Object* Runtime_GlobalReceiver(Arguments args) {
|
| ASSERT(args.length() == 1);
|
| Object* global = args[0];
|
| @@ -3995,37 +3944,112 @@
|
|
|
| static Object* Runtime_CompileString(Arguments args) {
|
| HandleScope scope;
|
| - ASSERT(args.length() == 3);
|
| + ASSERT(args.length() == 2);
|
| CONVERT_ARG_CHECKED(String, source, 0);
|
| CONVERT_ARG_CHECKED(Smi, line_offset, 1);
|
| - bool contextual = args[2]->IsTrue();
|
| - RUNTIME_ASSERT(contextual || args[2]->IsFalse());
|
|
|
| - // Compute the eval context.
|
| - Handle<Context> context;
|
| - if (contextual) {
|
| - // Get eval context. May not be available if we are calling eval
|
| - // through an alias, and the corresponding frame doesn't have a
|
| - // proper eval context set up.
|
| - Object* eval_context = EvalContext();
|
| - if (eval_context->IsFailure()) return eval_context;
|
| - context = Handle<Context>(Context::cast(eval_context));
|
| - } else {
|
| - context = Handle<Context>(Top::context()->global_context());
|
| - }
|
| -
|
| -
|
| // Compile source string.
|
| - bool is_global = context->IsGlobalContext();
|
| Handle<JSFunction> boilerplate =
|
| - Compiler::CompileEval(source, line_offset->value(), is_global);
|
| + Compiler::CompileEval(source, line_offset->value(), true);
|
| if (boilerplate.is_null()) return Failure::Exception();
|
| + Handle<Context> context(Top::context()->global_context());
|
| Handle<JSFunction> fun =
|
| Factory::NewFunctionFromBoilerplate(boilerplate, context);
|
| return *fun;
|
| }
|
|
|
|
|
| +static Handle<JSFunction> GetBuiltinFunction(String* name) {
|
| + LookupResult result;
|
| + Top::global_context()->builtins()->LocalLookup(name, &result);
|
| + return Handle<JSFunction>(JSFunction::cast(result.GetValue()));
|
| +}
|
| +
|
| +
|
| +static Object* CompileDirectEval(Handle<String> source) {
|
| + // Compute the eval context.
|
| + HandleScope scope;
|
| + StackFrameLocator locator;
|
| + JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
|
| + Handle<Context> context(Context::cast(frame->context()));
|
| + bool is_global = context->IsGlobalContext();
|
| +
|
| + // Compile source string.
|
| + Handle<JSFunction> boilerplate = Compiler::CompileEval(source, 0, is_global);
|
| + if (boilerplate.is_null()) return Failure::Exception();
|
| + Handle<JSFunction> fun =
|
| + Factory::NewFunctionFromBoilerplate(boilerplate, context);
|
| + return *fun;
|
| +}
|
| +
|
| +
|
| +static Object* Runtime_ResolvePossiblyDirectEval(Arguments args) {
|
| + ASSERT(args.length() == 2);
|
| +
|
| + HandleScope scope;
|
| +
|
| + CONVERT_ARG_CHECKED(JSFunction, callee, 0);
|
| +
|
| + Handle<Object> receiver;
|
| +
|
| + // Find where the 'eval' symbol is bound. It is unaliased only if
|
| + // it is bound in the global context.
|
| + StackFrameLocator locator;
|
| + JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
|
| + Handle<Context> context(Context::cast(frame->context()));
|
| + int index;
|
| + PropertyAttributes attributes;
|
| + while (!context.is_null()) {
|
| + receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN,
|
| + &index, &attributes);
|
| + if (attributes != ABSENT) break;
|
| + if (context->is_function_context()) {
|
| + context = Handle<Context>(Context::cast(context->closure()->context()));
|
| + } else {
|
| + context = Handle<Context>(context->previous());
|
| + }
|
| + }
|
| +
|
| + if (context->IsGlobalContext()) {
|
| + // 'eval' is bound in the global context, but it may have been overwritten.
|
| + // Compare it to the builtin 'GlobalEval' function to make sure.
|
| + Handle<JSFunction> global_eval =
|
| + GetBuiltinFunction(Heap::global_eval_symbol());
|
| + if (global_eval.is_identical_to(callee)) {
|
| + // A direct eval call.
|
| + if (args[1]->IsString()) {
|
| + CONVERT_ARG_CHECKED(String, source, 1);
|
| + // A normal eval call on a string. Compile it and return the
|
| + // compiled function bound in the local context.
|
| + Object* compiled_source = CompileDirectEval(source);
|
| + if (compiled_source->IsFailure()) return compiled_source;
|
| + receiver = Handle<Object>(frame->receiver());
|
| + callee = Handle<JSFunction>(JSFunction::cast(compiled_source));
|
| + } else {
|
| + // An eval call that is not called on a string. Global eval
|
| + // deals better with this.
|
| + receiver = Handle<Object>(Top::global_context()->global());
|
| + }
|
| + } else {
|
| + // 'eval' is overwritten. Just call the function with the given arguments.
|
| + receiver = Handle<Object>(Top::global_context()->global());
|
| + }
|
| + } else {
|
| + // 'eval' is not bound in the global context. Just call the function
|
| + // with the given arguments. This is not necessarily the global eval.
|
| + if (receiver->IsContext()) {
|
| + context = Handle<Context>::cast(receiver);
|
| + receiver = Handle<Object>(context->get(index));
|
| + }
|
| + }
|
| +
|
| + Handle<FixedArray> call = Factory::NewFixedArray(2);
|
| + call->set(0, *callee);
|
| + call->set(1, *receiver);
|
| + return *call;
|
| +}
|
| +
|
| +
|
| static Object* Runtime_CompileScript(Arguments args) {
|
| HandleScope scope;
|
| ASSERT(args.length() == 4);
|
|
|