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