Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index dce2e15674b52fcc3ec30b8922923220112c14a6..6f5807d8d888fe2d0446dfd1fb344f859fc9ccdf 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -160,7 +160,8 @@ MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(JSObject* boilerplate) { |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
{ MaybeObject* maybe_result = |
- copy->SetProperty(key_string, result, NONE); |
+ // Creating object copy for literals. No strict mode needed. |
+ copy->SetProperty(key_string, result, NONE, kNonStrictMode); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
} |
@@ -546,7 +547,9 @@ static MaybeObject* Runtime_CreateCatchExtensionObject(Arguments args) { |
// Assign the exception value to the catch variable and make sure |
// that the catch variable is DontDelete. |
{ MaybeObject* maybe_value = |
- JSObject::cast(object)->SetProperty(key, value, DONT_DELETE); |
+ // Passing non-strict per ECMA-262 5th Ed. 12.14. Catch, bullet #4. |
+ JSObject::cast(object)->SetProperty( |
+ key, value, DONT_DELETE, kNonStrictMode); |
if (!maybe_value->ToObject(&value)) return maybe_value; |
} |
return object; |
@@ -994,12 +997,16 @@ static Failure* ThrowRedeclarationError(const char* type, Handle<String> name) { |
static MaybeObject* Runtime_DeclareGlobals(Arguments args) { |
+ ASSERT(args.length() == 4); |
HandleScope scope; |
Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global()); |
Handle<Context> context = args.at<Context>(0); |
CONVERT_ARG_CHECKED(FixedArray, pairs, 1); |
bool is_eval = Smi::cast(args[2])->value() == 1; |
+ StrictModeFlag strict_mode = |
+ static_cast<StrictModeFlag>(Smi::cast(args[3])->value()); |
+ ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); |
// Compute the property attributes. According to ECMA-262, section |
// 13, page 71, the property must be read-only and |
@@ -1109,7 +1116,11 @@ static MaybeObject* Runtime_DeclareGlobals(Arguments args) { |
value, |
attributes)); |
} else { |
- RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); |
+ RETURN_IF_EMPTY_HANDLE(SetProperty(global, |
+ name, |
+ value, |
+ attributes, |
+ strict_mode)); |
} |
} |
@@ -1170,7 +1181,8 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { |
// Slow case: The property is not in the FixedArray part of the context. |
Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
RETURN_IF_EMPTY_HANDLE( |
- SetProperty(context_ext, name, initial_value, mode)); |
+ SetProperty(context_ext, name, initial_value, |
+ mode, kNonStrictMode)); |
} |
} |
@@ -1211,7 +1223,8 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { |
return ThrowRedeclarationError("const", name); |
} |
} |
- RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode)); |
+ RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode, |
+ kNonStrictMode)); |
} |
return Heap::undefined_value(); |
@@ -1220,14 +1233,21 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { |
static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { |
NoHandleAllocation nha; |
+ // args[0] == name |
+ // args[1] == strict_mode |
+ // args[2] == value (optional) |
// Determine if we need to assign to the variable if it already |
// exists (based on the number of arguments). |
- RUNTIME_ASSERT(args.length() == 1 || args.length() == 2); |
- bool assign = args.length() == 2; |
+ RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); |
+ bool assign = args.length() == 3; |
CONVERT_ARG_CHECKED(String, name, 0); |
GlobalObject* global = Top::context()->global(); |
+ RUNTIME_ASSERT(args[1]->IsSmi()); |
+ StrictModeFlag strict_mode = |
+ static_cast<StrictModeFlag>(Smi::cast(args[1])->value()); |
+ ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); |
// According to ECMA-262, section 12.2, page 62, the property must |
// not be deletable. |
@@ -1283,8 +1303,9 @@ static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { |
} |
// Assign the value (or undefined) to the property. |
- Object* value = (assign) ? args[1] : Heap::undefined_value(); |
- return real_holder->SetProperty(&lookup, *name, value, attributes); |
+ Object* value = (assign) ? args[2] : Heap::undefined_value(); |
+ return real_holder->SetProperty( |
+ &lookup, *name, value, attributes, strict_mode); |
} |
Object* proto = real_holder->GetPrototype(); |
@@ -1298,7 +1319,9 @@ static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { |
} |
global = Top::context()->global(); |
- if (assign) return global->SetProperty(*name, args[1], attributes); |
+ if (assign) { |
+ return global->SetProperty(*name, args[2], attributes, strict_mode); |
+ } |
return Heap::undefined_value(); |
} |
@@ -1357,13 +1380,19 @@ static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) { |
// BUG 1213575: Handle the case where we have to set a read-only |
// property through an interceptor and only do it if it's |
// uninitialized, e.g. the hole. Nirk... |
- RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); |
+ // Passing non-strict mode because the property is writable. |
+ RETURN_IF_EMPTY_HANDLE(SetProperty(global, |
+ name, |
+ value, |
+ attributes, |
+ kNonStrictMode)); |
return *value; |
} |
// Set the value, but only we're assigning the initial value to a |
// constant. For now, we determine this by checking if the |
// current value is the hole. |
+ // Strict mode handling not needed (const disallowed in strict mode). |
PropertyType type = lookup.type(); |
if (type == FIELD) { |
FixedArray* properties = global->properties(); |
@@ -1439,7 +1468,9 @@ static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) { |
// context. |
if (attributes == ABSENT) { |
Handle<JSObject> global = Handle<JSObject>(Top::context()->global()); |
- RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, NONE)); |
+ // Strict mode not needed (const disallowed in strict mode). |
+ RETURN_IF_EMPTY_HANDLE( |
+ SetProperty(global, name, value, NONE, kNonStrictMode)); |
return *value; |
} |
@@ -1476,8 +1507,9 @@ static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) { |
// The property was found in a different context extension object. |
// Set it if it is not a read-only property. |
if ((attributes & READ_ONLY) == 0) { |
+ // Strict mode not needed (const disallowed in strict mode). |
RETURN_IF_EMPTY_HANDLE( |
- SetProperty(context_ext, name, value, attributes)); |
+ SetProperty(context_ext, name, value, attributes, kNonStrictMode)); |
} |
} |
@@ -1643,7 +1675,7 @@ static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder, |
code, |
false); |
optimized->shared()->DontAdaptArguments(); |
- SetProperty(holder, key, optimized, NONE); |
+ SetProperty(holder, key, optimized, NONE, kStrictMode); |
return optimized; |
} |
@@ -3739,7 +3771,8 @@ static MaybeObject* Runtime_DefineOrRedefineDataProperty(Arguments args) { |
MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, |
Handle<Object> key, |
Handle<Object> value, |
- PropertyAttributes attr) { |
+ PropertyAttributes attr, |
+ StrictModeFlag strict) { |
HandleScope scope; |
if (object->IsUndefined() || object->IsNull()) { |
@@ -3769,6 +3802,7 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, |
return *value; |
} |
+ // TODO(1220): Implement SetElement strict mode. |
Handle<Object> result = SetElement(js_object, index, value); |
if (result.is_null()) return Failure::Exception(); |
return *value; |
@@ -3781,7 +3815,7 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, |
} else { |
Handle<String> key_string = Handle<String>::cast(key); |
key_string->TryFlatten(); |
- result = SetProperty(js_object, key_string, value, attr); |
+ result = SetProperty(js_object, key_string, value, attr, strict); |
} |
if (result.is_null()) return Failure::Exception(); |
return *value; |
@@ -3794,9 +3828,10 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, |
Handle<String> name = Handle<String>::cast(converted); |
if (name->AsArrayIndex(&index)) { |
+ // TODO(1220): Implement SetElement strict mode. |
return js_object->SetElement(index, *value); |
} else { |
- return js_object->SetProperty(*name, *value, attr); |
+ return js_object->SetProperty(*name, *value, attr, strict); |
} |
} |
@@ -3888,23 +3923,27 @@ MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, |
static MaybeObject* Runtime_SetProperty(Arguments args) { |
NoHandleAllocation ha; |
- RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); |
+ RUNTIME_ASSERT(args.length() == 4 || args.length() == 5); |
Handle<Object> object = args.at<Object>(0); |
Handle<Object> key = args.at<Object>(1); |
Handle<Object> value = args.at<Object>(2); |
- |
+ CONVERT_SMI_CHECKED(unchecked_attributes, args[3]); |
+ RUNTIME_ASSERT( |
+ (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
// Compute attributes. |
- PropertyAttributes attributes = NONE; |
- if (args.length() == 4) { |
- CONVERT_CHECKED(Smi, value_obj, args[3]); |
- int unchecked_value = value_obj->value(); |
- // Only attribute bits should be set. |
- RUNTIME_ASSERT( |
- (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
- attributes = static_cast<PropertyAttributes>(unchecked_value); |
+ PropertyAttributes attributes = |
+ static_cast<PropertyAttributes>(unchecked_attributes); |
+ |
+ StrictModeFlag strict = kNonStrictMode; |
+ if (args.length() == 5) { |
+ CONVERT_SMI_CHECKED(strict_unchecked, args[4]); |
+ RUNTIME_ASSERT(strict_unchecked == kStrictMode || |
+ strict_unchecked == kNonStrictMode); |
+ strict = static_cast<StrictModeFlag>(strict_unchecked); |
} |
- return Runtime::SetObjectProperty(object, key, value, attributes); |
+ |
+ return Runtime::SetObjectProperty(object, key, value, attributes, strict); |
} |
@@ -3938,7 +3977,7 @@ static MaybeObject* Runtime_DeleteProperty(Arguments args) { |
CONVERT_CHECKED(JSObject, object, args[0]); |
CONVERT_CHECKED(String, key, args[1]); |
CONVERT_SMI_CHECKED(strict, args[2]); |
- return object->DeleteProperty(key, strict == kStrictMode |
+ return object->DeleteProperty(key, (strict == kStrictMode) |
? JSObject::STRICT_DELETION |
: JSObject::NORMAL_DELETION); |
} |
@@ -7486,11 +7525,16 @@ static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) { |
static MaybeObject* Runtime_StoreContextSlot(Arguments args) { |
HandleScope scope; |
- ASSERT(args.length() == 3); |
+ ASSERT(args.length() == 4); |
Handle<Object> value(args[0]); |
CONVERT_ARG_CHECKED(Context, context, 1); |
CONVERT_ARG_CHECKED(String, name, 2); |
+ CONVERT_SMI_CHECKED(strict_unchecked, args[3]); |
+ RUNTIME_ASSERT(strict_unchecked == kStrictMode || |
+ strict_unchecked == kNonStrictMode); |
+ StrictModeFlag strict = static_cast<StrictModeFlag>(strict_unchecked); |
+ |
int index; |
PropertyAttributes attributes; |
@@ -7534,7 +7578,12 @@ static MaybeObject* Runtime_StoreContextSlot(Arguments args) { |
// extension object itself. |
if ((attributes & READ_ONLY) == 0 || |
(context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { |
- RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE)); |
+ RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE, strict)); |
+ } else if (strict == kStrictMode && (attributes & READ_ONLY) != 0) { |
+ // Setting read only property in strict mode. |
+ Handle<Object> error = |
+ Factory::NewTypeError("strict_cannot_assign", HandleVector(&name, 1)); |
+ return Top::Throw(*error); |
} |
return *value; |
} |
@@ -9267,7 +9316,9 @@ static bool CopyContextLocalsToScopeObject( |
RETURN_IF_EMPTY_HANDLE_VALUE( |
SetProperty(scope_object, |
scope_info.context_slot_name(i), |
- Handle<Object>(context->get(context_index)), NONE), |
+ Handle<Object>(context->get(context_index)), |
+ NONE, |
+ kNonStrictMode), |
false); |
} |
} |
@@ -9293,7 +9344,9 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { |
RETURN_IF_EMPTY_HANDLE_VALUE( |
SetProperty(local_scope, |
scope_info.parameter_name(i), |
- Handle<Object>(frame->GetParameter(i)), NONE), |
+ Handle<Object>(frame->GetParameter(i)), |
+ NONE, |
+ kNonStrictMode), |
Handle<JSObject>()); |
} |
@@ -9302,7 +9355,9 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { |
RETURN_IF_EMPTY_HANDLE_VALUE( |
SetProperty(local_scope, |
scope_info.stack_slot_name(i), |
- Handle<Object>(frame->GetExpression(i)), NONE), |
+ Handle<Object>(frame->GetExpression(i)), |
+ NONE, |
+ kNonStrictMode), |
Handle<JSObject>()); |
} |
@@ -9326,7 +9381,11 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { |
ASSERT(keys->get(i)->IsString()); |
Handle<String> key(String::cast(keys->get(i))); |
RETURN_IF_EMPTY_HANDLE_VALUE( |
- SetProperty(local_scope, key, GetProperty(ext, key), NONE), |
+ SetProperty(local_scope, |
+ key, |
+ GetProperty(ext, key), |
+ NONE, |
+ kNonStrictMode), |
Handle<JSObject>()); |
} |
} |
@@ -9364,7 +9423,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) { |
SetProperty(closure_scope, |
scope_info.parameter_name(i), |
Handle<Object>(element), |
- NONE), |
+ NONE, |
+ kNonStrictMode), |
Handle<JSObject>()); |
} |
} |
@@ -9385,7 +9445,11 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) { |
ASSERT(keys->get(i)->IsString()); |
Handle<String> key(String::cast(keys->get(i))); |
RETURN_IF_EMPTY_HANDLE_VALUE( |
- SetProperty(closure_scope, key, GetProperty(ext, key), NONE), |
+ SetProperty(closure_scope, |
+ key, |
+ GetProperty(ext, key), |
+ NONE, |
+ kNonStrictMode), |
Handle<JSObject>()); |
} |
} |