Add Set.prototype.union tests (#3816)

* Beginning of adding Set.prototype.union tests

* Fix description

* Add tests for GetSetRecord

Which also allows Set-like objects

* Add title to test descriptions

* Add test for ensuring values are appended

* Add tests for properties of union

Also: tests for RequireInternalSlot, Constructor, BuiltIns.

Added a test to ensure that -0F is converted to +0F

* Ensure Set.prototype.add is not called as part of .union

* fix lint issues

* Set subclassing and Symbol.species tests

* Set.prototype.union tests for arrays and subclass methods

* Add the Set-methods frontmatter feature flag

* Add additional Set.prototype.union test for edge cases

* Update test/built-ins/Set/GetSetRecord/keys-is-callable.js

Co-authored-by: Kevin Gibbons <bakkot@gmail.com>

* Use compareArray() for assertions

* Remove class field syntax

* Remove unused args

* Update test/built-ins/Set/prototype/union/subclass-receiver-methods.js

Co-authored-by: Jordan Harband <ljharb@gmail.com>

* Return original 'add'

* address comments

* add one more mutation in the evil mutating iterator test

* address further comments

---------

Co-authored-by: Kevin Gibbons <bakkot@gmail.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
Co-authored-by: Ms2ger <Ms2ger@igalia.com>
This commit is contained in:
Anthony Frehner 2023-11-15 09:55:47 -07:00 committed by GitHub
parent 5962be6d66
commit 60310b70bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 902 additions and 0 deletions

View File

@ -210,6 +210,7 @@ regexp-named-groups
regexp-unicode-property-escapes
rest-parameters
Set
Set-methods
SharedArrayBuffer
string-trimming
String.fromCodePoint

View File

@ -0,0 +1,27 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union should not call Set.prototype.add
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const s2 = new Set([2, 3]);
const expected = [1, 2, 3];
const originalAdd = Set.prototype.add;
let count = 0;
Set.prototype.add = function (...rest) {
count++;
return originalAdd.apply(this, rest);
};
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
assert.sameValue(count, 0, "Add is never called");
Set.prototype.add = originalAdd;

View File

@ -0,0 +1,34 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: GetSetRecord allows instances of Set-like classes
info: |
1. If obj is not an Object, throw a TypeError exception.
2. Let rawSize be ? Get(obj, "size").
...
7. Let has be ? Get(obj, "has").
...
9. Let keys be ? Get(obj, "keys").
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const s2 = new class {
get size() {
return 2;
}
has() {
throw new Test262Error("Set.prototype.union should not invoke .has on its argument");
}
* keys() {
yield 2;
yield 3;
}
};
const expected = [1, 2, 3];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,30 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: GetSetRecord allows Set-like objects
info: |
1. If obj is not an Object, throw a TypeError exception.
2. Let rawSize be ? Get(obj, "size").
...
7. Let has be ? Get(obj, "has").
...
9. Let keys be ? Get(obj, "keys").
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const s2 = {
size: 2,
has: () => {},
keys: function* keys() {
yield 2;
yield 3;
},
};
const expected = [1, 2, 3];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,30 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union appends new values to a copy of the original Set
info: |
7.b.iii.1 Append nextValue to resultSetData.
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const s2 = new Set([-1, 0, 3]);
const expected = [1, 2, -1, 0, 3];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
const s3 = new Set([1, 2, -3]);
const s4 = new Set([-1, 0]);
const expected2 = [1, 2, -3, -1, 0];
const combined2 = s3.union(s4);
assert.compareArray([...combined2], expected2);
assert.sameValue(
combined2 instanceof Set,
true,
"The returned object is a Set"
);

View File

@ -0,0 +1,17 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union doesn't work with arrays
features: [Set-methods]
---*/
const s1 = new Set([1, 2]);
const s2 = [3];
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"Throws an error when an array is used"
);

View File

@ -0,0 +1,25 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Tests that Set.prototype.union meets the requirements for built-in objects
features: [Set-methods]
---*/
assert.sameValue(
Object.isExtensible(Set.prototype.union),
true,
"Built-in objects must be extensible."
);
assert.sameValue(
Object.prototype.toString.call(Set.prototype.union),
"[object Function]",
"Object.prototype.toString"
);
assert.sameValue(
Object.getPrototypeOf(Set.prototype.union),
Function.prototype,
"prototype"
);

View File

@ -0,0 +1,66 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-getsetrecord
description: GetSetRecord throws if obj is not an object
info: |
1. If obj is not an Object, throw a TypeError exception.
features: [Set-methods]
---*/
let s1 = new Set([1]);
assert.throws(
TypeError,
function () {
s1.union(1);
},
"number"
);
assert.throws(
TypeError,
function () {
s1.union("");
},
"string"
);
assert.throws(
TypeError,
function () {
s1.union(1n);
},
"bigint"
);
assert.throws(
TypeError,
function () {
s1.union(false);
},
"boolean"
);
assert.throws(
TypeError,
function () {
s1.union(undefined);
},
"undefined"
);
assert.throws(
TypeError,
function () {
s1.union(null);
},
"null"
);
assert.throws(
TypeError,
function () {
s1.union(Symbol("test"));
},
"symbol"
);

View File

@ -0,0 +1,19 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union combines with Map
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const m1 = new Map([
[2, "two"],
[3, "three"],
]);
const expected = [1, 2, 3];
const combined = s1.union(m1);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,32 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union can combine empty Sets
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([]);
const s2 = new Set([1, 2]);
let expected = [1, 2];
let combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
const s3 = new Set([1, 2]);
const s4 = new Set([]);
expected = [1, 2];
combined = s3.union(s4);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
const s5 = new Set([]);
const s6 = new Set([]);
expected = [];
combined = s5.union(s6);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,15 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union is successful when called on itself
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const expected = [1, 2];
const combined = s1.union(s1);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,16 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union can combine Sets that have the same content
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const s2 = new Set([1, 2]);
const expected = [1, 2];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,16 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union combines Sets
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const s2 = new Set([2, 3]);
const expected = [1, 2, 3];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,35 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union converts -0𝔽 to +0𝔽
info: |
7.b.ii. If nextValue is -0𝔽, set nextValue to +0𝔽.
features: [Set-methods]
includes: [compareArray.js]
---*/
const setlikeWithMinusZero = {
size: 1,
has: function () {
throw new Test262Error("Set.prototype.union should not invoke .has on its argument");
},
keys: function () {
// we use an array here because the Set constructor would normalize away -0
return [-0].values();
},
};
const s1 = new Set([1]);
let expected = [1, +0];
let combined = s1.union(setlikeWithMinusZero);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
const s2 = new Set([+0]);
expected = [+0];
combined = s2.union(setlikeWithMinusZero);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,36 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-getsetrecord
description: GetSetRecord throws an exception if the Set-like object's 'has' property is not callable
info: |
7. Let has be ? Get(obj, "has").
8. If IsCallable(has) is false, throw a TypeError exception.
features: [Set-methods]
---*/
const s1 = new Set([1, 2]);
const s2 = {
size: 2,
has: undefined,
keys: function* keys() {
yield 2;
yield 3;
},
};
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when has is undefined"
);
s2.has = {};
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when has is not callable"
);

View File

@ -0,0 +1,33 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-getsetrecord
description: GetSetRecord throws an exception if the Set-like object's 'keys' property is not callable
info: |
9. Let keys be ? Get(obj, "keys").
10. If IsCallable(keys) is false, throw a TypeError exception.
features: [Set-methods]
---*/
const s1 = new Set([1, 2]);
const s2 = {
size: 2,
has: () => {},
keys: undefined,
};
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when keys is undefined"
);
s2.keys = {};
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when keys is not callable"
);

View File

@ -0,0 +1,18 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union length property
info: |
Set.prototype.union ( other )]
includes: [propertyHelper.js]
features: [Set-methods]
---*/
assert.sameValue(typeof Set.prototype.union, "function");
verifyProperty(Set.prototype.union, "length", {
enumerable: false,
writable: false,
configurable: true,
value: 1,
});

View File

@ -0,0 +1,18 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union name property
info: |
Set.prototype.union ( other )]
includes: [propertyHelper.js]
features: [Set-methods]
---*/
assert.sameValue(typeof Set.prototype.union, "function");
verifyProperty(Set.prototype.union, "name", {
enumerable: false,
writable: false,
configurable: true,
value: "union",
});

View File

@ -0,0 +1,22 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union does not implement [[Construct]], is not new-able
includes: [isConstructor.js]
features: [Reflect.construct, Set-methods]
---*/
assert.sameValue(
isConstructor(Set.prototype.union),
false,
"isConstructor(Set.prototype.union) must return false"
);
assert.throws(
TypeError,
() => {
new Set.prototype.union();
},
"`new Set.prototype.union()` throws TypeError"
);

View File

@ -0,0 +1,44 @@
// Copyright (C) 2023 Kevin Gibbons, Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union throws when receiver is not a Set
features: [Set-methods]
---*/
class MySetLike {
constructor() {
this.size = 2;
this.has = () => {};
this.keys = function* keys() {
yield 2;
yield 3;
};
}
}
const s1 = new MySetLike();
const s2 = new Set();
assert.throws(
TypeError,
() => {
Set.prototype.union.call(s1, s2);
},
"Set-like class"
);
const s3 = {
size: 2,
has: () => {},
keys: function* keys() {
yield 2;
yield 3;
},
};
assert.throws(
TypeError,
() => {
Set.prototype.union.call(s3, s2);
},
"Set-like object"
);

View File

@ -0,0 +1,25 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union RequireInternalSlot
info: |
2. Perform ? RequireInternalSlot(O, [[SetData]])
features: [Set-methods]
---*/
const union = Set.prototype.union;
assert.sameValue(typeof union, "function");
assert.throws(TypeError, () => union.call(undefined), "undefined");
assert.throws(TypeError, () => union.call(null), "null");
assert.throws(TypeError, () => union.call(true), "true");
assert.throws(TypeError, () => union.call(""), "empty string");
assert.throws(TypeError, () => union.call(Symbol()), "symbol");
assert.throws(TypeError, () => union.call(1), "1");
assert.throws(TypeError, () => union.call(1n), "1n");
assert.throws(TypeError, () => union.call({}), "plain object");
assert.throws(TypeError, () => union.call([]), "array");
assert.throws(TypeError, () => union.call(new Map()), "map");
assert.throws(TypeError, () => union.call(Set.prototype), "Set.prototype");

View File

@ -0,0 +1,24 @@
// Copyright (C) 2023 Kevin Gibbons, Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union consumes a set-like array as a set-like, not an array
features: [Set-methods]
includes: [compareArray.js]
---*/
const s1 = new Set([1, 2]);
const s2 = [5, 6];
s2.size = 3;
s2.has = function () {
throw new Test262Error("Set.prototype.union should not invoke .has on its argument");
};
s2.keys = function () {
return [2, 3, 4].values();
};
const expected = [1, 2, 3, 4];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");

View File

@ -0,0 +1,47 @@
// Copyright (C) 2023 Kevin Gibbons, Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union maintains values even when a custom Set-like class mutates the receiver
features: [Set-methods]
includes: [compareArray.js]
---*/
const baseSet = new Set(["a", "b", "c", "d", "e"]);
function mutatingIterator() {
let index = 0;
let values = ["x", "y"];
return {
next() {
baseSet.delete("b");
baseSet.delete("c");
baseSet.add("b");
baseSet.add("d");
return {
done: index >= 2,
value: values[index++],
};
},
};
}
const evilSetLike = {
size: 2,
get has() {
baseSet.add("q");
return function () {
throw new Test262Error("Set.prototype.union should not invoke .has on its argument");
};
},
keys() {
return mutatingIterator();
},
};
const combined = baseSet.union(evilSetLike);
const expectedCombined = ["a", "b", "c", "d", "e", "q", "x", "y"];
assert.compareArray([...combined], expectedCombined);
const expectedNewBase = ["a", "d", "e", "q", "b"];
assert.compareArray([...baseSet], expectedNewBase);

View File

@ -0,0 +1,83 @@
// Copyright (C) 2023 Kevin Gibbons, Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union calls a Set-like class's methods in order
features: [Set-methods]
includes: [compareArray.js]
---*/
const observedOrder = [];
const expectedOrder = [
"getting size",
"ToNumber(size)",
"getting has",
"getting keys",
"calling keys",
"getting next",
// first iteration, has value
"calling next",
"getting done",
"getting value",
// second iteration, has value
"calling next",
"getting done",
"getting value",
// third iteration, no value; ends
"calling next",
"getting done",
];
function observableIterator() {
let values = ["a", "b"];
let index = 0;
return {
get next() {
observedOrder.push("getting next");
return function () {
observedOrder.push("calling next");
return {
get done() {
observedOrder.push("getting done");
return index >= values.length;
},
get value() {
observedOrder.push("getting value");
return values[index++];
},
};
};
},
};
}
class MySetLike {
get size() {
observedOrder.push("getting size");
return {
valueOf: function () {
observedOrder.push("ToNumber(size)");
return 2;
},
};
}
get has() {
observedOrder.push("getting has");
return function () {
throw new Test262Error("Set.prototype.union should not invoke .has on its argument");
};
}
get keys() {
observedOrder.push("getting keys");
return function () {
observedOrder.push("calling keys");
return observableIterator();
};
}
}
const s1 = new Set([1, 2]);
const s2 = new MySetLike();
const combined = s1.union(s2);
assert.compareArray(observedOrder, expectedOrder);

View File

@ -0,0 +1,72 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-getsetrecord
description: GetSetRecord throws an exception if the Set-like object has a size that is coerced to NaN
info: |
2. Let rawSize be ? Get(obj, "size").
3. Let numSize be ? ToNumber(rawSize).
4. NOTE: If rawSize is undefined, then numSize will be NaN.
5. If numSize is NaN, throw a TypeError exception.
features: [Set-methods]
---*/
const s1 = new Set([1, 2]);
const s2 = {
size: undefined,
has: () => {},
keys: function* keys() {
yield 2;
yield 3;
},
};
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when size is undefined"
);
s2.size = NaN;
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when size is NaN"
);
let coercionCalls = 0;
s2.size = {
valueOf: function() {
++coercionCalls;
return NaN;
},
};
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when size coerces to NaN"
);
assert.sameValue(coercionCalls, 1, "GetSetRecord coerces size");
s2.size = 0n;
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when size is a BigInt"
);
s2.size = "string";
assert.throws(
TypeError,
function () {
s1.union(s2);
},
"GetSetRecord throws an error when size is a non-numeric string"
);

View File

@ -0,0 +1,45 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union works on subclasses of Set, but never calls the receiver's size/has/keys methods
features: [Set-methods]
includes: [compareArray.js]
---*/
let sizeCount = 0;
let hasCount = 0;
let keysCount = 0;
class MySet extends Set {
size(...rest) {
sizeCount++;
return super.size(...rest);
}
has(...rest) {
hasCount++;
return super.has(...rest);
}
keys(...rest) {
keysCount++;
return super.keys(...rest);
}
}
const s1 = new MySet([1, 2]);
const s2 = new Set([2, 3]);
const expected = [1, 2, 3];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
assert.sameValue(
combined instanceof MySet,
false,
"The returned object is a Set, not a subclass"
);
assert.sameValue(sizeCount, 0, "size should not be called on the receiver");
assert.sameValue(hasCount, 0, "has should not be called on the receiver");
assert.sameValue(keysCount, 0, "keys should not be called on the receiver");

View File

@ -0,0 +1,29 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union works on subclasses of Set, but returns an instance of Set even when Symbol.species is overridden.
features: [Set-methods]
includes: [compareArray.js]
---*/
var count = 0;
class MySet extends Set {
static get [Symbol.species]() {
count++;
return Set;
}
}
const s1 = new MySet([1, 2]);
const s2 = new Set([2, 3]);
const expected = [1, 2, 3];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(count, 0, "Symbol.species is never called");
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
assert.sameValue(
combined instanceof MySet,
false,
"The returned object is a Set, not a subclass"
);

View File

@ -0,0 +1,23 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union works on subclasses of Set, but returns an instance of Set
features: [Set-methods]
includes: [compareArray.js]
---*/
class MySet extends Set {}
const s1 = new MySet([1, 2]);
const s2 = new Set([2, 3]);
const expected = [1, 2, 3];
const combined = s1.union(s2);
assert.compareArray([...combined], expected);
assert.sameValue(combined instanceof Set, true, "The returned object is a Set");
assert.sameValue(
combined instanceof MySet,
false,
"The returned object is a Set, not a subclass"
);

View File

@ -0,0 +1,20 @@
// Copyright (C) 2023 Anthony Frehner. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-set.prototype.union
description: Set.prototype.union properties
includes: [propertyHelper.js]
features: [Set-methods]
---*/
assert.sameValue(
typeof Set.prototype.union,
"function",
"`typeof Set.prototype.union` is `'function'`"
);
verifyProperty(Set.prototype, "union", {
enumerable: false,
writable: true,
configurable: true,
});