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