CALL_AND_RETRY(FUNCTION_CALL, return, return)
+#define CALL_HEAP_FUNCTION_INLINE(FUNCTION_CALL) \
+ CALL_AND_RETRY(FUNCTION_CALL, break, break)
+
+
#ifdef DEBUG
inline bool Heap::allow_allocation(bool new_state) {
MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
- Object* value) {
+ Object* value,
+ bool check_prototype) {
// Make sure that the top context does not change when doing
// callbacks or interceptor calls.
AssertNoContextChange ncc;
if (!result.IsEmpty()) return *value_handle;
}
MaybeObject* raw_result =
- this_handle->SetElementWithoutInterceptor(index, *value_handle);
+ this_handle->SetElementWithoutInterceptor(index,
+ *value_handle,
+ check_prototype);
RETURN_IF_SCHEDULED_EXCEPTION();
return raw_result;
}
// Adding n elements in fast case is O(n*n).
// Note: revisit design to have dual undefined values to capture absent
// elements.
-MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) {
+MaybeObject* JSObject::SetFastElement(uint32_t index,
+ Object* value,
+ bool check_prototype) {
ASSERT(HasFastElements());
Object* elms_obj;
FixedArray* elms = FixedArray::cast(elms_obj);
uint32_t elms_length = static_cast<uint32_t>(elms->length());
- if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
+ if (check_prototype && !IsJSArray() &&
+ (index >= elms_length || elms->get(index)->IsTheHole())) {
if (SetElementWithCallbackSetterInPrototypes(index, value)) {
return value;
}
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
ASSERT(HasDictionaryElements());
- return SetElement(index, value);
+ return SetElement(index, value, check_prototype);
}
-MaybeObject* JSObject::SetElement(uint32_t index, Object* value) {
+MaybeObject* JSObject::SetElement(uint32_t index,
+ Object* value,
+ bool check_prototype) {
// Check access rights if needed.
if (IsAccessCheckNeeded() &&
!Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
Object* proto = GetPrototype();
if (proto->IsNull()) return value;
ASSERT(proto->IsJSGlobalObject());
- return JSObject::cast(proto)->SetElement(index, value);
+ return JSObject::cast(proto)->SetElement(index, value, check_prototype);
}
// Check for lookup interceptor
if (HasIndexedInterceptor()) {
- return SetElementWithInterceptor(index, value);
+ return SetElementWithInterceptor(index, value, check_prototype);
}
- return SetElementWithoutInterceptor(index, value);
+ return SetElementWithoutInterceptor(index, value, check_prototype);
}
MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
- Object* value) {
+ Object* value,
+ bool check_prototype) {
switch (GetElementsKind()) {
case FAST_ELEMENTS:
// Fast case.
- return SetFastElement(index, value);
+ return SetFastElement(index, value, check_prototype);
case PIXEL_ELEMENTS: {
PixelArray* pixels = PixelArray::cast(elements());
return pixels->SetValue(index, value);
}
} else {
// Index not already used. Look for an accessor in the prototype chain.
- if (!IsJSArray()) {
- if (SetElementWithCallbackSetterInPrototypes(index, value)) {
- return value;
- }
+ if (check_prototype && !IsJSArray() &&
+ SetElementWithCallbackSetterInPrototypes(index, value)) {
+ return value;
}
// When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there).
bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);
- MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index, Object* value);
+ MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
+ Object* value,
+ bool check_prototype = true);
// Set the index'th array element.
// A Failure object is returned if GC is needed.
- MUST_USE_RESULT MaybeObject* SetElement(uint32_t index, Object* value);
+ MUST_USE_RESULT MaybeObject* SetElement(uint32_t index,
+ Object* value,
+ bool check_prototype = true);
// Returns the index'th element.
// The undefined object if index is out of bounds.
Object* value,
JSObject* holder);
MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(uint32_t index,
- Object* value);
- MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(uint32_t index,
- Object* value);
+ Object* value,
+ bool check_prototype);
+ MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(
+ uint32_t index,
+ Object* value,
+ bool check_prototype);
MaybeObject* GetElementPostInterceptor(JSObject* receiver, uint32_t index);
if (value.is_null()) return Handle<Object>::null();
uint32_t index;
if (key->AsArrayIndex(&index)) {
- SetElement(json_object, index, value);
+ CALL_HEAP_FUNCTION_INLINE(
+ (*json_object)->SetElement(index, *value, true));
} else {
- SetProperty(json_object, key, value, NONE);
+ CALL_HEAP_FUNCTION_INLINE(
+ (*json_object)->SetPropertyPostInterceptor(*key, *value, NONE));
}
} while (scanner_.Next() == Token::COMMA);
if (scanner_.current_token() != Token::RBRACE) {
--- /dev/null
+// Copyright 2010 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1015
+
+// Object and array literals should be created using DefineOwnProperty, and
+// therefore not hit setters in the prototype.
+
+function mkFail(message) {
+ return function () { assertUnreachable(message); }
+}
+
+Object.defineProperty(Object.prototype, "foo",
+ {get: mkFail("oget"), set: mkFail("oset")});
+Object.defineProperty(Array.prototype, "2",
+ {get: mkFail("aget"), set: mkFail("aset")});
+
+function inFunction() {
+ for (var i = 0; i < 10; i++) {
+ // in loop.
+ var ja = JSON.parse('[1,2,3,4]');
+ var jo = JSON.parse('{"bar": 10, "foo": 20}')
+ var jop = JSON.parse('{"bar": 10, "__proto__": { }, "foo": 20}')
+ var a = [1,2,3,4];
+ var o = { bar: 10, foo: 20 };
+ var op = { __proto__: { set bar(v) { assertUnreachable("bset"); } },
+ bar: 10 };
+ }
+}
+
+for (var i = 0; i < 10; i++) {
+ // In global scope.
+ var ja = JSON.parse('[1,2,3,4]');
+ var jo = JSON.parse('{"bar": 10, "foo": 20}')
+ var jop = JSON.parse('{"bar": 10, "__proto__": { }, "foo": 20}')
+ var a = [1,2,3,4];
+ var o = { bar: 10, foo: 20 };
+ var op = { __proto__: { set bar(v) { assertUnreachable("bset"); } },
+ bar: 10 };
+ // In function scope.
+ inFunction();
+}