Index: src/v8natives.js |
diff --git a/src/v8natives.js b/src/v8natives.js |
index f5ab122ff0aa8d2a1604f640ca97de7cb2499d1e..d444613f3a8ad0422aeae6d84c0f7cf7636bc2e8 100644 |
--- a/src/v8natives.js |
+++ b/src/v8natives.js |
@@ -873,6 +873,7 @@ function DefineArrayProperty(obj, p, desc, should_throw) { |
// Step 3 - Special handling for length property. |
if (p === "length") { |
var length = obj.length; |
+ var old_length = length; |
if (!desc.hasValue()) { |
return DefineObjectProperty(obj, "length", desc, should_throw); |
} |
@@ -889,8 +890,24 @@ function DefineArrayProperty(obj, p, desc, should_throw) { |
} |
} |
var threw = false; |
+ |
+ var emit_splice = %IsObserved(obj) && new_length !== old_length; |
+ var removed; |
+ if (emit_splice) { |
+ BeginPerformSplice(obj); |
+ removed = []; |
+ if (new_length < old_length) |
+ removed.length = old_length - new_length; |
+ } |
+ |
while (new_length < length--) { |
- if (!Delete(obj, ToString(length), false)) { |
+ var index = ToString(length); |
+ if (emit_splice) { |
+ var deletedDesc = GetOwnProperty(obj, index); |
+ if (deletedDesc && deletedDesc.hasValue()) |
+ removed[length - new_length] = deletedDesc.getValue(); |
+ } |
+ if (!Delete(obj, index, false)) { |
new_length = length + 1; |
threw = true; |
break; |
@@ -902,13 +919,18 @@ function DefineArrayProperty(obj, p, desc, should_throw) { |
// respective TODO in Runtime_DefineOrRedefineDataProperty. |
// For the time being, we need a hack to prevent Object.observe from |
// generating two change records. |
- var isObserved = %IsObserved(obj); |
- if (isObserved) %SetIsObserved(obj, false); |
obj.length = new_length; |
desc.value_ = void 0; |
desc.hasValue_ = false; |
threw = !DefineObjectProperty(obj, "length", desc, should_throw) || threw; |
- if (isObserved) %SetIsObserved(obj, true); |
+ if (emit_splice) { |
+ EndPerformSplice(obj); |
+ EnqueueSpliceRecord(obj, |
+ new_length < old_length ? new_length : old_length, |
+ removed, |
+ removed.length, |
+ new_length > old_length ? new_length - old_length : 0); |
+ } |
if (threw) { |
if (should_throw) { |
throw MakeTypeError("redefine_disallowed", [p]); |
@@ -916,27 +938,24 @@ function DefineArrayProperty(obj, p, desc, should_throw) { |
return false; |
} |
} |
- if (isObserved) { |
- var new_desc = GetOwnProperty(obj, "length"); |
- var updated = length_desc.value_ !== new_desc.value_; |
- var reconfigured = length_desc.writable_ !== new_desc.writable_ || |
- length_desc.configurable_ !== new_desc.configurable_ || |
- length_desc.enumerable_ !== new_desc.configurable_; |
- if (updated || reconfigured) { |
- NotifyChange(reconfigured ? "reconfigured" : "updated", |
- obj, "length", length_desc.value_); |
- } |
- } |
return true; |
} |
// Step 4 - Special handling for array index. |
var index = ToUint32(p); |
+ var emit_splice = false; |
if (ToString(index) == p && index != 4294967295) { |
var length = obj.length; |
+ if (index >= length && %IsObserved(obj)) { |
+ emit_splice = true; |
+ BeginPerformSplice(obj); |
+ } |
+ |
var length_desc = GetOwnProperty(obj, "length"); |
if ((index >= length && !length_desc.isWritable()) || |
!DefineObjectProperty(obj, p, desc, true)) { |
+ if (emit_splice) |
+ EndPerformSplice(obj); |
if (should_throw) { |
throw MakeTypeError("define_disallowed", [p]); |
} else { |
@@ -946,6 +965,10 @@ function DefineArrayProperty(obj, p, desc, should_throw) { |
if (index >= length) { |
obj.length = index + 1; |
} |
+ if (emit_splice) { |
+ EndPerformSplice(obj); |
+ EnqueueSpliceRecord(obj, length, [], 0, index + 1 - length); |
+ } |
return true; |
} |