213016d65a
This reverts commit 29c1eab92e
.
Reason for revert: Causes Blink test failures:
https://ci.chromium.org/p/v8/builders/ci/V8%20Blink%20Linux/4222
Original change's description:
> [builtins] Clean up the use of class_name / ES5 [[Class]]
>
> Before ES2015, the ES spec had a [[Class]] internal slot for all
> objects, which Object.prototype.toString() would use to figure the
> returned string. Post-ES2015, the [[Class]] slot was removed in spec for
> all objects, with the @@toStringTag well-known symbol the proper way to
> change Object.prototype.toString() output.
>
> At the time, spec-identical handling without the use of [[Class]] was
> implemented in V8 for all objects other than API objects, where issues
> with the Web IDL spec [1] prevented Blink, and hence V8, to totally
> migrate to @@toStringTag. However, since 2016 [2] Blink has been setting
> @@toStringTag on API class prototypes to manage the
> Object.prototype.toString() output, so the legacy [[Class]] handling in
> V8 has not been necessary for the past couple of years.
>
> This CL removes the remaining legacy [[Class]] handling in
> Object.prototype.toString(), JSReceiver::class_name(), and
> GetConstructorName(). However, it does not remove the class_name field
> in FunctionTemplateInfo, as it is still used for the `name` property of
> created functions.
>
> This CL also cleans up other places in the codebase that still reference
> [[Class]].
>
> This change should have minimal impact on web-compatibility. For the
> change to be observable, a script must do one of the following:
>
> 1. delete APIConstructor.prototype[Symbol.toStringTag];
> 2. Object.setPrototypeOf(apiObject, somethingElse);
>
> Before this CL, these changes will not change the apiObject.toString()
> output. But after this CL, they will make apiObject.toString() show
> "[object Object]" (in the first case) or the @@toStringTag of the other
> prototype (in the latter case).
>
> However, both are deemed unlikely. @@toStringTag is not well-known
> feature of JavaScript, nor does it get tampered much on API
> constructors. In the second case, setting the prototype of an API object
> would effectly render the object useless, as all its methods (including
> property getters/setters) would no longer be accessible.
>
> Currently, @@toStringTag-based API object branding is not yet
> implemented by other browsers. This V8 bug in particular has been an
> impediment to standardizing toString behavior. Fixing this bug will
> unblock [3] and lead to a better Web IDL spec, and better toString()
> compatibility for all.
>
> [1]: https://www.w3.org/Bugs/Public/show_bug.cgi?id=28244
> [2]: https://crrev.com/909c0d7d5a53c8526ded351683c65ea7d17531d4
> [3]: https://github.com/heycam/webidl/pull/357
>
> Bug: chromium:793406
> Cq-Include-Trybots: luci.chromium.try:linux-rel
> Change-Id: Iceded24e37afa2646ec385d5018909f55b177f93
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2146996
> Commit-Queue: Timothy Gu <timothygu@chromium.org>
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#67327}
TBR=verwaest@chromium.org,timothygu@chromium.org
Change-Id: I678d2ffc1064b1d1ddb62024cc23c6c41b216ef4
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:793406
Cq-Include-Trybots: luci.chromium.try:linux-rel
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2163956
Reviewed-by: Bill Budge <bbudge@chromium.org>
Commit-Queue: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67349}
337 lines
9.2 KiB
JavaScript
337 lines
9.2 KiB
JavaScript
// Copyright 2014 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
(function copyWithinArity() {
|
|
assertEquals(Array.prototype.copyWithin.length, 2);
|
|
})();
|
|
|
|
|
|
(function copyWithinTargetAndStart() {
|
|
// works with two arguemnts
|
|
assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3));
|
|
assertArrayEquals([1, 4, 5, 4, 5], [1, 2, 3, 4, 5].copyWithin(1, 3));
|
|
assertArrayEquals([1, 3, 4, 5, 5], [1, 2, 3, 4, 5].copyWithin(1, 2));
|
|
assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(2, 2));
|
|
})();
|
|
|
|
|
|
(function copyWithinTargetStartAndEnd() {
|
|
// works with three arguments
|
|
assertArrayEquals([1, 2, 3, 4, 5].copyWithin(0, 3, 4), [4, 2, 3, 4, 5]);
|
|
assertArrayEquals([1, 2, 3, 4, 5].copyWithin(1, 3, 4), [1, 4, 3, 4, 5]);
|
|
assertArrayEquals([1, 2, 3, 4, 5].copyWithin(1, 2, 4), [1, 3, 4, 4, 5]);
|
|
})();
|
|
|
|
|
|
(function copyWithinNegativeRelativeOffsets() {
|
|
// works with negative arguments
|
|
assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, -2));
|
|
assertArrayEquals([4, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, -2, -1));
|
|
assertArrayEquals([1, 3, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3, -2));
|
|
assertArrayEquals([1, 3, 4, 4, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3, -1));
|
|
assertArrayEquals([1, 3, 4, 5, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3));
|
|
// test with arguments equal to -this.length
|
|
assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-5, 0));
|
|
})();
|
|
|
|
|
|
(function copyWithinArrayLikeValues() {
|
|
// works with array-like values
|
|
var args = (function () { return arguments; }(1, 2, 3));
|
|
Array.prototype.copyWithin.call(args, -2, 0);
|
|
assertArrayEquals([1, 1, 2], Array.prototype.slice.call(args));
|
|
|
|
// [[Class]] does not change
|
|
assertArrayEquals("[object Arguments]", Object.prototype.toString.call(args));
|
|
})();
|
|
|
|
|
|
(function copyWithinNullThis() {
|
|
// throws on null/undefined values
|
|
assertThrows(function() {
|
|
return Array.prototype.copyWithin.call(null, 0, 3);
|
|
}, TypeError);
|
|
})();
|
|
|
|
|
|
(function copyWithinUndefinedThis() {
|
|
assertThrows(function() {
|
|
return Array.prototype.copyWithin.call(undefined, 0, 3);
|
|
}, TypeError);
|
|
})();
|
|
|
|
|
|
// TODO(caitp): indexed properties of String are read-only and setting them
|
|
// should throw in strict mode. See bug v8:4042
|
|
// (function copyWithinStringThis() {
|
|
// // test with this value as string
|
|
// assertThrows(function() {
|
|
// return Array.prototype.copyWithin.call("hello world", 0, 3);
|
|
// }, TypeError);
|
|
// })();
|
|
|
|
|
|
(function copyWithinNumberThis() {
|
|
// test with this value as number
|
|
assertEquals(34, Array.prototype.copyWithin.call(34, 0, 3).valueOf());
|
|
})();
|
|
|
|
|
|
(function copyWithinSymbolThis() {
|
|
// test with this value as number
|
|
var sym = Symbol("test");
|
|
assertEquals(sym, Array.prototype.copyWithin.call(sym, 0, 3).valueOf());
|
|
})();
|
|
|
|
|
|
(function copyyWithinTypedArray() {
|
|
// test with this value as TypedArray
|
|
var buffer = new ArrayBuffer(16);
|
|
var int32View = new Int32Array(buffer);
|
|
for (var i=0; i<int32View.length; i++) {
|
|
int32View[i] = i*2;
|
|
}
|
|
assertArrayEquals(new Int32Array([2, 4, 6, 6]),
|
|
Array.prototype.copyWithin.call(int32View, 0, 1));
|
|
})();
|
|
|
|
|
|
(function copyWithinSloppyArguments() {
|
|
// if arguments object is sloppy, copyWithin must move the arguments around
|
|
function f(a, b, c, d, e) {
|
|
[].copyWithin.call(arguments, 1, 3);
|
|
return [a, b, c, d, e];
|
|
}
|
|
assertArrayEquals([1, 4, 5, 4, 5], f(1, 2, 3, 4, 5));
|
|
})();
|
|
|
|
|
|
(function copyWithinStartLessThanTarget() {
|
|
// test with target > start on 2 arguments
|
|
assertArrayEquals([1, 2, 3, 1, 2], [1, 2, 3, 4, 5].copyWithin(3, 0));
|
|
|
|
// test with target > start on 3 arguments
|
|
assertArrayEquals([1, 2, 3, 1, 2], [1, 2, 3, 4, 5].copyWithin(3, 0, 4));
|
|
})();
|
|
|
|
|
|
(function copyWithinArrayWithHoles() {
|
|
// test on array with holes
|
|
var arr = new Array(6);
|
|
for (var i = 0; i < arr.length; i += 2) {
|
|
arr[i] = i;
|
|
}
|
|
assertArrayEquals([, 4, , , 4, , ], arr.copyWithin(0, 3));
|
|
})();
|
|
|
|
|
|
(function copyWithinArrayLikeWithHoles() {
|
|
// test on array-like object with holes
|
|
assertArrayEquals({
|
|
length: 6,
|
|
1: 4,
|
|
4: 4
|
|
}, Array.prototype.copyWithin.call({
|
|
length: 6,
|
|
0: 0,
|
|
2: 2,
|
|
4: 4
|
|
}, 0, 3));
|
|
})();
|
|
|
|
|
|
(function copyWithinNonIntegerRelativeOffsets() {
|
|
// test on fractional arguments
|
|
assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0.2, 3.9));
|
|
})();
|
|
|
|
|
|
(function copyWithinNegativeZeroTarget() {
|
|
// test with -0
|
|
assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-0, 3));
|
|
})();
|
|
|
|
|
|
(function copyWithinTargetOutsideStart() {
|
|
// test with arguments more than this.length
|
|
assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 7));
|
|
|
|
// test with arguments less than -this.length
|
|
assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-7, 0));
|
|
})();
|
|
|
|
|
|
(function copyWithinEmptyArray() {
|
|
// test on empty array
|
|
assertArrayEquals([], [].copyWithin(0, 3));
|
|
})();
|
|
|
|
|
|
(function copyWithinTargetCutOff() {
|
|
// test with target range being shorter than end - start
|
|
assertArrayEquals([1, 2, 2, 3, 4], [1, 2, 3, 4, 5].copyWithin(2, 1, 4));
|
|
})();
|
|
|
|
|
|
(function copyWithinOverlappingRanges() {
|
|
// test overlapping ranges
|
|
var arr = [1, 2, 3, 4, 5];
|
|
arr.copyWithin(2, 1, 4);
|
|
assertArrayEquals([1, 2, 2, 2, 3], arr.copyWithin(2, 1, 4));
|
|
})();
|
|
|
|
|
|
(function copyWithinStrictDelete() {
|
|
// check that [[Delete]] is strict (non-extensible via freeze)
|
|
assertThrows(function() {
|
|
return Object.freeze([1, , 3, , 4, 5]).copyWithin(2, 1, 4);
|
|
}, TypeError);
|
|
|
|
// check that [[Delete]] is strict (non-extensible via seal)
|
|
assertThrows(function() {
|
|
return Object.seal([1, , 3, , 4, 5]).copyWithin(2, 1, 4);
|
|
}, TypeError);
|
|
|
|
// check that [[Delete]] is strict (non-extensible via preventExtensions)
|
|
assertThrows(function() {
|
|
return Object.preventExtensions([1, , 3, , 4, 5]).copyWithin(2, 1, 4);
|
|
}, TypeError);
|
|
})();
|
|
|
|
|
|
(function copyWithinStrictSet() {
|
|
// check that [[Set]] is strict (non-extensible via freeze)
|
|
assertThrows(function() {
|
|
return Object.freeze([1, 2, 3, 4, 5]).copyWithin(0, 3);
|
|
}, TypeError);
|
|
|
|
// check that [[Set]] is strict (non-extensible via seal)
|
|
assertThrows(function() {
|
|
return Object.seal([, 2, 3, 4, 5]).copyWithin(0, 3);
|
|
}, TypeError);
|
|
|
|
// check that [[Set]] is strict (non-extensible via preventExtensions)
|
|
assertThrows(function() {
|
|
return Object.preventExtensions([ , 2, 3, 4, 5]).copyWithin(0, 3);
|
|
}, TypeError);
|
|
})();
|
|
|
|
|
|
(function copyWithinSetterThrows() {
|
|
function Boom() {}
|
|
// test if we throw in between
|
|
var arr = Object.defineProperty([1, 2, 3, 4, 5], 1, {
|
|
set: function () {
|
|
throw new Boom();
|
|
}
|
|
});
|
|
|
|
assertThrows(function() {
|
|
return arr.copyWithin(1, 3);
|
|
}, Boom);
|
|
|
|
assertArrayEquals([1, , 3, 4, 5], arr);
|
|
})();
|
|
|
|
|
|
(function copyWithinDefaultEnd() {
|
|
// undefined as third argument
|
|
assertArrayEquals(
|
|
[4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3, undefined));
|
|
})();
|
|
|
|
|
|
(function copyWithinGetLengthOnce() {
|
|
// test that this.length is called only once
|
|
var count = 0;
|
|
var arr = Object.defineProperty({ 0: 1, 1: 2, 2: 3, 3: 4, 4: 5 }, "length", {
|
|
get: function () {
|
|
count++;
|
|
return 5;
|
|
}
|
|
});
|
|
Array.prototype.copyWithin.call(arr, 1, 3);
|
|
assertEquals(1, count);
|
|
|
|
Array.prototype.copyWithin.call(arr, 1, 3, 4);
|
|
assertEquals(2, count);
|
|
})();
|
|
|
|
|
|
(function copyWithinLargeArray() {
|
|
var large = 10000;
|
|
|
|
// test on a large array
|
|
var arr = new Array(large);
|
|
assertArrayEquals(arr, arr.copyWithin(45, 9000));
|
|
|
|
var expected = new Array(large);
|
|
// test on floating point numbers
|
|
for (var i = 0; i < large; i++) {
|
|
arr[i] = Math.random();
|
|
expected[i] = arr[i];
|
|
if (i >= 9000) {
|
|
expected[(i - 9000) + 45] = arr[i];
|
|
}
|
|
}
|
|
assertArrayEquals(expected, arr.copyWithin(45, 9000));
|
|
|
|
// test on array of objects
|
|
for (var i = 0; i < large; i++) {
|
|
arr[i] = { num: Math.random() };
|
|
} + 45
|
|
arr.copyWithin(45, 9000);
|
|
|
|
// test copied by reference
|
|
for (var i = 9000; i < large; ++i) {
|
|
assertSame(arr[(i - 9000) + 45], arr[i]);
|
|
}
|
|
|
|
// test array length remains same
|
|
assertEquals(large, arr.length);
|
|
})();
|
|
|
|
|
|
(function copyWithinSuperLargeLength() {
|
|
// 2^53 - 1 is the maximum value returned from ToLength()
|
|
var large = Math.pow(2, 53) - 1;
|
|
var object = { length: large };
|
|
|
|
// Initialize last 10 entries
|
|
for (var i = 1; i <= 10; ++i) {
|
|
object[(large - 11) + i] = { num: i };
|
|
}
|
|
|
|
Array.prototype.copyWithin.call(object, 1, large - 10);
|
|
|
|
// Test copied values
|
|
for (var i = 1; i <= 10; ++i) {
|
|
var old_ref = object[(large - 11) + i];
|
|
var new_ref = object[i];
|
|
assertSame(old_ref, new_ref);
|
|
assertSame(new_ref.num, i);
|
|
}
|
|
|
|
// Assert length has not changed
|
|
assertEquals(large, object.length);
|
|
})();
|
|
|
|
|
|
(function copyWithinNullEnd() {
|
|
// test null on third argument is converted to +0
|
|
assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3, null));
|
|
})();
|
|
|
|
|
|
(function copyWithinElementsInObjectsPrototype() {
|
|
// tamper the global Object prototype and test this works
|
|
Object.prototype[2] = 1;
|
|
assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3));
|
|
delete Object.prototype[2];
|
|
|
|
Object.prototype[3] = "FAKE";
|
|
assertArrayEquals(["FAKE", 5, 3, "FAKE", 5], [1, 2, 3, , 5].copyWithin(0, 3));
|
|
delete Object.prototype[3];
|
|
})();
|