Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
deps: update ChakraCore to chakra-core/ChakraCore@6f03ee05ac
Browse files Browse the repository at this point in the history
[MERGE #5530 @irinayat-MS] 'length' property of arrays should have same delete semantics as own non-indexed non-configurable props

Merge pull request #5530 from irinayat-MS:DeleteArrayLength

Fixes OS#16382392

The assert has caught non-conforming behaviour of delete on 'length' property of Arrays. In strict mode delete should throw because 'length' is own and non-configurable.

Reviewed-By: chakrabot <chakrabot@users.noreply.github.com>
  • Loading branch information
Irina Yatsenko authored and kfarnung committed Aug 4, 2018
1 parent 2cbfd42 commit 521b324
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 30 deletions.
6 changes: 6 additions & 0 deletions deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12237,6 +12237,9 @@ using namespace Js;
{
if (propertyId == PropertyIds::length)
{
JavascriptError::ThrowCantDeleteIfStrictModeOrNonconfigurable(
flags, GetScriptContext(), BuiltInPropertyRecords::length.buffer);

return false;
}
return DynamicObject::DeleteProperty(propertyId, flags);
Expand All @@ -12246,6 +12249,9 @@ using namespace Js;
{
if (BuiltInPropertyRecords::length.Equals(propertyNameString))
{
JavascriptError::ThrowCantDeleteIfStrictModeOrNonconfigurable(
flags, GetScriptContext(), BuiltInPropertyRecords::length.buffer);

return false;
}
return DynamicObject::DeleteProperty(propertyNameString, flags);
Expand Down
8 changes: 0 additions & 8 deletions deps/chakrashim/core/test/Array/delete.baseline

This file was deleted.

106 changes: 91 additions & 15 deletions deps/chakrashim/core/test/Array/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,100 @@
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

function write(v) { WScript.Echo(v + ""); }
if (this.WScript && this.WScript.LoadScriptFile) { // Check for running in ch
this.WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
}

Object.prototype[5] = "obj.proto5";
Object.prototype[7] = "obj.proto7";
var tests = [
{
name: "Deleting of configurable non-indexed properties on Arrays",
body: function () {
var arr = [1,4,9,16];

Array.prototype[1] = "arr.proto.1";
Array.prototype[2] = "arr.proto.2";
Array.prototype[3] = "arr.proto.3";
Array.prototype[6] = "arr.proto.6";
arr.non_indexed = 'whatever';
Object.defineProperty(arr, 'with_getter', { get: function() { return 'with getter'; }, configurable: true });

var n=8;
var i=0;
assert.areEqual('whatever', arr.non_indexed, "arr.non_indexed is set to 'whatever'");
assert.areEqual('with getter', arr.with_getter, "arr.with_getter is set to 'with getter'");

var arr = new Array(n);
var res = delete arr.non_indexed;
assert.areEqual(true, res, "Deleting own property should succeed");
assert.areEqual(undefined, arr.non_indexed, "arr.non_indexed has been deleted");

for (i=3;i<n;i++) { arr[i] = i * i + 1; }
var res = delete arr.with_getter;
assert.areEqual(true, res, "Deleting own property with a getter should succeed");
assert.areEqual(undefined, arr.with_getter, "arr.with_getter has been deleted");
}
},
{
name: "Deleting of non-configurable non-indexed properties on Arrays",
body: function () {
var arr = [1,4,9,16];
var id = 'id';
Object.defineProperty(arr, id, { value: 17, configurable: false });

write(delete arr[1]); write("T1:" + arr.length + " : " + arr);
write(delete arr[3]); write("T2:" + arr.length + " : " + arr);
write(delete arr[n-1]); write("T3:" + arr.length + " : " + arr);
write(delete arr[n+1]); write("T4:" + arr.length + " : " + arr);
var res = delete arr[id];
assert.areEqual(false, res);
assert.areEqual(17, arr[id], "arr['id'] value after failed delete");

assert.throws(function () { 'use strict'; delete arr[id]; }, TypeError,
"Should throw on delete of non-indexed property in array",
"Calling delete on 'id' is not allowed in strict mode");
}
},
{
name: "Deleting of the 'length' property on Arrays",
body: function () {
var arr = [1,4,9,16];

var res = delete arr.length;
assert.areEqual(false, res, "delete of arr.length should fail (as noop)");
assert.areEqual(4, arr.length, "arr.length after attempting to delete it");

assert.throws(function () { 'use strict'; delete arr.length; }, TypeError,
"Should throw on delete of 'length' property in array",
"Calling delete on 'length' is not allowed in strict mode");
assert.areEqual(4, arr.length, "arr.length after attempting to delete it in strict mode");
}
},
{
name: "Deleting of indexed properties on Arrays",
body: function () {
var arr = [1,4,9,16];

var res = delete arr[1];
assert.areEqual(true, res, "delete of arr[1] should succeed");
assert.areEqual(undefined, arr[1], "arr[1] value after delete should be undefined");
assert.areEqual(4, arr.length, "the array's lenght should not change");

res = delete arr[42];
assert.areEqual(true, res, "delete of arr[42] (beyond the array bounds) should succeed");
assert.areEqual(4, arr.length, "the array's length is unchanged");

const last = arr.length - 1;
res = delete arr[last];
assert.areEqual(true, res, "delete of last element should succeed");
assert.areEqual(undefined, arr[last], "arr[last] value after delete should be undefined");
assert.areEqual(4, arr.length, "the array's lenght should not change");
}
},
{
name: "Deleting of indexed properties on Arrays that are also set on prototypes",
body: function () {
Object.prototype[4] = "obj.proto";
Array.prototype[1] = "arr.proto";
var arr = [1,4,9,16,25];

var res = delete arr[1];
assert.areEqual(true, res, "delete of arr[1] should succeed");
assert.areEqual("arr.proto", arr[1], "arr[1] after deleting should be picked up from the Array prototype");

var res = delete arr[4];
assert.areEqual(true, res, "delete of arr[4] should succeed");
assert.areEqual("obj.proto", arr[4], "arr[4] after deleting should be picked up from the Object prototype");
assert.areEqual(5, arr.length, "arr.length after deleting of the last element");
}
},
];

testRunner.runTests(tests, { verbose: false /*so no need to provide baseline*/ });
1 change: 0 additions & 1 deletion deps/chakrashim/core/test/Array/rlexe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@
<test>
<default>
<files>delete.js</files>
<baseline>delete.baseline</baseline>
</default>
</test>
<test>
Expand Down
29 changes: 23 additions & 6 deletions deps/chakrashim/core/test/typedarray/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,51 @@ var tests = [
ta.non_indexed = 'whatever';
assert.areEqual('whatever', ta.non_indexed, "ta.non_indexed is set to 'whatever'");

delete ta.non_indexed;
var res = delete ta.non_indexed;
assert.areEqual(true, res, "delete of configurable non-indexed property should succeed");
assert.areEqual(undefined, ta.non_indexed, "ta.non_indexed has been deleted");
}
},
{
name: "delete of nonconfigurable non-indexed properties on Typed arrays",
name: "Deleting of non-configurable non-indexed properties on Typed arrays",
body: function () {
const ta = Int8Array.of(42);
var id = 'id';
Object.defineProperty(ta, id, { value: 17, configurable: false });

delete ta[id];
var res = delete ta[id];
assert.areEqual(false, res, "delete of non-configurable property should fail");
assert.areEqual(17, ta[id], "ta['id'] value after failed delete");

assert.throws(function () { 'use strict'; delete ta[id]; }, TypeError, "Should throw on delete of indexed property in typed array", "Calling delete on 'id' is not allowed in strict mode");
assert.throws(function () { 'use strict'; delete ta[id]; }, TypeError, "Should throw on delete of non-indexed property in typed array", "Calling delete on 'id' is not allowed in strict mode");
}
},
{
name: "Typed arrays don't support delete of indexed properties",
body: function () {
const ta = Int8Array.of(42);

delete ta[0];
var res = delete ta[0];
assert.areEqual(false, res, "delete of ta[0] should fail");
assert.areEqual(42, ta[0], "ta[0] value after failed delete");

assert.throws(function () { 'use strict'; delete ta[0]; }, TypeError, "Should throw on delete of indexed property in typed array", "Calling delete on '0' is not allowed in strict mode");
}
}
},
{
name: "Typed arrays ignore delete of the inherited 'length' property",
body: function () {
const ta = Int8Array.of(42);

var res = delete ta.length;
assert.areEqual(true, res, "delete of ta.length should succeed (as noop)");
assert.areEqual(1, ta.length, "ta.length after attempting to delete it");

res = (function () { 'use strict'; return delete ta.length; })();
assert.areEqual(true, res, "delete of ta.length should succeed (as noop) in strict mode");
assert.areEqual(1, ta.length, "ta.length after attempting to delete it in strict mode");
}
},
];

testRunner.runTests(tests, { verbose: false /*so no need to provide baseline*/ });

0 comments on commit 521b324

Please sign in to comment.