| 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;
|
| }
|
|
|
|
|