Bug 1566146 - Implement Set methods union, intersection, difference, symmetricDifference, isSubsetOf, isSuperSetOf, isDisjointFrom as per https://tc39.es/proposal-set-methods/ r=arai

Differential Revision: https://phabricator.services.mozilla.com/D131799
This commit is contained in:
jake champion 2021-11-30 03:40:50 +00:00
Родитель 48a5fa5e43
Коммит 6f9c143d3d
29 изменённых файлов: 1164 добавлений и 5 удалений

Просмотреть файл

@ -1148,3 +1148,25 @@ def enable_change_array_by_copy(value):
set_config("ENABLE_CHANGE_ARRAY_BY_COPY", enable_change_array_by_copy)
set_define("ENABLE_CHANGE_ARRAY_BY_COPY", enable_change_array_by_copy)
# Enable New Set methods
# ===================================================
def use_new_set_methods():
return False
option(
"--enable-new-set-methods",
default=use_new_set_methods(),
help="{Enable|Disable} New Set methods pref/command-line option (disabled by default)",
)
@depends("--enable-new-set-methods")
def enable_new_set_methods(value):
if value:
return True
set_config("ENABLE_NEW_SET_METHODS", enable_new_set_methods)
set_define("ENABLE_NEW_SET_METHODS", enable_new_set_methods)

Просмотреть файл

@ -232,6 +232,14 @@ class JS_PUBLIC_API RealmCreationOptions {
return *this;
}
#ifdef ENABLE_NEW_SET_METHODS
bool getNewSetMethodsEnabled() const { return newSetMethods_; }
RealmCreationOptions& setNewSetMethodsEnabled(bool flag) {
newSetMethods_ = flag;
return *this;
}
#endif
// This flag doesn't affect JS engine behavior. It is used by Gecko to
// mark whether content windows and workers are "Secure Context"s. See
// https://w3c.github.io/webappsec-secure-contexts/
@ -270,6 +278,9 @@ class JS_PUBLIC_API RealmCreationOptions {
bool toSource_ = false;
bool propertyErrorMessageFix_ = false;
bool iteratorHelpers_ = false;
#ifdef ENABLE_NEW_SET_METHODS
bool newSetMethods_ = false;
#endif
bool secureContext_ = false;
};

Просмотреть файл

@ -62,6 +62,7 @@ MSG_DEF(JSMSG_READ_ONLY, 1, JSEXN_TYPEERR, "{0} is read-only")
MSG_DEF(JSMSG_CANT_DELETE, 1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted")
MSG_DEF(JSMSG_CANT_TRUNCATE_ARRAY, 0, JSEXN_TYPEERR, "can't delete non-configurable array element")
MSG_DEF(JSMSG_NOT_FUNCTION, 1, JSEXN_TYPEERR, "{0} is not a function")
MSG_DEF(JSMSG_PROPERTY_NOT_CALLABLE, 1, JSEXN_TYPEERR, "{0} property is not callable")
MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} is not a constructor")
MSG_DEF(JSMSG_BOGUS_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} constructor can't be used directly")
MSG_DEF(JSMSG_CANT_CONVERT_TO, 2, JSEXN_TYPEERR, "can't convert {0} to {1}")

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function IteratorIdentity() {
function IteratorIdentity() {
return this;
}
@ -38,6 +38,40 @@ function IteratorClose(iteratorRecord, value) {
return value;
}
/**
* ES2022 draft rev c5f683e61d5dce703650f1c90d2309c46f8c157a
*
* GetIterator ( obj [ , hint [ , method ] ] )
* https://tc39.es/ecma262/#sec-getiterator
*
* Optimized for single argument
*/
function GetIteratorSync(obj) {
// Steps 1 & 2 skipped as we know we want the sync iterator method
var method = GetMethod(obj, GetBuiltinSymbol("iterator"))
// Step 3. Let iterator be ? Call(method, obj).
var iterator = callContentFunction(method, obj);
// Step 4. If Type(iterator) is not Object, throw a TypeError exception.
if (!IsObject(iterator)) {
ThrowTypeError(JSMSG_NOT_ITERABLE, obj === null ? "null" : typeof obj);
}
// Step 5. Let nextMethod be ? GetV(iterator, "next").
var nextMethod = iterator.next;
// Step 6. Let iteratorRecord be the Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }.
var iteratorRecord = {
iterator,
nextMethod,
done: false
};
// Step 7. Return iteratorRecord.
return iteratorRecord;
}
/* Iterator Helpers proposal 1.1.1 */
function GetIteratorDirect(obj) {
// Step 1.

Просмотреть файл

@ -1201,6 +1201,15 @@ const JSFunctionSpec SetObject::methods[] = {
JS_FN("entries", entries, 0, 0),
JS_FN("clear", clear, 0, 0),
JS_SELF_HOSTED_FN("forEach", "SetForEach", 2, 0),
#ifdef ENABLE_NEW_SET_METHODS
JS_SELF_HOSTED_FN("union", "SetUnion", 1, 0),
JS_SELF_HOSTED_FN("difference", "SetDifference", 1, 0),
JS_SELF_HOSTED_FN("intersection", "SetIntersection", 1, 0),
JS_SELF_HOSTED_FN("symmetricDifference", "SetSymmetricDifference", 1, 0),
JS_SELF_HOSTED_FN("isSubsetOf", "SetIsSubsetOf", 1, 0),
JS_SELF_HOSTED_FN("isSupersetOf", "SetIsSupersetOf", 1, 0),
JS_SELF_HOSTED_FN("isDisjointFrom", "SetIsDisjointFrom", 1, 0),
#endif
JS_FN("values", values, 0, 0),
// @@iterator and |keys| re-defined in finishInit so that they have the
// same identity as |values|.

Просмотреть файл

@ -261,6 +261,8 @@ class SetObject : public NativeObject {
// interfaces, etc.)
static SetObject* create(JSContext* cx, HandleObject proto = nullptr);
static uint32_t size(JSContext* cx, HandleObject obj);
[[nodiscard]] static bool add(JSContext* cx, unsigned argc, Value* vp);
[[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp);
[[nodiscard]] static bool has(JSContext* cx, HandleObject obj,
HandleValue key, bool* rval);
[[nodiscard]] static bool clear(JSContext* cx, HandleObject obj);
@ -310,9 +312,7 @@ class SetObject : public NativeObject {
[[nodiscard]] static bool size_impl(JSContext* cx, const CallArgs& args);
[[nodiscard]] static bool size(JSContext* cx, unsigned argc, Value* vp);
[[nodiscard]] static bool has_impl(JSContext* cx, const CallArgs& args);
[[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp);
[[nodiscard]] static bool add_impl(JSContext* cx, const CallArgs& args);
[[nodiscard]] static bool add(JSContext* cx, unsigned argc, Value* vp);
[[nodiscard]] static bool delete_impl(JSContext* cx, const CallArgs& args);
[[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp);
[[nodiscard]] static bool values_impl(JSContext* cx, const CallArgs& args);

Просмотреть файл

@ -19,6 +19,503 @@ function SetConstructorInit(iterable) {
callContentFunction(adder, set, nextValue);
}
#ifdef ENABLE_NEW_SET_METHODS
// New Set methods proposal
//
// Set.prototype.union(iterable)
// https://tc39.es/proposal-set-methods/#Set.prototype.union
function SetUnion(iterable) {
// Step 1. Let set be the this value.
var set = this;
// Step 2. If Type(set) is not Object, throw a TypeError exception.
if (!IsObject(set)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED,
set === null ? "null" : typeof set
);
}
// Step 3. Let Ctr be ? SpeciesConstructor(set, %Set%).
var Ctr = SpeciesConstructor(set, GetBuiltinConstructor("Set"));
// Step 4. Let newSet be ? Construct(Ctr, set).
var newSet = new Ctr(set);
// Step 5. Let adder be ? Get(newSet, "add").
var adder = newSet.add;
// Inlined AddEntryFromIterable Step 1. If IsCallable(adder) is false,
// throw a TypeError exception.
if (!IsCallable(adder)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "add");
}
// Step 6. Return ? AddEntryFromIterable(newSet, iterable, adder).
return AddEntryFromIterable(newSet, iterable, adder);
}
// New Set methods proposal
//
// Set.prototype.intersection(iterable)
// https://tc39.es/proposal-set-methods/#Set.prototype.intersection
function SetIntersection(iterable) {
// Step 1. Let set be the this value.
var set = this;
// Step 2. If Type(set) is not Object, throw a TypeError exception.
if (!IsObject(set)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED,
set === null ? "null" : typeof set
);
}
// Step 3. Let Ctr be ? SpeciesConstructor(set, %Set%).
var Ctr = SpeciesConstructor(set, GetBuiltinConstructor("Set"));
// Step 4. Let newSet be ? Construct(Ctr).
var newSet = new Ctr();
// Step 5. Let hasCheck be ? Get(set, "has").
var hasCheck = set.has;
// Step 6. If IsCallable(hasCheck) is false, throw a TypeError exception.
if (!IsCallable(hasCheck)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "has");
}
// Step 7. Let adder be ? Get(newSet, "add").
var adder = newSet.add;
// Step 8. If IsCallable(adder) is false, throw a TypeError exception.
if (!IsCallable(adder)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "add");
}
// Step 9. Let iteratorRecord be ? GetIterator(iterable).
var iteratorRecord = GetIteratorSync(iterable);
// Step 10. Repeat,
while (true) {
// Step a. Let next be ? IteratorStep(iteratorRecord).
var next = IteratorStep(iteratorRecord);
// Step b. If next is false, return newSet.
if (!next) {
return newSet;
}
// Step c. Let nextValue be ? IteratorValue(next).
var nextValue = next.value;
var needClose = true;
var has;
try {
// Step d. Let has be Call(hasCheck, set, « nextValue »).
has = callContentFunction(hasCheck, set, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step e. If has is an abrupt completion,
// return ? IteratorClose(iteratorRecord, has).
IteratorClose(iteratorRecord);
}
}
// Step f. If has.[[Value]] is true,
if (has) {
needClose = true;
try {
// Step i. Let status be Call(adder, newSet, « nextValue »).
callContentFunction(adder, newSet, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step ii. If status is an abrupt completion, return ?
// IteratorClose(iteratorRecord, status).
IteratorClose(iteratorRecord);
}
}
}
}
}
// New Set methods proposal
//
// Set.prototype.difference(iterable)
// https://tc39.es/proposal-set-methods/#Set.prototype.difference
function SetDifference(iterable) {
// Step 1. Let set be the this value.
var set = this;
// Step 2. If Type(set) is not Object, throw a TypeError exception.
if (!IsObject(set)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED,
set === null ? "null" : typeof set
);
}
// Step 3. Let Ctr be ? SpeciesConstructor(set, %Set%).
var Ctr = SpeciesConstructor(set, GetBuiltinConstructor("Set"));
// Step 4. Let newSet be ? Construct(Ctr, set).
var newSet = new Ctr(set);
// Step 5. Let remover be ? Get(newSet, "delete").
var remover = newSet.delete;
// Step 6. If IsCallable(remover) is false, throw a TypeError exception.
if (!IsCallable(remover)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "delete");
}
// Step 7. Let iteratorRecord be ? GetIterator(iterable).
var iteratorRecord = GetIteratorSync(iterable);
// Step 8. Repeat,
while (true) {
// Step a. Let next be ? IteratorStep(iteratorRecord).
var next = IteratorStep(iteratorRecord);
// Step b. If next is false, return newSet.
if (!next) {
return newSet;
}
// Step c. Let nextValue be ? IteratorValue(next).
var nextValue = next.value;
var needClose = true;
try {
// Step d. Let status be Call(remover, newSet, « nextValue »).
callContentFunction(remover, newSet, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step e. If status is an abrupt completion,
// return ? IteratorClose(iteratorRecord, status).
IteratorClose(iteratorRecord);
}
}
}
}
// New Set methods proposal
//
// Set.prototype.symmetricDifference(iterable)
// https://tc39.es/proposal-set-methods/#Set.prototype.symmetricDifference
function SetSymmetricDifference(iterable) {
// Step 1. Let set be the this value.
var set = this;
// Step 2. If Type(set) is not Object, throw a TypeError exception.
if (!IsObject(set)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED,
set === null ? "null" : typeof set
);
}
// Step 3. Let Ctr be ? SpeciesConstructor(set, %Set%).
var Ctr = SpeciesConstructor(set, GetBuiltinConstructor("Set"));
// Step 4. Let newSet be ? Construct(Ctr, set).
var newSet = new Ctr(set);
// Step 5. Let remover be ? Get(newSet, "delete").
var remover = newSet.delete;
// Step 6. If IsCallable(remover) is false, throw a TypeError exception.
if (!IsCallable(remover)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "delete");
}
// Step 7. Let adder be ? Get(newSet, "add").
var adder = newSet.add;
// Step 8. If IsCallable(adder) is false, throw a TypeError exception.
if (!IsCallable(adder)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "add");
}
// Step 9. Let iteratorRecord be ? GetIterator(iterable).
var iteratorRecord = GetIteratorSync(iterable);
// Step 10. Repeat,
while (true) {
// Step a. Let next be ? IteratorStep(iteratorRecord).
var next = IteratorStep(iteratorRecord);
// Step b. If next is false, return newSet.
if (!next) {
return newSet;
}
// Step c. Let nextValue be ? IteratorValue(next).
var nextValue = next.value;
var needClose = true;
var removed;
try {
// Step d. Let removed be Call(remover, newSet, « nextValue »).
removed = callContentFunction(remover, newSet, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step e. If removed is an abrupt completion,
// return ? IteratorClose(iteratorRecord, removed).
IteratorClose(iteratorRecord);
}
}
// Step f. If removed.[[Value]] is false,
if (!removed) {
needClose = true;
try {
// Step i. Let status be Call(adder, newSet, « nextValue »).
callContentFunction(adder, newSet, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step ii. If status is an abrupt completion,
// return ? IteratorClose(iteratorRecord, status).
IteratorClose(iteratorRecord);
}
}
}
}
}
// New Set methods proposal
//
// Set.prototype.isSubsetOf(iterable)
// https://tc39.es/proposal-set-methods/#Set.prototype.isSubsetOf
function SetIsSubsetOf(iterable) {
// Step 1. Let set be the this value.
var set = this;
// Step 2. Let iteratorRecord be ? GetIterator(set).
var iteratorRecord = GetIteratorSync(set);
// Step 3. If Type(iterable) is not Object, throw a TypeError exception.
if (!IsObject(iterable)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED,
set === null ? "null" : typeof set
);
}
// Step 4. Let otherSet be iterable.
var otherSet = iterable;
// Step 5. Let hasCheck be ? Get(otherSet, "has").
var hasCheck = otherSet.has;
// Step 6. If IsCallable(hasCheck) is false,
if (!IsCallable(hasCheck)) {
// Step a. Let otherSet be ? Construct(%Set%).
let set = GetBuiltinConstructor("Set");
otherSet = new set();
// We are not inlining AddEntryFromIterable Step 1 here because we know
// std_Set_add is callable Step b. Perform ?
// AddEntryFromIterable(otherSet, iterable, %SetProto_add%).
AddEntryFromIterable(otherSet, iterable, std_Set_add);
// Step c. Let hasCheck be %SetProto_has%.
hasCheck = std_Set_has;
}
// Step 7. Repeat,
while (true) {
// Step a. Let next be ? IteratorStep(iteratorRecord).
var next = IteratorStep(iteratorRecord);
// Step b. If next is false, return true.
if (!next) {
return true;
}
// Step c. Let nextValue be ? IteratorValue(next).
var nextValue = next.value;
var needClose = true;
var has;
try {
// Step d. Let has be Call(hasCheck, otherSet, « nextValue »).
has = callContentFunction(hasCheck, otherSet, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step e. If has is an abrupt completion,
// return ? IteratorClose(iteratorRecord, has).
IteratorClose(iteratorRecord);
}
}
// Step f. If has.[[Value]] is false, return false.
if (!has) {
return false;
}
}
}
// New Set methods proposal
//
// Set.prototype.isSupersetOf(iterable)
// https://tc39.es/proposal-set-methods/#Set.prototype.isSupersetOf
function SetIsSupersetOf(iterable) {
// Step 1. Let set be the this value.
var set = this;
// Step 2. If Type(set) is not Object, throw a TypeError exception.
if (!IsObject(set)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED,
set === null ? "null" : typeof set
);
}
// Step 3. Let hasCheck be ? Get(set, "has").
var hasCheck = set.has;
// Step 4. If IsCallable(hasCheck) is false, throw a TypeError exception.
if (!IsCallable(hasCheck)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "has");
}
// Step 5. Let iteratorRecord be ? GetIterator(iterable).
var iteratorRecord = GetIteratorSync(iterable);
// Step 6. Repeat,
while (true) {
// Step a. Let next be ? IteratorStep(iteratorRecord).
var next = IteratorStep(iteratorRecord);
// Step b. If next is false, return true.
if (!next) {
return true;
}
// Step c. Let nextValue be ? IteratorValue(next).
var nextValue = next.value;
var needClose = true;
var has;
try {
// Step d. Let has be Call(hasCheck, set, « nextValue »).
has = callContentFunction(hasCheck, set, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step e. If has is an abrupt completion,
// return ? IteratorClose(iteratorRecord, has).
IteratorClose(iteratorRecord);
}
}
// Step f. If has.[[Value]] is false, return false.
if (!has) {
return false;
}
}
}
// New Set methods proposal
//
// Set.prototype.isDisjointFrom(iterable)
// https://tc39.es/proposal-set-methods/#Set.prototype.isDisjointFrom
function SetIsDisjointFrom(iterable) {
// Step 1. Let set be the this value.
var set = this;
// Step 2. If Type(set) is not Object, throw a TypeError exception.
if (!IsObject(set)) {
ThrowTypeError(
JSMSG_OBJECT_REQUIRED,
set === null ? "null" : typeof set
);
}
// Step 3. Let hasCheck be ? Get(set, "has").
var hasCheck = set.has;
// Step 4. If IsCallable(hasCheck) is false, throw a TypeError exception.
if (!IsCallable(hasCheck)) {
ThrowTypeError(JSMSG_PROPERTY_NOT_CALLABLE, "has");
}
// Step 5. Let iteratorRecord be ? GetIterator(iterable).
var iteratorRecord = GetIteratorSync(iterable);
// Step 6. Repeat,
while (true) {
// Step a. Let next be ? IteratorStep(iteratorRecord).
var next = IteratorStep(iteratorRecord);
// Step b. If next is false, return true.
if (!next) {
return true;
}
// Step c. Let nextValue be ? IteratorValue(next).
var nextValue = next.value;
var needClose = true;
var has;
try {
// Step d. Let has be Call(hasCheck, set, « nextValue »).
has = callContentFunction(hasCheck, set, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step e. If has is an abrupt completion,
// return ? IteratorClose(iteratorRecord, has).
IteratorClose(iteratorRecord);
}
}
// Step f. If has.[[Value]] is true, return false.
if (has) {
return false;
}
}
}
// New Set methods proposal
//
// AddEntryFromIterable ( target, iterable, adder )
// https://tc39.es/proposal-set-methods/#AddEntryFromIterable
function AddEntryFromIterable(target, iterable, adder) {
assert(IsCallable(adder), "adder argument is callable");
// Step 2. Let iteratorRecord be ? GetIterator(iterable).
var iteratorRecord = GetIteratorSync(iterable);
// Step 3. Repeat,
while (true) {
// Step a. Let next be ? IteratorStep(iteratorRecord).
var next = IteratorStep(iteratorRecord);
// Step b. If next is false, return target.
if (!next) {
return target;
}
// Step c. Let nextValue be ? IteratorValue(next).
var nextValue = next.value;
var needClose = true;
try {
// Step d. Let status be Call(adder, target, « nextValue »).
callContentFunction(adder, target, nextValue);
needClose = false;
} finally {
if (needClose) {
// Step e. If status is an abrupt completion,
// return ? IteratorClose(iteratorRecord, status).
IteratorClose(iteratorRecord);
}
}
}
}
#endif
// ES2018 draft rev f83aa38282c2a60c6916ebc410bfdf105a0f6a54
// 23.2.3.6 Set.prototype.forEach ( callbackfn [ , thisArg ] )
function SetForEach(callbackfn, thisArg = undefined) {

Просмотреть файл

@ -211,6 +211,14 @@ static bool GetRealmConfiguration(JSContext* cx, unsigned argc, Value* vp) {
}
#endif
#ifdef ENABLE_NEW_SET_METHODS
bool newSetMethods = cx->realm()->creationOptions().getNewSetMethodsEnabled();
if (!JS_SetProperty(cx, info, "enableNewSetMethods",
newSetMethods ? TrueHandleValue : FalseHandleValue)) {
return false;
}
#endif
args.rval().setObject(*info);
return true;
}
@ -531,6 +539,15 @@ static bool GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
#ifdef ENABLE_NEW_SET_METHODS
value = BooleanValue(true);
#else
value = BooleanValue(false);
#endif
if (!JS_SetProperty(cx, info, "new-set-methods", value)) {
return false;
}
args.rval().setObject(*info);
return true;
}

Просмотреть файл

@ -628,6 +628,9 @@ bool shell::enableErgonomicBrandChecks = true;
#ifdef ENABLE_CHANGE_ARRAY_BY_COPY
bool shell::enableChangeArrayByCopy = false;
#endif
#ifdef ENABLE_NEW_SET_METHODS
bool shell::enableNewSetMethods = true;
#endif
bool shell::enableClassStaticBlocks = true;
#ifdef JS_GC_ZEAL
uint32_t shell::gZealBits = 0;
@ -4316,7 +4319,11 @@ static void SetStandardRealmOptions(JS::RealmOptions& options) {
: JS::WeakRefSpecifier::Disabled)
.setToSourceEnabled(enableToSource)
.setPropertyErrorMessageFixEnabled(enablePropertyErrorMessageFix)
.setIteratorHelpersEnabled(enableIteratorHelpers);
.setIteratorHelpersEnabled(enableIteratorHelpers)
#ifdef ENABLE_NEW_SET_METHODS
.setNewSetMethodsEnabled(enableNewSetMethods)
#endif
;
}
[[nodiscard]] static bool CheckRealmOptions(JSContext* cx,
@ -11287,6 +11294,9 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
!op.getBoolOption("disable-ergonomic-brand-checks");
#ifdef ENABLE_CHANGE_ARRAY_BY_COPY
enableChangeArrayByCopy = op.getBoolOption("enable-change-array-by-copy");
#endif
#ifdef ENABLE_NEW_SET_METHODS
enableNewSetMethods = op.getBoolOption("enable-new-set-methods");
#endif
enableClassStaticBlocks = !op.getBoolOption("disable-class-static-blocks");
useFdlibmForSinCosTan = op.getBoolOption("use-fdlibm-for-sin-cos-tan");
@ -12294,6 +12304,15 @@ int main(int argc, char** argv) {
#else
!op.addBoolOption('\0', "enable-change-array-by-copy", "no-op") ||
!op.addBoolOption('\0', "disable-change-array-by-copy", "no-op") ||
#endif
#ifdef ENABLE_NEW_SET_METHODS
!op.addBoolOption('\0', "enable-new-set-methods",
"Enable New Set methods") ||
!op.addBoolOption('\0', "disable-new-set-methods",
"Disable New Set methods") ||
#else
!op.addBoolOption('\0', "enable-new-set-methods", "no-op") ||
!op.addBoolOption('\0', "disable-new-set-methods", "no-op") ||
#endif
!op.addBoolOption('\0', "enable-top-level-await",
"Enable top-level await") ||

Просмотреть файл

@ -138,6 +138,9 @@ extern bool enableErgonomicBrandChecks;
#ifdef ENABLE_CHANGE_ARRAY_BY_COPY
extern bool enableChangeArrayByCopy;
#endif
#ifdef ENABLE_NEW_SET_METHODS
extern bool enableNewSetMethods;
#endif
extern bool enableClassStaticBlocks;
#ifdef JS_GC_ZEAL
extern uint32_t gZealBits;

Просмотреть файл

Просмотреть файл

@ -0,0 +1,63 @@
/*
* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
if (typeof getBuildConfiguration === "undefined") {
var getBuildConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration;
}
if (typeof getRealmConfiguration === "undefined") {
var getRealmConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration;
}
if (getBuildConfiguration()['new-set-methods'] && getRealmConfiguration().enableNewSetMethods) {
assertEq(typeof Set.prototype.difference, 'function');
assertEq(Set.prototype.difference.length, 1);
assertEq(Set.prototype.difference.name, 'difference');
assertSetContainsExactOrderedItems(new Set([1, true, null]).difference(new Set()), [1, true, null]);
assertSetContainsExactOrderedItems(new Set([1, true, null]).difference([1, true, null]), []);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).difference([2, 3, 4]), [1]);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).difference([4]), [1, 2, 3]);
// Works when the argument is a custom iterable which follows the Symbol.iterator protocol
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).difference(makeArrayIterator([3, 4])), [1, 2]);
assertSetContainsExactOrderedItems(new Set(['a','d']).difference('abc'), ['d']);
// Works when the `this` is a custom iterable which follows the Symbol.iterator protocol
assertSetContainsExactOrderedItems(Set.prototype.difference.call(makeArrayIterator([1, 2, 3, 3, 2]), [4, 5, 6]), [1, 2, 3]);
// Does not modify the original set object
const set = new Set([1]);
assertEq(set.difference([1]) !== set, true);
// Argument must be iterable
assertThrowsInstanceOf(function () {
const set = new Set();
set.difference();
}, TypeError);
for (const arg of [null, {}, true, 1, undefined, NaN, Symbol()]) {
assertThrowsInstanceOf(function () {
const set = new Set();
set.difference(arg);
}, TypeError);
}
// `this` must be an Object
for (const arg of [null, undefined, Symbol()]) {
assertThrowsInstanceOf(function () {
Set.prototype.difference.call(arg, []);
}, TypeError);
}
// `this` must be iterable
assertThrowsInstanceOf(function () {
Set.prototype.difference.call({}, []);
}, TypeError);
} else {
assertEq(typeof Set.prototype.difference, 'undefined');
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,63 @@
/*
* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
if (typeof getBuildConfiguration === "undefined") {
var getBuildConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration;
}
if (typeof getRealmConfiguration === "undefined") {
var getRealmConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration;
}
if (getBuildConfiguration()['new-set-methods'] && getRealmConfiguration().enableNewSetMethods) {
assertEq(typeof Set.prototype.intersection, 'function');
assertEq(Set.prototype.intersection.length, 1);
assertEq(Set.prototype.intersection.name, 'intersection');
assertSetContainsExactOrderedItems(new Set([1, true, null]).intersection(new Set()), []);
assertSetContainsExactOrderedItems(new Set([1, true, null]).intersection([1, true, null]), [1, true, null]);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).intersection([2, 3, 4]), [2, 3]);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).intersection([4]), []);
// Works when the argument is a custom iterable which follows the Symbol.iterator protocol
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).intersection(makeArrayIteratorWithHasMethod([3, 4])), [3]);
assertSetContainsExactOrderedItems(new Set(['a']).intersection('abc'), ['a']);
// Works when the `this` is a custom iterable which follows the Symbol.iterator protocol and has a `has` method
assertSetContainsExactOrderedItems(Set.prototype.intersection.call(makeArrayIteratorWithHasMethod([1, 2, 3, 3, 2]), [3, 4, 5, 6]), [3]);
// Does not modify the original set object
const set = new Set([1]);
assertEq(set.intersection([2]) !== set, true);
// Argument must be iterable
assertThrowsInstanceOf(function () {
const set = new Set();
set.intersection();
}, TypeError);
for (const arg of [null, {}, true, 1, undefined, NaN, Symbol()]) {
assertThrowsInstanceOf(function () {
const set = new Set();
set.intersection(arg);
}, TypeError);
}
// `this` must be an Object
for (const arg of [null, undefined, Symbol()]) {
assertThrowsInstanceOf(function () {
Set.prototype.intersection.call(arg, []);
}, TypeError);
}
// `this` must be iterable
assertThrowsInstanceOf(function () {
Set.prototype.intersection.call({}, []);
}, TypeError);
} else {
assertEq(typeof Set.prototype.intersection, 'undefined');
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,63 @@
/*
* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
if (typeof getBuildConfiguration === "undefined") {
var getBuildConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration;
}
if (typeof getRealmConfiguration === "undefined") {
var getRealmConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration;
}
if (getBuildConfiguration()['new-set-methods'] && getRealmConfiguration().enableNewSetMethods) {
assertEq(typeof Set.prototype.isDisjointFrom, 'function');
assertEq(Set.prototype.isDisjointFrom.length, 1);
assertEq(Set.prototype.isDisjointFrom.name, 'isDisjointFrom');
assertEq(new Set([1, true, null]).isDisjointFrom(new Set()), true);
assertEq(new Set([1, true, null]).isDisjointFrom([1, true, null]), false);
assertEq(new Set([1, 2, 3]).isDisjointFrom([2, 3, 4]), false);
assertEq(new Set([1, 2, 3]).isDisjointFrom([4]), true);
// Works when the argument is a custom iterable which follows the Symbol.iterator protocol
assertEq(new Set([1, 2, 3]).isDisjointFrom(makeArrayIteratorWithHasMethod([3, 4])), false);
assertEq(new Set(['a']).isDisjointFrom('abc'), false);
// Works when the `this` is a custom iterable which follows the Symbol.iterator protocol
assertEq(Set.prototype.isDisjointFrom.call(makeArrayIteratorWithHasMethod([1, 2, 3, 3, 2]), [4, 5, 6]), true);
// Does not modify the original set object
const set = new Set([1]);
assertEq(set.isDisjointFrom([2]) !== set, true);
// Argument must be iterable
assertThrowsInstanceOf(function () {
const set = new Set();
set.isDisjointFrom();
}, TypeError);
for (const arg of [null, {}, true, 1, undefined, NaN, Symbol()]) {
assertThrowsInstanceOf(function () {
const set = new Set();
set.isDisjointFrom(arg);
}, TypeError);
}
// `this` must be an Object
for (const arg of [null, undefined, Symbol()]) {
assertThrowsInstanceOf(function () {
Set.prototype.isDisjointFrom.call(arg, []);
}, TypeError);
}
// `this` must be iterable
assertThrowsInstanceOf(function () {
Set.prototype.isDisjointFrom.call({}, []);
}, TypeError);
} else {
assertEq(typeof Set.prototype.isDisjointFrom, 'undefined');
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,69 @@
/*
* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
if (typeof getBuildConfiguration === "undefined") {
var getBuildConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration;
}
if (typeof getRealmConfiguration === "undefined") {
var getRealmConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration;
}
if (getBuildConfiguration()['new-set-methods'] && getRealmConfiguration().enableNewSetMethods) {
assertEq(typeof Set.prototype.isSubsetOf, 'function');
assertEq(Set.prototype.isSubsetOf.length, 1);
assertEq(Set.prototype.isSubsetOf.name, 'isSubsetOf');
assertEq(new Set([1, true, null]).isSubsetOf(new Set()), false);
assertEq(new Set([1, true, null]).isSubsetOf([1, true, null]), true);
assertEq(new Set([1, 2, 3]).isSubsetOf([2, 3, 4]), false);
assertEq(new Set([1, 2, 3]).isSubsetOf([1, 2, 3, 4]), true);
// Works when the argument is a custom iterable which follows the Symbol.iterator protocol
assertEq(new Set([1, 2, 3]).isSubsetOf(makeArrayIteratorWithHasMethod([3, 4])), false);
// Works when the `this` is a custom iterable which follows the Symbol.iterator protocol
assertEq(
Set.prototype.isSubsetOf.call(
makeArrayIteratorWithHasMethod([1, 2, 3, 3, 2]),
makeArrayIteratorWithHasMethod([4, 5, 6])
),
false
);
// Does not modify the original set object
const set = new Set([1]);
assertEq(set.isSubsetOf(new Set([2])) !== set, true);
// Argument must be iterable and an object
assertThrowsInstanceOf(function () {
const set = new Set();
set.isSubsetOf();
}, TypeError);
for (const arg of [null, {}, true, 1, undefined, NaN, Symbol(), ""]) {
assertThrowsInstanceOf(function () {
const set = new Set();
set.isSubsetOf(arg);
}, TypeError);
}
// `this` must be an Object
for (const arg of [null, undefined, Symbol()]) {
assertThrowsInstanceOf(function () {
Set.prototype.isSubsetOf.call(arg, []);
}, TypeError);
}
// `this` must be iterable
assertThrowsInstanceOf(function () {
Set.prototype.isSubsetOf.call({}, []);
}, TypeError);
} else {
assertEq(typeof Set.prototype.isSubsetOf, 'undefined');
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,63 @@
/*
* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
if (typeof getBuildConfiguration === "undefined") {
var getBuildConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration;
}
if (typeof getRealmConfiguration === "undefined") {
var getRealmConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration;
}
if (getBuildConfiguration()['new-set-methods'] && getRealmConfiguration().enableNewSetMethods) {
assertEq(typeof Set.prototype.isSupersetOf, 'function');
assertEq(Set.prototype.isSupersetOf.length, 1);
assertEq(Set.prototype.isSupersetOf.name, 'isSupersetOf');
assertEq(new Set([1, true, null]).isSupersetOf(new Set()), true);
assertEq(new Set([1, true, null]).isSupersetOf([1, true, null]), true);
assertEq(new Set([1, 2, 3]).isSupersetOf([2, 3, 4]), false);
assertEq(new Set([1, 2, 3]).isSupersetOf([3]), true);
// Works when the argument is a custom iterable which follows the Symbol.iterator protocol
assertEq(new Set([1, 2, 3]).isSupersetOf(makeArrayIteratorWithHasMethod([2, 3])), true);
assertEq(new Set(['a']).isSupersetOf('abc'), false);
// Works when the `this` is a custom iterable which follows the Symbol.iterator protocol
assertEq(Set.prototype.isSupersetOf.call(makeArrayIteratorWithHasMethod([1, 2, 3, 3, 2]), [4, 5, 6]), false);
// Does not modify the original set object
const set = new Set([1]);
assertEq(set.isSupersetOf([2]) !== set, true);
// Argument must be iterable
assertThrowsInstanceOf(function () {
const set = new Set();
set.isSupersetOf();
}, TypeError);
for (const arg of [null, {}, true, 1, undefined, NaN, Symbol()]) {
assertThrowsInstanceOf(function () {
const set = new Set();
set.isSupersetOf(arg);
}, TypeError);
}
// `this` must be an Object
for (const arg of [null, undefined, Symbol()]) {
assertThrowsInstanceOf(function () {
Set.prototype.isSupersetOf.call(arg, []);
}, TypeError);
}
// `this` must be iterable
assertThrowsInstanceOf(function () {
Set.prototype.isSupersetOf.call({}, []);
}, TypeError);
} else {
assertEq(typeof Set.prototype.isSupersetOf, 'undefined');
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,45 @@
function makeArrayIterator(array) {
let i = 0;
return {
[Symbol.iterator]() {
return {
next() {
if (i >= array.length) {
return { done: true };
} else {
return { value: array[i++] };
}
}
};
}
}
}
function makeArrayIteratorWithHasMethod(array) {
let i = 0;
return {
has(item) {
return array.includes(item);
},
[Symbol.iterator]() {
return {
next() {
if (i >= array.length) {
return { done: true };
} else {
return { value: array[i++] };
}
}
};
}
};
}
function assertSetContainsExactOrderedItems(actual, expected) {
assertEq(actual.size, expected.length);
let index = 0;
for (const item of actual) {
assertEq(item, expected[index]);
index++;
}
}

Просмотреть файл

@ -0,0 +1,63 @@
/*
* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
if (typeof getBuildConfiguration === "undefined") {
var getBuildConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration;
}
if (typeof getRealmConfiguration === "undefined") {
var getRealmConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration;
}
if (getBuildConfiguration()['new-set-methods'] && getRealmConfiguration().enableNewSetMethods) {
assertEq(typeof Set.prototype.symmetricDifference, 'function');
assertEq(Set.prototype.symmetricDifference.length, 1);
assertEq(Set.prototype.symmetricDifference.name, 'symmetricDifference');
assertSetContainsExactOrderedItems(new Set([1, true, null]).symmetricDifference(new Set()), [1, true, null]);
assertSetContainsExactOrderedItems(new Set([1, true, null]).symmetricDifference([1, true, null]), []);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).symmetricDifference([2, 3, 4]), [1, 4]);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).symmetricDifference([4]), [1, 2, 3, 4]);
// Works when the argument is a custom iterable which follows the Symbol.iterator protocol
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).symmetricDifference(makeArrayIterator([3, 4])), [1, 2, 4]);
assertSetContainsExactOrderedItems(new Set(['a']).symmetricDifference('abc'), ['b', 'c']);
// Works when the `this` is a custom iterable which follows the Symbol.iterator protocol
assertSetContainsExactOrderedItems(Set.prototype.symmetricDifference.call(makeArrayIterator([1, 2, 3, 3, 2]), [4, 5, 6]), [1, 2, 3, 4, 5, 6]);
// Does not modify the original set object
const set = new Set([1]);
assertEq(set.symmetricDifference([2]) !== set, true);
// Argument must be iterable
assertThrowsInstanceOf(function () {
const set = new Set();
set.symmetricDifference();
}, TypeError);
for (const arg of [null, {}, true, 1, undefined, NaN, Symbol()]) {
assertThrowsInstanceOf(function () {
const set = new Set();
set.symmetricDifference(arg);
}, TypeError);
}
// `this` must be an Object
for (const arg of [null, undefined, Symbol()]) {
assertThrowsInstanceOf(function () {
Set.prototype.symmetricDifference.call(arg, []);
}, TypeError);
}
// `this` must be iterable
assertThrowsInstanceOf(function () {
Set.prototype.symmetricDifference.call({}, []);
}, TypeError);
} else {
assertEq(typeof Set.prototype.symmetricDifference, 'undefined');
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,65 @@
/*
* Any copyright is dedicated to the Public Domain.
* https://creativecommons.org/publicdomain/zero/1.0/
*/
if (typeof getBuildConfiguration === "undefined") {
var getBuildConfiguration =
SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration;
}
if (typeof getRealmConfiguration === "undefined") {
var getRealmConfiguration =
SpecialPowers.Cu.getJSTestingFunctions().getRealmConfiguration;
}
if (getBuildConfiguration()['new-set-methods'] && getRealmConfiguration().enableNewSetMethods) {
assertEq(typeof Set.prototype.union, 'function');
assertEq(Set.prototype.union.length, 1);
assertEq(Set.prototype.union.name, 'union');
assertSetContainsExactOrderedItems(new Set([1, true, null]).union(new Set()), [1, true, null]);
assertSetContainsExactOrderedItems(new Set([1, true, null]).union([1, true, null]), [1, true, null]);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).union([2, 3, 4]), [1, 2, 3, 4]);
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).union([4]), [1, 2, 3, 4]);
// Works when the argument is a custom iterable which follows the Symbol.iterator protocol
assertSetContainsExactOrderedItems(new Set([1, 2, 3]).union(makeArrayIterator([3, 4])), [1, 2, 3, 4]);
assertSetContainsExactOrderedItems(new Set(['a']).union('abc'), ['a', 'b', 'c']);
// Works when the `this` is a custom iterable which follows the Symbol.iterator protocol
assertSetContainsExactOrderedItems(Set.prototype.union.call(makeArrayIterator([1, 2, 3, 3, 2]), [4, 5, 6]), [1, 2, 3, 4, 5, 6]);
// Does not modify the original set object
const set = new Set([1]);
assertEq(set.union([2]) !== set, true);
// Argument must be iterable
assertThrowsInstanceOf(function () {
const set = new Set();
set.union();
}, TypeError);
for (const arg of [null, {}, true, 1, undefined, NaN, Symbol()]) {
assertThrowsInstanceOf(function () {
const set = new Set();
set.union(arg);
}, TypeError);
}
// `this` must be an Object
for (const arg of [null, undefined, Symbol()]) {
assertThrowsInstanceOf(function () {
Set.prototype.union.call(arg, []);
}, TypeError);
}
// `this` must be iterable
assertThrowsInstanceOf(function () {
Set.prototype.union.call({}, []);
}, TypeError);
} else {
assertEq(typeof Set.prototype.union, 'undefined');
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -35,3 +35,4 @@ user_pref("javascript.options.experimental.iterator_helpers", true);
user_pref("javascript.options.experimental.top_level_await", true);
user_pref("javascript.options.experimental.ergonomic_brand_checks", true);
user_pref("javascript.options.experimental.enable_change_array_by_copy", false);
user_pref("javascript.options.experimental.enable_new_set_methods", false);

Просмотреть файл

@ -28,6 +28,8 @@ static JSProtoKey ToProtoKey(BuiltinObjectKind kind) {
return JSProto_Promise;
case BuiltinObjectKind::RegExp:
return JSProto_RegExp;
case BuiltinObjectKind::Set:
return JSProto_Set;
case BuiltinObjectKind::SharedArrayBuffer:
return JSProto_SharedArrayBuffer;
case BuiltinObjectKind::Symbol:
@ -61,6 +63,7 @@ static bool IsPrototype(BuiltinObjectKind kind) {
case BuiltinObjectKind::Iterator:
case BuiltinObjectKind::Promise:
case BuiltinObjectKind::RegExp:
case BuiltinObjectKind::Set:
case BuiltinObjectKind::SharedArrayBuffer:
case BuiltinObjectKind::Symbol:
return false;
@ -101,6 +104,9 @@ BuiltinObjectKind js::BuiltinConstructorForName(
if (name == frontend::TaggedParserAtomIndex::WellKnown::RegExp()) {
return BuiltinObjectKind::RegExp;
}
if (name == frontend::TaggedParserAtomIndex::WellKnown::Set()) {
return BuiltinObjectKind::Set;
}
if (name == frontend::TaggedParserAtomIndex::WellKnown::SharedArrayBuffer()) {
return BuiltinObjectKind::SharedArrayBuffer;
}
@ -166,6 +172,8 @@ const char* js::BuiltinObjectName(BuiltinObjectKind kind) {
return "RegExp";
case BuiltinObjectKind::SharedArrayBuffer:
return "SharedArrayBuffer";
case BuiltinObjectKind::Set:
return "Set";
case BuiltinObjectKind::Symbol:
return "Symbol";

Просмотреть файл

@ -35,6 +35,7 @@ enum class BuiltinObjectKind : uint8_t {
Iterator,
Promise,
RegExp,
Set,
SharedArrayBuffer,
Symbol,

Просмотреть файл

@ -121,6 +121,7 @@
MACRO_(defineSetter, defineSetter, "__defineSetter__") \
MACRO_(delete, delete_, "delete") \
MACRO_(deleteProperty, deleteProperty, "deleteProperty") \
MACRO_(difference, difference, "difference") \
MACRO_(displayURL, displayURL, "displayURL") \
MACRO2(do, do_, "do") \
MACRO_(domNode, domNode, "domNode") \
@ -243,6 +244,7 @@
MACRO_(index, index, "index") \
MACRO_(indices, indices, "indices") \
MACRO_(infinity, infinity, "infinity") \
MACRO_(intersection, intersection, "intersection") \
MACRO_(Infinity, Infinity, "Infinity") \
MACRO_(initial, initial, "initial") \
MACRO_(InitializeCollator, InitializeCollator, "InitializeCollator") \
@ -271,12 +273,15 @@
"InterpretGeneratorResume") \
MACRO_(InvalidDate, InvalidDate, "Invalid Date") \
MACRO_(isBreakpoint, isBreakpoint, "isBreakpoint") \
MACRO_(isDisjointFrom, isDisjointFrom, "isDisjointFrom") \
MACRO_(isEntryPoint, isEntryPoint, "isEntryPoint") \
MACRO_(isExtensible, isExtensible, "isExtensible") \
MACRO_(isFinite, isFinite, "isFinite") \
MACRO_(isNaN, isNaN, "isNaN") \
MACRO_(isPrototypeOf, isPrototypeOf, "isPrototypeOf") \
MACRO_(isStepStart, isStepStart, "isStepStart") \
MACRO_(isSubsetOf, isSubsetOf, "isSubsetOf") \
MACRO_(isSupersetOf, isSupersetOf, "isSupersetOf") \
MACRO_(IterableToList, IterableToList, "IterableToList") \
MACRO_(iterate, iterate, "iterate") \
MACRO_(join, join, "join") \
@ -457,6 +462,7 @@
MACRO_(style, style, "style") \
MACRO_(super, super, "super") \
MACRO_(switch, switch_, "switch") \
MACRO_(symmetricDifference, symmetricDifference, "symmetricDifference") \
MACRO_(Symbol_iterator_fun, Symbol_iterator_fun, "[Symbol.iterator]") \
MACRO_(target, target, "target") \
MACRO_(test, test, "test") \
@ -497,6 +503,7 @@
MACRO_(uneval, uneval, "uneval") \
MACRO_(unicode, unicode, "unicode") \
MACRO_(uninitialized, uninitialized, "uninitialized") \
MACRO_(union, union_, "union") \
MACRO_(unit, unit, "unit") \
MACRO_(unitDisplay, unitDisplay, "unitDisplay") \
MACRO_(unknown, unknown, "unknown") \

Просмотреть файл

@ -2164,6 +2164,20 @@ JS_PUBLIC_API bool js::ShouldIgnorePropertyDefinition(JSContext* cx,
}
#endif
#ifdef ENABLE_NEW_SET_METHODS
if (key == JSProto_Set &&
!cx->realm()->creationOptions().getNewSetMethodsEnabled() &&
(id == NameToId(cx->names().union_) ||
id == NameToId(cx->names().difference) ||
id == NameToId(cx->names().intersection) ||
id == NameToId(cx->names().isSubsetOf) ||
id == NameToId(cx->names().isSupersetOf) ||
id == NameToId(cx->names().isDisjointFrom) ||
id == NameToId(cx->names().symmetricDifference))) {
return true;
}
#endif
return false;
}

Просмотреть файл

@ -2456,6 +2456,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
ReflectGetPrototypeOf),
JS_FN("std_Reflect_isExtensible", Reflect_isExtensible, 1, 0),
JS_FN("std_Reflect_ownKeys", Reflect_ownKeys, 1, 0),
JS_FN("std_Set_add", SetObject::add, 1, 0),
JS_FN("std_Set_has", SetObject::has, 1, 0),
JS_FN("std_Set_values", SetObject::values, 0, 0),
JS_INLINABLE_FN("std_String_charCodeAt", str_charCodeAt, 1, 0,
StringCharCodeAt),

Просмотреть файл

@ -800,7 +800,11 @@ void xpc::SetPrefableRealmOptions(JS::RealmOptions& options) {
StaticPrefs::javascript_options_writable_streams())
.setPropertyErrorMessageFixEnabled(sPropertyErrorMessageFixEnabled)
.setWeakRefsEnabled(GetWeakRefsEnabled())
.setIteratorHelpersEnabled(sIteratorHelpersEnabled);
.setIteratorHelpersEnabled(sIteratorHelpersEnabled)
#ifdef ENABLE_NEW_SET_METHODS
.setNewSetMethodsEnabled(enableNewSetMethods)
#endif
;
}
// Mirrored value of javascript.options.self_hosted.use_shared_memory.
@ -944,6 +948,11 @@ static void ReloadPrefsCallback(const char* pref, void* aXpccx) {
Preferences::GetBool(JS_OPTIONS_DOT_STR "experimental.iterator_helpers");
#endif
#ifdef ENABLE_NEW_SET_METHODS
bool enableNewSetMethods =
Preferences::GetBool(JS_OPTIONS_DOT_STR "experimental.new_set_methods");
#endif
#ifdef JS_GC_ZEAL
int32_t zeal = Preferences::GetInt(JS_OPTIONS_DOT_STR "gczeal", -1);
int32_t zeal_frequency = Preferences::GetInt(

Просмотреть файл

@ -35,6 +35,7 @@ prefs =
javascript.options.large_arraybuffers=true
javascript.options.experimental.ergonomic_brand_checks=true
javascript.options.experimental.enable_change_array_by_copy=false
javascript.options.experimental.enable_new_set_methods=false
[test_APIExposer.xhtml]
[test_bug361111.xhtml]

Просмотреть файл

@ -45,6 +45,7 @@ prefs =
javascript.options.experimental.ergonomic_brand_checks=true
javascript.options.experimental.top_level_await=true
javascript.options.experimental.enable_change_array_by_copy=false
javascript.options.experimental.enable_new_set_methods=false
[test_bug384632.html]
[test_bug390488.html]

Просмотреть файл

@ -6275,6 +6275,14 @@
value: false
mirror: always
#if defined(ENABLE_NEW_SET_METHODS)
# Experimental support for New Set methods
- name: javascript.options.experimental.enable_new_set_methods
type: bool
value: false
mirror: always
#endif
# Experimental support for Top-level Await in JavaScript.
- name: javascript.options.experimental.top_level_await
type: bool