MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
String* name,
Object* value,
- JSObject* holder) {
+ JSObject* holder,
+ StrictModeFlag strict_mode) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
if (setter->IsJSFunction()) {
return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
} else {
+ if (strict_mode == kNonStrictMode) {
+ return value;
+ }
Handle<String> key(name);
Handle<Object> holder_handle(holder, isolate);
Handle<Object> args[2] = { key, holder_handle };
}
-MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index,
- Object* value,
- bool* found) {
+MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
+ uint32_t index,
+ Object* value,
+ bool* found,
+ StrictModeFlag strict_mode) {
Heap* heap = GetHeap();
for (Object* pt = GetPrototype();
pt != heap->null_value();
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
*found = true;
- return SetElementWithCallback(
- dictionary->ValueAt(entry), index, value, JSObject::cast(pt));
+ return SetElementWithCallback(dictionary->ValueAt(entry),
+ index,
+ value,
+ JSObject::cast(pt),
+ strict_mode);
}
}
}
// We only need to deal with CALLBACKS and INTERCEPTORS
-MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result,
- String* name,
- Object* value,
- bool check_prototype) {
+MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
+ LookupResult* result,
+ String* name,
+ Object* value,
+ bool check_prototype,
+ StrictModeFlag strict_mode) {
if (check_prototype && !result->IsProperty()) {
LookupCallbackSetterInPrototypes(name, result);
}
return SetPropertyWithCallback(result->GetCallbackObject(),
name,
value,
- result->holder());
+ result->holder(),
+ strict_mode);
}
}
break;
LookupResult r;
LookupRealNamedProperty(name, &r);
if (r.IsProperty()) {
- return SetPropertyWithFailedAccessCheck(&r, name, value,
- check_prototype);
+ return SetPropertyWithFailedAccessCheck(&r,
+ name,
+ value,
+ check_prototype,
+ strict_mode);
}
break;
}
// Check access rights if needed.
if (IsAccessCheckNeeded()
&& !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
- return SetPropertyWithFailedAccessCheck(result, name, value, true);
+ return SetPropertyWithFailedAccessCheck(result,
+ name,
+ value,
+ true,
+ strict_mode);
}
if (IsJSGlobalProxy()) {
return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
name,
value,
- accessor_result.holder());
+ accessor_result.holder(),
+ strict_mode);
}
}
if (!result->IsFound()) {
return SetPropertyWithCallback(result->GetCallbackObject(),
name,
value,
- result->holder());
+ result->holder(),
+ strict_mode);
case INTERCEPTOR:
return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
case CONSTANT_TRANSITION: {
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
- return SetPropertyWithFailedAccessCheck(&result, name, value, false);
+ return SetPropertyWithFailedAccessCheck(&result,
+ name,
+ value,
+ false,
+ kNonStrictMode);
}
}
MaybeObject* JSObject::SetElementWithCallback(Object* structure,
uint32_t index,
Object* value,
- JSObject* holder) {
+ JSObject* holder,
+ StrictModeFlag strict_mode) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
}
if (structure->IsFixedArray()) {
- Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
+ Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex));
if (setter->IsJSFunction()) {
- return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
+ return SetPropertyWithDefinedSetter(JSFunction::cast(*setter), value);
} else {
+ if (strict_mode == kNonStrictMode) {
+ return value;
+ }
Handle<Object> holder_handle(holder, isolate);
Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
Handle<Object> args[2] = { key, holder_handle };
if (check_prototype &&
(index >= elms_length || elms->get(index)->IsTheHole())) {
bool found;
- MaybeObject* result =
- SetElementWithCallbackSetterInPrototypes(index, value, &found);
+ MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
+ value,
+ &found,
+ strict_mode);
if (found) return result;
}
Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
- return SetElementWithCallback(element, index, value, this);
+ return SetElementWithCallback(element,
+ index,
+ value,
+ this,
+ strict_mode);
} else {
dictionary->UpdateMaxNumberKey(index);
// If put fails instrict mode, throw exception.
bool found;
MaybeObject* result =
// Strict mode not needed. No-setter case already handled.
- SetElementWithCallbackSetterInPrototypes(index, value, &found);
+ SetElementWithCallbackSetterInPrototypes(index,
+ value,
+ &found,
+ strict_mode);
if (found) return result;
}
// When we set the is_extensible flag to false we always force
LookupResult* result,
String* name,
Object* value,
- bool check_prototype);
- MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(Object* structure,
- String* name,
- Object* value,
- JSObject* holder);
+ bool check_prototype,
+ StrictModeFlag strict_mode);
+ MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(
+ Object* structure,
+ String* name,
+ Object* value,
+ JSObject* holder,
+ StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSFunction* setter,
Object* value);
MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
- uint32_t index, Object* value, bool* found);
+ uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
void LookupCallback(String* name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
MaybeObject* SetElementWithCallback(Object* structure,
uint32_t index,
Object* value,
- JSObject* holder);
+ JSObject* holder,
+ StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(
uint32_t index,
Object* value,
--- /dev/null
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that an exception is not thrown when trying to set a value for
+// a property that has only a defined getter, except when in strict mode.
+
+var foo = Object.defineProperty({}, "bar", {
+ get: function () {
+ return 10;
+ }
+ });
+
+assertDoesNotThrow("foo.bar = 20");
+
+function shouldThrow() {
+ 'use strict';
+ foo.bar = 20;
+}
+
+assertThrows("shouldThrow()");