| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 446443148dcf219323317ec5ab40aefd29598706..bc8de56560f8c39c950471dbfa6b9e1bf99da3e3 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -10798,6 +10798,92 @@ static Handle<JSObject> MaterializeLocalScope(
|
| }
|
|
|
|
|
| +// Set the context local variable value.
|
| +static bool SetContextLocalValue(Isolate* isolate,
|
| + Handle<ScopeInfo> scope_info,
|
| + Handle<Context> context,
|
| + Handle<String> variable_name,
|
| + Handle<Object> new_value) {
|
| + for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
|
| + Handle<String> next_name(scope_info->ContextLocalName(i));
|
| + if (variable_name->Equals(*next_name)) {
|
| + VariableMode mode;
|
| + InitializationFlag init_flag;
|
| + int context_index =
|
| + scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
|
| + context->set(context_index, *new_value);
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +
|
| +static bool SetLocalVariableValue(Isolate* isolate,
|
| + JavaScriptFrame* frame,
|
| + int inlined_jsframe_index,
|
| + Handle<String> variable_name,
|
| + Handle<Object> new_value) {
|
| + if (inlined_jsframe_index != 0 || frame->is_optimized()) {
|
| + // Optimized frames are not supported.
|
| + return false;
|
| + }
|
| +
|
| + Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
| + Handle<SharedFunctionInfo> shared(function->shared());
|
| + Handle<ScopeInfo> scope_info(shared->scope_info());
|
| +
|
| + // Parameters.
|
| + for (int i = 0; i < scope_info->ParameterCount(); ++i) {
|
| + if (scope_info->ParameterName(i)->Equals(*variable_name)) {
|
| + frame->SetParameterValue(i, *new_value);
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + // Stack locals.
|
| + for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
|
| + if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
|
| + frame->SetExpression(i, *new_value);
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + if (scope_info->HasContext()) {
|
| + // Context locals.
|
| + Handle<Context> frame_context(Context::cast(frame->context()));
|
| + Handle<Context> function_context(frame_context->declaration_context());
|
| + if (SetContextLocalValue(
|
| + isolate, scope_info, function_context, variable_name, new_value)) {
|
| + return true;
|
| + }
|
| +
|
| + // Function context extension. These are variables introduced by eval.
|
| + if (function_context->closure() == *function) {
|
| + if (function_context->has_extension() &&
|
| + !function_context->IsNativeContext()) {
|
| + Handle<JSObject> ext(JSObject::cast(function_context->extension()));
|
| +
|
| + if (ext->HasProperty(*variable_name)) {
|
| + // We don't expect this to do anything except replacing
|
| + // property value.
|
| + SetProperty(isolate,
|
| + ext,
|
| + variable_name,
|
| + new_value,
|
| + NONE,
|
| + kNonStrictMode);
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +
|
| // Create a plain JSObject which materializes the closure content for the
|
| // context.
|
| static Handle<JSObject> MaterializeClosure(Isolate* isolate,
|
| @@ -10858,19 +10944,9 @@ static bool SetClosureVariableValue(Isolate* isolate,
|
| Handle<ScopeInfo> scope_info(shared->scope_info());
|
|
|
| // Context locals to the context extension.
|
| - for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
|
| - Handle<String> next_name(scope_info->ContextLocalName(i));
|
| - if (variable_name->Equals(*next_name)) {
|
| - VariableMode mode;
|
| - InitializationFlag init_flag;
|
| - int context_index =
|
| - scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
|
| - if (context_index < 0) {
|
| - return false;
|
| - }
|
| - context->set(context_index, *new_value);
|
| - return true;
|
| - }
|
| + if (SetContextLocalValue(
|
| + isolate, scope_info, context, variable_name, new_value)) {
|
| + return true;
|
| }
|
|
|
| // Properties from the function context extension. This will
|
| @@ -10915,6 +10991,20 @@ static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
|
| }
|
|
|
|
|
| +static bool SetCatchVariableValue(Isolate* isolate,
|
| + Handle<Context> context,
|
| + Handle<String> variable_name,
|
| + Handle<Object> new_value) {
|
| + ASSERT(context->IsCatchContext());
|
| + Handle<String> name(String::cast(context->extension()));
|
| + if (!name->Equals(*variable_name)) {
|
| + return false;
|
| + }
|
| + context->set(Context::THROWN_OBJECT_INDEX, *new_value);
|
| + return true;
|
| +}
|
| +
|
| +
|
| // Create a plain JSObject which materializes the block scope for the specified
|
| // block context.
|
| static Handle<JSObject> MaterializeBlockScope(
|
| @@ -11180,13 +11270,13 @@ class ScopeIterator {
|
| case ScopeIterator::ScopeTypeGlobal:
|
| break;
|
| case ScopeIterator::ScopeTypeLocal:
|
| - // TODO(2399): implement.
|
| - break;
|
| + return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
|
| + variable_name, new_value);
|
| case ScopeIterator::ScopeTypeWith:
|
| break;
|
| case ScopeIterator::ScopeTypeCatch:
|
| - // TODO(2399): implement.
|
| - break;
|
| + return SetCatchVariableValue(isolate_, CurrentContext(),
|
| + variable_name, new_value);
|
| case ScopeIterator::ScopeTypeClosure:
|
| return SetClosureVariableValue(isolate_, CurrentContext(),
|
| variable_name, new_value);
|
|
|