Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 3528) |
+++ src/runtime.cc (working copy) |
@@ -5233,51 +5233,31 @@ |
} |
-static Handle<JSFunction> GetBuiltinFunction(String* name) { |
- LookupResult result; |
- Top::global_context()->builtins()->LocalLookup(name, &result); |
- return Handle<JSFunction>(JSFunction::cast(result.GetValue())); |
-} |
+static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) { |
+ ASSERT(args.length() == 3); |
+ if (!args[0]->IsJSFunction()) { |
+ return MakePair(Top::ThrowIllegalOperation(), NULL); |
+ } |
- |
-static Object* CompileDirectEval(Handle<String> source) { |
- // Compute the eval context. |
HandleScope scope; |
+ Handle<JSFunction> callee = args.at<JSFunction>(0); |
+ Handle<Object> receiver; // Will be overwritten. |
+ |
+ // Compute the calling context. |
+ Handle<Context> context = Handle<Context>(Top::context()); |
+#ifdef DEBUG |
+ // Make sure Top::context() agrees with the old code that traversed |
+ // the stack frames to compute the context. |
StackFrameLocator locator; |
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
- Handle<Context> context(Context::cast(frame->context())); |
- bool is_global = context->IsGlobalContext(); |
+ ASSERT(Context::cast(frame->context()) == *context); |
+#endif |
- // Compile source string in the current context. |
- Handle<JSFunction> boilerplate = Compiler::CompileEval( |
- source, |
- context, |
- is_global, |
- Compiler::DONT_VALIDATE_JSON); |
- if (boilerplate.is_null()) return Failure::Exception(); |
- Handle<JSFunction> fun = |
- Factory::NewFunctionFromBoilerplate(boilerplate, context, NOT_TENURED); |
- 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()) { |
+ int index = -1; |
+ PropertyAttributes attributes = ABSENT; |
+ while (true) { |
receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN, |
&index, &attributes); |
// Stop search when eval is found or when the global context is |
@@ -5296,46 +5276,42 @@ |
Handle<Object> name = Factory::eval_symbol(); |
Handle<Object> reference_error = |
Factory::NewReferenceError("not_defined", HandleVector(&name, 1)); |
- return Top::Throw(*reference_error); |
+ return MakePair(Top::Throw(*reference_error), NULL); |
} |
- 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 { |
+ if (!context->IsGlobalContext()) { |
// '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)); |
+ } else if (receiver->IsJSContextExtensionObject()) { |
+ receiver = Handle<JSObject>(Top::context()->global()->global_receiver()); |
} |
+ return MakePair(*callee, *receiver); |
} |
- Handle<FixedArray> call = Factory::NewFixedArray(2); |
- call->set(0, *callee); |
- call->set(1, *receiver); |
- return *call; |
+ // 'eval' is bound in the global context, but it may have been overwritten. |
+ // Compare it to the builtin 'GlobalEval' function to make sure. |
+ if (*callee != Top::global_context()->global_eval_fun() || |
+ !args[1]->IsString()) { |
+ return MakePair(*callee, Top::context()->global()->global_receiver()); |
+ } |
+ |
+ // Deal with a normal eval call with a string argument. Compile it |
+ // and return the compiled function bound in the local context. |
+ Handle<String> source = args.at<String>(1); |
+ Handle<JSFunction> boilerplate = Compiler::CompileEval( |
+ source, |
+ Handle<Context>(Top::context()), |
+ Top::context()->IsGlobalContext(), |
+ Compiler::DONT_VALIDATE_JSON); |
+ if (boilerplate.is_null()) return MakePair(Failure::Exception(), NULL); |
+ callee = Factory::NewFunctionFromBoilerplate( |
+ boilerplate, |
+ Handle<Context>(Top::context()), |
+ NOT_TENURED); |
+ return MakePair(*callee, args[2]); |
} |