Chromium Code Reviews| Index: src/v8natives.js |
| diff --git a/src/v8natives.js b/src/v8natives.js |
| index 9fd2162686d65ae878107a5969ed1723e629070f..cae079bb94782583453b2ce2250463de10f0eeaf 100644 |
| --- a/src/v8natives.js |
| +++ b/src/v8natives.js |
| @@ -545,10 +545,12 @@ function DefineOwnProperty(obj, p, desc, should_throw) { |
| if (IS_UNDEFINED(current) && !extensible) |
| throw MakeTypeError("define_disallowed", ["defineProperty"]); |
| - if (!IS_UNDEFINED(current) && !current.isConfigurable()) { |
| + if (!IS_UNDEFINED(current)) { |
| // Step 5 and 6 |
| - if ((!desc.hasEnumerable() || |
| - SameValue(desc.isEnumerable() && current.isEnumerable())) && |
| + if ((IsGenericDescriptor(desc) || |
| + IsDataDescriptor(desc) == IsDataDescriptor(current)) && |
| + (!desc.hasEnumerable() || |
| + SameValue(desc.isEnumerable(), current.isEnumerable())) && |
| (!desc.hasConfigurable() || |
| SameValue(desc.isConfigurable(), current.isConfigurable())) && |
| (!desc.hasWritable() || |
| @@ -561,29 +563,35 @@ function DefineOwnProperty(obj, p, desc, should_throw) { |
| SameValue(desc.getSet(), current.getSet()))) { |
| return true; |
| } |
| - |
| - // Step 7 |
| - if (desc.isConfigurable() || desc.isEnumerable() != current.isEnumerable()) |
| - throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| - // Step 9 |
| - if (IsDataDescriptor(current) != IsDataDescriptor(desc)) |
| - throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| - // Step 10 |
| - if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { |
| - if (!current.isWritable() && desc.isWritable()) |
| - throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| - if (!current.isWritable() && desc.hasValue() && |
| - !SameValue(desc.getValue(), current.getValue())) { |
| - throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| - } |
| - } |
| - // Step 11 |
| - if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { |
| - if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())){ |
| + if (!current.isConfigurable()) { |
| + // Step 7 |
| + if (desc.isConfigurable() || |
| + (desc.hasEnumerable() && |
| + desc.isEnumerable() != current.isEnumerable())) |
| throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| + // Step 8 |
| + if (!IsGenericDescriptor(desc)) { |
| + // Step 9a |
| + if (IsDataDescriptor(current) != IsDataDescriptor(desc)) |
| + throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| + // Step 10a |
| + if (IsDataDescriptor(current) && IsDataDescriptor(desc)) { |
| + if (!current.isWritable() && desc.isWritable()) |
| + throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| + if (!current.isWritable() && desc.hasValue() && |
| + !SameValue(desc.getValue(), current.getValue())) { |
| + throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| + } |
| + } |
| + // Step 11 |
| + if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) { |
| + if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())){ |
| + throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| + } |
| + if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) |
| + throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| + } |
| } |
| - if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) |
| - throw MakeTypeError("redefine_disallowed", ["defineProperty"]); |
| } |
| } |
| @@ -607,7 +615,16 @@ function DefineOwnProperty(obj, p, desc, should_throw) { |
| } else |
| flag |= DONT_DELETE; |
| - if (IsDataDescriptor(desc) || IsGenericDescriptor(desc)) { |
| + if (IsDataDescriptor(desc) || |
| + (IsGenericDescriptor(desc) && |
| + (IS_UNDEFINED(current) || IsDataDescriptor(current)))) { |
| + // There are 3 cases that lead here: |
| + // Step 4a - defining a new data property. |
| + // Steps 9b & 12 - replacing an existing accessor property with a data |
| + // property. |
| + // Step 12 - updating an existing data property with a data or generic |
| + // descriptor. |
| + |
| if (desc.hasWritable()) { |
| flag |= desc.isWritable() ? 0 : READ_ONLY; |
| } else if (!IS_UNDEFINED(current)) { |
| @@ -615,20 +632,30 @@ function DefineOwnProperty(obj, p, desc, should_throw) { |
| } else { |
| flag |= READ_ONLY; |
| } |
| + |
| var value = void 0; // Default value is undefined. |
| if (desc.hasValue()) { |
| value = desc.getValue(); |
| - } else if (!IS_UNDEFINED(current)) { |
| + } else if (!IS_UNDEFINED(current) && IsDataDescriptor(current)) { |
| value = current.getValue(); |
| } |
| + |
| %DefineOrRedefineDataProperty(obj, p, value, flag); |
| + } else if (IsGenericDescriptor(desc)) { |
| + // Step 12 - updating an existing accessor property with generic |
|
Rico
2011/01/07 09:47:30
with generic -> with a generic
|
| + // descriptor. Changing flags only. |
| + %DefineOrRedefineAccessorProperty(obj, p, GETTER, current.getGet(), flag); |
| } else { |
| - if (desc.hasGetter() && |
| - (IS_FUNCTION(desc.getGet()) || IS_UNDEFINED(desc.getGet()))) { |
| - %DefineOrRedefineAccessorProperty(obj, p, GETTER, desc.getGet(), flag); |
| + // There are 3 cases that lead here: |
| + // Step 4b - defining a new accessor property. |
| + // Steps 9c & 12 - replacing an existing data property with an accessor |
| + // property. |
| + // Step 12 - updating an existing accessor property with an accessor |
| + // descriptor. |
| + if (desc.hasGetter()) { |
| + %DefineOrRedefineAccessorProperty(obj, p, GETTER, desc.getGet(), flag); |
| } |
| - if (desc.hasSetter() && |
| - (IS_FUNCTION(desc.getSet()) || IS_UNDEFINED(desc.getSet()))) { |
| + if (desc.hasSetter()) { |
| %DefineOrRedefineAccessorProperty(obj, p, SETTER, desc.getSet(), flag); |
| } |
| } |