Commit fb6d7e17 authored by ricow@chromium.org's avatar ricow@chromium.org

Follow jsc on not throwing when trying to add a property to a non-extensible object.

This change makes us compatible with Safari on not throwing when trying to add a property to a non-extensible object. 
Review URL: http://codereview.chromium.org/6712059

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7379 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 67f20c4d
...@@ -1447,13 +1447,19 @@ MaybeObject* JSObject::AddSlowProperty(String* name, ...@@ -1447,13 +1447,19 @@ MaybeObject* JSObject::AddSlowProperty(String* name,
MaybeObject* JSObject::AddProperty(String* name, MaybeObject* JSObject::AddProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes) { PropertyAttributes attributes,
StrictModeFlag strict_mode) {
ASSERT(!IsJSGlobalProxy()); ASSERT(!IsJSGlobalProxy());
Heap* heap = GetHeap(); Heap* heap = GetHeap();
if (!map()->is_extensible()) { if (!map()->is_extensible()) {
Handle<Object> args[1] = {Handle<String>(name)}; if (strict_mode == kNonStrictMode) {
return heap->isolate()->Throw( return heap->undefined_value();
*FACTORY->NewTypeError("object_not_extensible", HandleVector(args, 1))); } else {
Handle<Object> args[1] = {Handle<String>(name)};
return heap->isolate()->Throw(
*FACTORY->NewTypeError("object_not_extensible",
HandleVector(args, 1)));
}
} }
if (HasFastProperties()) { if (HasFastProperties()) {
// Ensure the descriptor array does not get too big. // Ensure the descriptor array does not get too big.
...@@ -1494,7 +1500,7 @@ MaybeObject* JSObject::SetPropertyPostInterceptor( ...@@ -1494,7 +1500,7 @@ MaybeObject* JSObject::SetPropertyPostInterceptor(
return SetProperty(&result, name, value, attributes, strict_mode); return SetProperty(&result, name, value, attributes, strict_mode);
} }
// Add a new real property. // Add a new real property.
return AddProperty(name, value, attributes); return AddProperty(name, value, attributes, strict_mode);
} }
...@@ -2069,7 +2075,7 @@ MaybeObject* JSObject::SetProperty(LookupResult* result, ...@@ -2069,7 +2075,7 @@ MaybeObject* JSObject::SetProperty(LookupResult* result,
} }
if (!result->IsFound()) { if (!result->IsFound()) {
// Neither properties nor transitions found. // Neither properties nor transitions found.
return AddProperty(name, value, attributes); return AddProperty(name, value, attributes, strict_mode);
} }
if (result->IsReadOnly() && result->IsProperty()) { if (result->IsReadOnly() && result->IsProperty()) {
if (strict_mode == kStrictMode) { if (strict_mode == kStrictMode) {
...@@ -2177,7 +2183,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( ...@@ -2177,7 +2183,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
// Check for accessor in prototype chain removed here in clone. // Check for accessor in prototype chain removed here in clone.
if (!result.IsFound()) { if (!result.IsFound()) {
// Neither properties nor transitions found. // Neither properties nor transitions found.
return AddProperty(name, value, attributes); return AddProperty(name, value, attributes, kNonStrictMode);
} }
PropertyDetails details = PropertyDetails(attributes, NORMAL); PropertyDetails details = PropertyDetails(attributes, NORMAL);
...@@ -7431,13 +7437,17 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, ...@@ -7431,13 +7437,17 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
// When we set the is_extensible flag to false we always force // When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there). // the element into dictionary mode (and force them to stay there).
if (!map()->is_extensible()) { if (!map()->is_extensible()) {
Handle<Object> number(isolate->factory()->NewNumberFromUint(index)); if (strict_mode == kNonStrictMode) {
Handle<String> index_string( return isolate->heap()->undefined_value();
isolate->factory()->NumberToString(number)); } else {
Handle<Object> args[1] = { index_string }; Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
return isolate->Throw( Handle<String> index_string(
*isolate->factory()->NewTypeError("object_not_extensible", isolate->factory()->NumberToString(number));
HandleVector(args, 1))); Handle<Object> args[1] = { index_string };
return isolate->Throw(
*isolate->factory()->NewTypeError("object_not_extensible",
HandleVector(args, 1)));
}
} }
Object* result; Object* result;
{ MaybeObject* maybe_result = dictionary->AtNumberPut(index, value); { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value);
......
...@@ -1719,7 +1719,8 @@ class JSObject: public HeapObject { ...@@ -1719,7 +1719,8 @@ class JSObject: public HeapObject {
// Add a property to an object. // Add a property to an object.
MUST_USE_RESULT MaybeObject* AddProperty(String* name, MUST_USE_RESULT MaybeObject* AddProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes); PropertyAttributes attributes,
StrictModeFlag strict_mode);
// Convert the object to use the canonical dictionary // Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties // representation. If the object is expected to have additional properties
......
...@@ -3870,10 +3870,8 @@ THREADED_TEST(ExtensibleOnUndetectable) { ...@@ -3870,10 +3870,8 @@ THREADED_TEST(ExtensibleOnUndetectable) {
source = v8_str("undetectable.y = 2000;"); source = v8_str("undetectable.y = 2000;");
script = Script::Compile(source); script = Script::Compile(source);
v8::TryCatch try_catch;
Local<Value> result = script->Run(); Local<Value> result = script->Run();
CHECK(result.IsEmpty()); ExpectBoolean("undetectable.y == undefined", true);
CHECK(try_catch.HasCaught());
} }
......
...@@ -70,12 +70,8 @@ Object.freeze(obj); ...@@ -70,12 +70,8 @@ Object.freeze(obj);
assertFalse(Object.isExtensible(obj)); assertFalse(Object.isExtensible(obj));
assertTrue(Object.isFrozen(obj)); assertTrue(Object.isFrozen(obj));
try { obj.foo = 42;
obj.foo = 42; assertEquals(obj.foo, undefined);
assertUnreachable();
} catch(e) {
assertTrue(/object is not extensible/.test(e));
}
desc = Object.getOwnPropertyDescriptor(obj, 'x'); desc = Object.getOwnPropertyDescriptor(obj, 'x');
assertFalse(desc.writable); assertFalse(desc.writable);
...@@ -88,7 +84,7 @@ assertFalse(desc.configurable); ...@@ -88,7 +84,7 @@ assertFalse(desc.configurable);
assertEquals("foobar", desc.value); assertEquals("foobar", desc.value);
// Make sure that even if we try overwrite a value that is not writable, it is // Make sure that even if we try overwrite a value that is not writable, it is
// not changed. // not changed.
obj.x = "tete"; obj.x = "tete";
assertEquals(42, obj.x); assertEquals(42, obj.x);
obj.x = { get: function() {return 43}, set: function() {} }; obj.x = { get: function() {return 43}, set: function() {} };
...@@ -118,12 +114,8 @@ assertEquals(undefined, desc.value); ...@@ -118,12 +114,8 @@ assertEquals(undefined, desc.value);
assertEquals(set, desc.set); assertEquals(set, desc.set);
assertEquals(get, desc.get); assertEquals(get, desc.get);
try { obj2.foo = 42;
obj2.foo = 42; assertEquals(obj2.foo, undefined);
assertUnreachable();
} catch(e) {
assertTrue(/object is not extensible/.test(e));
}
// Test freeze on arrays. // Test freeze on arrays.
......
...@@ -35,22 +35,11 @@ Object.preventExtensions(obj1); ...@@ -35,22 +35,11 @@ Object.preventExtensions(obj1);
// Make sure the is_extensible flag is set. // Make sure the is_extensible flag is set.
assertFalse(Object.isExtensible(obj1)); assertFalse(Object.isExtensible(obj1));
// Try adding a new property. obj1.x = 42;
try {
obj1.x = 42;
assertUnreachable();
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
assertEquals(undefined, obj1.x); assertEquals(undefined, obj1.x);
// Try adding a new element. // Try adding a new element.
try { obj1[1] = 42;
obj1[1] = 42;
assertUnreachable();
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
assertEquals(undefined, obj1[1]); assertEquals(undefined, obj1[1]);
...@@ -64,25 +53,14 @@ assertTrue(Object.isExtensible(obj2)); ...@@ -64,25 +53,14 @@ assertTrue(Object.isExtensible(obj2));
Object.preventExtensions(obj2); Object.preventExtensions(obj2);
assertEquals(42, obj2.x); assertEquals(42, obj2.x);
try { obj2.y = 42;
obj2.y = 42;
assertUnreachable();
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
// obj2.y should still be undefined. // obj2.y should still be undefined.
assertEquals(undefined, obj2.y); assertEquals(undefined, obj2.y);
// Make sure we can still write values to obj.x. // Make sure we can still write values to obj.x.
obj2.x = 43; obj2.x = 43;
assertEquals(43, obj2.x) assertEquals(43, obj2.x)
try { obj2.y = new function() { return 42; };
obj2.y = new function() { return 42; };
assertUnreachable();
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
// obj2.y should still be undefined. // obj2.y should still be undefined.
assertEquals(undefined, obj2.y); assertEquals(undefined, obj2.y);
assertEquals(43, obj2.x) assertEquals(43, obj2.x)
...@@ -97,12 +75,7 @@ try { ...@@ -97,12 +75,7 @@ try {
assertEquals(undefined, obj2.y); assertEquals(undefined, obj2.y);
assertEquals(43, obj2.x); assertEquals(43, obj2.x);
try { obj2[1] = 42;
obj2[1] = 42;
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
assertEquals(undefined, obj2[1]); assertEquals(undefined, obj2[1]);
var arr = new Array(); var arr = new Array();
...@@ -110,12 +83,7 @@ arr[1] = 10; ...@@ -110,12 +83,7 @@ arr[1] = 10;
Object.preventExtensions(arr); Object.preventExtensions(arr);
try { arr[2] = 42;
arr[2] = 42;
assertUnreachable();
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
assertEquals(10, arr[1]); assertEquals(10, arr[1]);
// We should still be able to change exiting elements. // We should still be able to change exiting elements.
...@@ -134,12 +102,7 @@ var child = Object.create(parent); ...@@ -134,12 +102,7 @@ var child = Object.create(parent);
child.y = 42; child.y = 42;
// This should have no influence on the parent class. // This should have no influence on the parent class.
try { parent.y = 29;
parent.y = 29;
assertUnreachable();
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
// Test that attributes on functions are also handled correctly. // Test that attributes on functions are also handled correctly.
...@@ -149,9 +112,5 @@ function foo() { ...@@ -149,9 +112,5 @@ function foo() {
Object.preventExtensions(foo); Object.preventExtensions(foo);
try { foo.x = 29;
foo.x = 29; assertEquals(undefined, foo.x);
assertUnreachable();
} catch (e) {
assertTrue(/object is not extensible/.test(e));
}
...@@ -75,12 +75,8 @@ assertTrue(Object.isSealed(obj)); ...@@ -75,12 +75,8 @@ assertTrue(Object.isSealed(obj));
assertFalse(Object.isFrozen(obj)); assertFalse(Object.isFrozen(obj));
// We should not allow new properties to be added. // We should not allow new properties to be added.
try { obj.foo = 42;
obj.foo = 42; assertEquals(obj.foo, undefined);
assertUnreachable();
} catch(e) {
assertTrue(/object is not extensible/.test(e));
}
desc = Object.getOwnPropertyDescriptor(obj, 'x'); desc = Object.getOwnPropertyDescriptor(obj, 'x');
assertTrue(desc.writable); assertTrue(desc.writable);
...@@ -125,13 +121,8 @@ assertEquals(undefined, desc.value); ...@@ -125,13 +121,8 @@ assertEquals(undefined, desc.value);
assertEquals(set, desc.set); assertEquals(set, desc.set);
assertEquals(get, desc.get); assertEquals(get, desc.get);
try { obj2.foo = 42;
obj2.foo = 42; assertEquals(obj2.foo, undefined);
assertUnreachable();
} catch(e) {
assertTrue(/object is not extensible/.test(e));
}
// Test seal on arrays. // Test seal on arrays.
var arr = new Array(42,43); var arr = new Array(42,43);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --max-new-space-size=256 // Flags: --max-new-space-size=256
"use strict";
// Check for GC bug constructing exceptions. // Check for GC bug constructing exceptions.
var v = [1, 2, 3, 4] var v = [1, 2, 3, 4]
......
...@@ -983,7 +983,10 @@ function CheckPillDescriptor(func, name) { ...@@ -983,7 +983,10 @@ function CheckPillDescriptor(func, name) {
function CheckPill(pill) { function CheckPill(pill) {
assertEquals("function", typeof pill); assertEquals("function", typeof pill);
assertInstanceof(pill, Function); assertInstanceof(pill, Function);
assertThrows(function() { pill.property = "value"; }, TypeError); pill.property = "value";
assertEquals(pill.value, undefined);
assertThrows(function() { 'use strict'; pill.property = "value"; },
TypeError);
assertThrows(pill, TypeError); assertThrows(pill, TypeError);
assertEquals(pill.prototype, (function(){}).prototype); assertEquals(pill.prototype, (function(){}).prototype);
var d = Object.getOwnPropertyDescriptor(pill, "prototype"); var d = Object.getOwnPropertyDescriptor(pill, "prototype");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment