Skip to content
forked from v8/v8

Commit

Permalink
[set-methods] Add isSubsetOf method
Browse files Browse the repository at this point in the history
This CL adds a slow (generic) implementation of isSubsetOf method to set methods.

Bug: v8:13556
Change-Id: Id80e7f3be598ea07cca7f5051377899730e2a103
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4656300
Reviewed-by: Shu-yu Guo <syg@chromium.org>
Commit-Queue: Rezvan Mahdavi Hezaveh <rezvan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#89240}
  • Loading branch information
rmahdav authored and V8 LUCI CQ committed Jul 27, 2023
1 parent b5263d8 commit 8672781
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 2 deletions.
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ filegroup(
"src/builtins/regexp-test.tq",
"src/builtins/set-difference.tq",
"src/builtins/set-intersection.tq",
"src/builtins/set-is-subset-of.tq",
"src/builtins/set-symmetric-difference.tq",
"src/builtins/set-union.tq",
"src/builtins/string-at.tq",
Expand Down
1 change: 1 addition & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1908,6 +1908,7 @@ torque_files = [
"src/builtins/regexp.tq",
"src/builtins/set-difference.tq",
"src/builtins/set-intersection.tq",
"src/builtins/set-is-subset-of.tq",
"src/builtins/set-symmetric-difference.tq",
"src/builtins/set-union.tq",
"src/builtins/string-at.tq",
Expand Down
2 changes: 0 additions & 2 deletions src/builtins/set-intersection.tq
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include 'src/objects/ordered-hash-table.h'

namespace collections {

// https://tc39.es/proposal-set-methods/#sec-set.prototype.intersection
Expand Down
65 changes: 65 additions & 0 deletions src/builtins/set-is-subset-of.tq
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2023 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.

namespace collections {

// https://tc39.es/proposal-set-methods/#sec-set.prototype.issubsetof
transitioning javascript builtin SetPrototypeIsSubsetOf(
js-implicit context: NativeContext,
receiver: JSAny)(other: JSAny): Boolean {
const methodName: constexpr string = 'Set.prototype.isSubsetOf';

// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[SetData]]).
const o = Cast<JSSet>(receiver) otherwise
ThrowTypeError(
MessageTemplate::kIncompatibleMethodReceiver, methodName, receiver);

const table = Cast<OrderedHashSet>(o.table) otherwise unreachable;

// 3. Let otherRec be ? GetSetRecord(other).
let otherRec = GetSetRecord(other, methodName);

// 4. Let thisSize be the number of elements in O.[[SetData]].
const thisSize =
LoadOrderedHashTableMetadata(table, kOrderedHashSetNumberOfElementsIndex);

// 5. If thisSize > otherRec.[[Size]], return false.
if (thisSize > Convert<int32>(otherRec.size)) {
return False;
}

// 6. Let index be 0.
let thisIter = collections::NewOrderedHashSetIterator(table);
let key: JSAny;

// 7. Repeat, while index < thisSize,
while (true) {
try {
// a. Let e be O.[[SetData]][index].
key = thisIter.Next() otherwise Done;
} label Done {
// 8. Return true.
return True;
}

// b. Set index to index + 1.
// c. Let inOther be ToBoolean(? Call(otherRec.[[Has]], otherRec.[[Set]], «
// e »)).
const inOther =
ToBoolean(Call(context, otherRec.has, otherRec.object, key));

// d. If inOther is false, return false.
if (!inOther) {
return False;
}
// e. NOTE: The number of elements in O.[[SetData]] may have increased
// during execution of otherRec.[[Has]].
// f. Set thisSize to the number of elements of O.[[SetData]].
// We have used `collections::NewOrderedHashSetIterator` which allows
// changes on the table.
}
unreachable;
}
}
2 changes: 2 additions & 0 deletions src/init/bootstrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4727,6 +4727,8 @@ void Genesis::InitializeGlobal_harmony_set_methods() {
Builtin::kSetPrototypeDifference, 1, true);
SimpleInstallFunction(isolate(), set_prototype, "symmetricDifference",
Builtin::kSetPrototypeSymmetricDifference, 1, true);
SimpleInstallFunction(isolate(), set_prototype, "isSubsetOf",
Builtin::kSetPrototypeIsSubsetOf, 1, true);
}

void Genesis::InitializeGlobal_harmony_json_parse_with_source() {
Expand Down
181 changes: 181 additions & 0 deletions test/mjsunit/harmony/set-is-subset-of.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Copyright 2023 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.
//
// Flags: --harmony-set-methods

(function TestIsSubsetOfSetFirstShorterIsSubset() {
const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);

const otherSet = new Set();
otherSet.add(42);
otherSet.add(43);
otherSet.add(47);

assertEquals(firstSet.isSubsetOf(otherSet), true);
})();

(function TestIsSubsetOfSetFirstShorterIsNotSubset() {
const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);

const otherSet = new Set();
otherSet.add(42);
otherSet.add(46);
otherSet.add(47);

assertEquals(firstSet.isSubsetOf(otherSet), false);
})();

(function TestIsSubsetOfSetSecondShorter() {
const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);
firstSet.add(44);

const otherSet = new Set();
otherSet.add(42);
otherSet.add(44);

assertEquals(firstSet.isSubsetOf(otherSet), false);
})();

(function TestIsSubsetOfMapFirstShorterIsSubset() {
const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);

const other = new Map();
other.set(42);
other.set(43);
other.set(47);

assertEquals(firstSet.isSubsetOf(other), true);
})();

(function TestIsSubsetOfMapFirstShorterIsNotSubset() {
const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);

const other = new Map();
other.set(42);
other.set(46);
other.set(47);

assertEquals(firstSet.isSubsetOf(other), false);
})();

(function TestIsSubsetOfMapSecondShorter() {
const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);
firstSet.add(44);

const other = new Map();
other.set(42);
other.set(43);

assertEquals(firstSet.isSubsetOf(other), false);
})();

(function TestIsSubsetOfSetLikeObjectFirstShorterIsSubset() {
const SetLike = {
arr: [42, 44, 45],
size: 3,
keys() {
return this.arr[Symbol.iterator]();
},
has(key) {
return this.arr.indexOf(key) != -1;
}
};

const firstSet = new Set();
firstSet.add(42);
firstSet.add(45);

assertEquals(firstSet.isSubsetOf(SetLike), true);
})();

(function TestIsSubsetOfSetLikeObjectFirstShorterIsNotSubset() {
const SetLike = {
arr: [42, 44, 45],
size: 3,
keys() {
return this.arr[Symbol.iterator]();
},
has(key) {
return this.arr.indexOf(key) != -1;
}
};

const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);

assertEquals(firstSet.isSubsetOf(SetLike), false);
})();

(function TestIsSubsetOfSetLikeObjectSecondShorter() {
const SetLike = {
arr: [42, 43],
size: 3,
keys() {
return this.arr[Symbol.iterator]();
},
has(key) {
return this.arr.indexOf(key) != -1;
}
};

const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);
firstSet.add(44);

assertEquals(firstSet.isSubsetOf(SetLike), false);
})();

(function TestIsSubsetOfSetEqualLengthIsSubset() {
const SetLike = {
arr: [42, 43, 45],
size: 3,
keys() {
return this.arr[Symbol.iterator]();
},
has(key) {
return this.arr.indexOf(key) != -1;
}
};

const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);
firstSet.add(45);

assertEquals(firstSet.isSubsetOf(SetLike), true);
})();

(function TestIsSubsetOfSetEqualLengthIsNotSubset() {
const SetLike = {
arr: [42, 44, 45],
size: 3,
keys() {
return this.arr[Symbol.iterator]();
},
has(key) {
return this.arr.indexOf(key) != -1;
}
};

const firstSet = new Set();
firstSet.add(42);
firstSet.add(43);
firstSet.add(45);

assertEquals(firstSet.isSubsetOf(SetLike), false);
})();

0 comments on commit 8672781

Please sign in to comment.