mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 20:37:31 +09:00
Implement ES2024 grouping and resolver builtins
This commit is contained in:
parent
0d06f59dc1
commit
1e463a1d16
11 changed files with 313 additions and 25 deletions
|
|
@ -55,6 +55,49 @@ function MapForEach(callbackfn, thisArg = undefined) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ES2024
|
||||||
|
// Map.groupBy ( items, callbackfn )
|
||||||
|
function MapGroupBy(items, callbackfn) {
|
||||||
|
// Step 1.
|
||||||
|
RequireObjectCoercible(items);
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
if (!IsCallable(callbackfn))
|
||||||
|
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, callbackfn));
|
||||||
|
|
||||||
|
// Step 3.
|
||||||
|
var groups = std_Map_create();
|
||||||
|
|
||||||
|
// Step 4.
|
||||||
|
var k = 0;
|
||||||
|
|
||||||
|
// Steps 5-8.
|
||||||
|
for (var value of allowContentIter(items)) {
|
||||||
|
// Step 6.a.
|
||||||
|
if (k >= MAX_NUMERIC_INDEX)
|
||||||
|
ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
|
||||||
|
|
||||||
|
// Step 6.b.
|
||||||
|
var key = callContentFunction(callbackfn, undefined, value, k);
|
||||||
|
|
||||||
|
// Steps 6.c-d.
|
||||||
|
var elements;
|
||||||
|
if (callFunction(std_Map_has, groups, key)) {
|
||||||
|
elements = callFunction(std_Map_get, groups, key);
|
||||||
|
callFunction(std_Array_push, elements, value);
|
||||||
|
} else {
|
||||||
|
elements = [value];
|
||||||
|
callFunction(std_Map_set, groups, key, elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6.e.
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 9.
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
var iteratorTemp = { mapIterationResultPair : null };
|
var iteratorTemp = { mapIterationResultPair : null };
|
||||||
|
|
||||||
function MapIteratorNext() {
|
function MapIteratorNext() {
|
||||||
|
|
|
||||||
|
|
@ -332,9 +332,15 @@ const JSPropertySpec MapObject::staticProperties[] = {
|
||||||
JS_PS_END
|
JS_PS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const JSFunctionSpec MapObject::staticMethods[] = {
|
||||||
|
JS_SELF_HOSTED_FN("groupBy", "MapGroupBy", 2, 0),
|
||||||
|
JS_FS_END
|
||||||
|
};
|
||||||
|
|
||||||
static JSObject*
|
static JSObject*
|
||||||
InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSProtoKey key, Native construct,
|
InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSProtoKey key, Native construct,
|
||||||
const JSPropertySpec* properties, const JSFunctionSpec* methods,
|
const JSPropertySpec* properties, const JSFunctionSpec* methods,
|
||||||
|
const JSFunctionSpec* staticMethods,
|
||||||
const JSPropertySpec* staticProperties)
|
const JSPropertySpec* staticProperties)
|
||||||
{
|
{
|
||||||
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||||
|
|
@ -343,8 +349,13 @@ InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSPro
|
||||||
|
|
||||||
Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0));
|
Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0));
|
||||||
if (!ctor ||
|
if (!ctor ||
|
||||||
!JS_DefineProperties(cx, ctor, staticProperties) ||
|
!JS_DefineProperties(cx, ctor, staticProperties))
|
||||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (staticMethods && !JS_DefineFunctions(cx, ctor, staticMethods))
|
||||||
|
return nullptr;
|
||||||
|
if (!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||||
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
|
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
|
||||||
!GlobalObject::initBuiltinConstructor(cx, global, key, ctor, proto))
|
!GlobalObject::initBuiltinConstructor(cx, global, key, ctor, proto))
|
||||||
{
|
{
|
||||||
|
|
@ -359,7 +370,7 @@ MapObject::initClass(JSContext* cx, JSObject* obj)
|
||||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||||
RootedObject proto(cx,
|
RootedObject proto(cx,
|
||||||
InitClass(cx, global, &class_, JSProto_Map, construct, properties, methods,
|
InitClass(cx, global, &class_, JSProto_Map, construct, properties, methods,
|
||||||
staticProperties));
|
staticMethods, staticProperties));
|
||||||
if (proto) {
|
if (proto) {
|
||||||
// Define the "entries" method.
|
// Define the "entries" method.
|
||||||
JSFunction* fun = JS_DefineFunction(cx, proto, "entries", entries, 0, 0);
|
JSFunction* fun = JS_DefineFunction(cx, proto, "entries", entries, 0, 0);
|
||||||
|
|
@ -1084,7 +1095,7 @@ SetObject::initClass(JSContext* cx, JSObject* obj)
|
||||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||||
RootedObject proto(cx,
|
RootedObject proto(cx,
|
||||||
InitClass(cx, global, &class_, JSProto_Set, construct, properties, methods,
|
InitClass(cx, global, &class_, JSProto_Set, construct, properties, methods,
|
||||||
staticProperties));
|
nullptr, staticProperties));
|
||||||
if (proto) {
|
if (proto) {
|
||||||
// Define the "values" method.
|
// Define the "values" method.
|
||||||
JSFunction* fun = JS_DefineFunction(cx, proto, "values", values, 0, 0);
|
JSFunction* fun = JS_DefineFunction(cx, proto, "values", values, 0, 0);
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,10 @@ class MapObject : public NativeObject {
|
||||||
|
|
||||||
static MOZ_MUST_USE bool getKeysAndValuesInterleaved(JSContext* cx, HandleObject obj,
|
static MOZ_MUST_USE bool getKeysAndValuesInterleaved(JSContext* cx, HandleObject obj,
|
||||||
JS::MutableHandle<GCVector<JS::Value>> entries);
|
JS::MutableHandle<GCVector<JS::Value>> entries);
|
||||||
static MOZ_MUST_USE bool entries(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool entries(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool has(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool get(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
[[nodiscard]] static bool has(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
[[nodiscard]] static bool set(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MapObject* create(JSContext* cx, HandleObject proto = nullptr);
|
static MapObject* create(JSContext* cx, HandleObject proto = nullptr);
|
||||||
|
|
||||||
// Publicly exposed Map calls for JSAPI access (webidl maplike/setlike
|
// Publicly exposed Map calls for JSAPI access (webidl maplike/setlike
|
||||||
|
|
@ -137,6 +139,7 @@ class MapObject : public NativeObject {
|
||||||
|
|
||||||
static const JSPropertySpec properties[];
|
static const JSPropertySpec properties[];
|
||||||
static const JSFunctionSpec methods[];
|
static const JSFunctionSpec methods[];
|
||||||
|
static const JSFunctionSpec staticMethods[];
|
||||||
static const JSPropertySpec staticProperties[];
|
static const JSPropertySpec staticProperties[];
|
||||||
ValueMap* getData() { return static_cast<ValueMap*>(getPrivate()); }
|
ValueMap* getData() { return static_cast<ValueMap*>(getPrivate()); }
|
||||||
static ValueMap& extract(HandleObject o);
|
static ValueMap& extract(HandleObject o);
|
||||||
|
|
@ -150,22 +153,20 @@ class MapObject : public NativeObject {
|
||||||
|
|
||||||
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
static MOZ_MUST_USE bool iterator_impl(JSContext* cx, const CallArgs& args, IteratorKind kind);
|
||||||
|
|
||||||
static MOZ_MUST_USE bool size_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool size_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool size(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool size(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool get_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool get_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool get(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool has_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool has_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool set_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool set_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool delete_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool set(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool delete_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool keys_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool delete_(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool keys(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool keys_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool values_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool keys(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool values(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool values_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool entries_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool values(JSContext* cx, unsigned argc, Value* vp);
|
[[nodiscard]] static bool clear_impl(JSContext* cx, const CallArgs& args);
|
||||||
static MOZ_MUST_USE bool entries_impl(JSContext* cx, const CallArgs& args);
|
[[nodiscard]] static bool clear(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool clear_impl(JSContext* cx, const CallArgs& args);
|
|
||||||
static MOZ_MUST_USE bool clear(JSContext* cx, unsigned argc, Value* vp);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MapIteratorObject : public NativeObject
|
class MapIteratorObject : public NativeObject
|
||||||
|
|
|
||||||
|
|
@ -240,12 +240,16 @@ function ObjectGroupBy(items, callbackfn) {
|
||||||
// Steps 5-8.
|
// Steps 5-8.
|
||||||
for (var value of allowContentIter(items)) {
|
for (var value of allowContentIter(items)) {
|
||||||
// Step 6.a.
|
// Step 6.a.
|
||||||
var key = callContentFunction(callbackfn, undefined, value, k);
|
if (k >= MAX_NUMERIC_INDEX)
|
||||||
|
ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
|
||||||
|
|
||||||
// Step 6.b.
|
// Step 6.b.
|
||||||
|
var key = callContentFunction(callbackfn, undefined, value, k);
|
||||||
|
|
||||||
|
// Step 6.c.
|
||||||
key = ToPropertyKey(key);
|
key = ToPropertyKey(key);
|
||||||
|
|
||||||
// Steps 6.c-d.
|
// Steps 6.d-e.
|
||||||
var elements = groups[key];
|
var elements = groups[key];
|
||||||
if (elements === undefined) {
|
if (elements === undefined) {
|
||||||
_DefineDataProperty(groups, key, [value]);
|
_DefineDataProperty(groups, key, [value]);
|
||||||
|
|
@ -253,7 +257,7 @@ function ObjectGroupBy(items, callbackfn) {
|
||||||
callFunction(std_Array_push, elements, value);
|
callFunction(std_Array_push, elements, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6.e.
|
// Step 6.f.
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3673,6 +3673,48 @@ Promise_static_resolve(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ES2024
|
||||||
|
// Promise.withResolvers ( )
|
||||||
|
static bool
|
||||||
|
Promise_static_withResolvers(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
|
// Step 1.
|
||||||
|
if (!args.thisv().isObject()) {
|
||||||
|
ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, -1, args.thisv(), nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RootedObject C(cx, &args.thisv().toObject());
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
Rooted<PromiseCapability> capability(cx);
|
||||||
|
if (!NewPromiseCapability(cx, C, &capability, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Step 3.
|
||||||
|
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||||
|
if (!obj)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Steps 4-7.
|
||||||
|
RootedValue promise(cx, ObjectValue(*capability.promise()));
|
||||||
|
if (!::JS_DefineProperty(cx, obj, "promise", promise, JSPROP_ENUMERATE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RootedValue resolve(cx, ObjectValue(*capability.resolve()));
|
||||||
|
if (!::JS_DefineProperty(cx, obj, "resolve", resolve, JSPROP_ENUMERATE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RootedValue reject(cx, ObjectValue(*capability.reject()));
|
||||||
|
if (!::JS_DefineProperty(cx, obj, "reject", reject, JSPROP_ENUMERATE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Step 8.
|
||||||
|
args.rval().setObject(*obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unforgeable version of ES2016, 25.4.4.5, Promise.resolve.
|
* Unforgeable version of ES2016, 25.4.4.5, Promise.resolve.
|
||||||
*/
|
*/
|
||||||
|
|
@ -5180,6 +5222,7 @@ static const JSFunctionSpec promise_static_methods[] = {
|
||||||
JS_FN("race", Promise_static_race, 1, 0),
|
JS_FN("race", Promise_static_race, 1, 0),
|
||||||
JS_FN("reject", Promise_reject, 1, 0),
|
JS_FN("reject", Promise_reject, 1, 0),
|
||||||
JS_FN("resolve", Promise_static_resolve, 1, 0),
|
JS_FN("resolve", Promise_static_resolve, 1, 0),
|
||||||
|
JS_FN("withResolvers", Promise_static_withResolvers, 0, 0),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,82 @@ function String_repeat(count) {
|
||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ES2024
|
||||||
|
// String.prototype.isWellFormed ( )
|
||||||
|
function String_isWellFormed() {
|
||||||
|
// Steps 1-2.
|
||||||
|
RequireObjectCoercible(this);
|
||||||
|
var S = ToString(this);
|
||||||
|
|
||||||
|
// Step 3.
|
||||||
|
var length = S.length;
|
||||||
|
for (var k = 0; k < length; k++) {
|
||||||
|
var c = callFunction(std_String_charCodeAt, S, k);
|
||||||
|
if (c >= 0xD800 && c <= 0xDBFF) {
|
||||||
|
if (k + 1 >= length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var d = callFunction(std_String_charCodeAt, S, k + 1);
|
||||||
|
if (d < 0xDC00 || d > 0xDFFF)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
k++;
|
||||||
|
} else if (c >= 0xDC00 && c <= 0xDFFF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES2024
|
||||||
|
// String.prototype.toWellFormed ( )
|
||||||
|
function String_toWellFormed() {
|
||||||
|
// Steps 1-2.
|
||||||
|
RequireObjectCoercible(this);
|
||||||
|
var S = ToString(this);
|
||||||
|
|
||||||
|
// Step 3.
|
||||||
|
var length = S.length;
|
||||||
|
var result = "";
|
||||||
|
var copied = 0;
|
||||||
|
|
||||||
|
for (var k = 0; k < length; k++) {
|
||||||
|
var c = callFunction(std_String_charCodeAt, S, k);
|
||||||
|
var isUnpairedSurrogate = false;
|
||||||
|
|
||||||
|
if (c >= 0xD800 && c <= 0xDBFF) {
|
||||||
|
if (k + 1 < length) {
|
||||||
|
var d = callFunction(std_String_charCodeAt, S, k + 1);
|
||||||
|
if (d >= 0xDC00 && d <= 0xDFFF) {
|
||||||
|
k++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isUnpairedSurrogate = true;
|
||||||
|
} else if (c >= 0xDC00 && c <= 0xDFFF) {
|
||||||
|
isUnpairedSurrogate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUnpairedSurrogate) {
|
||||||
|
if (copied < k)
|
||||||
|
result += callFunction(String_substring, S, copied, k);
|
||||||
|
result += "\uFFFD";
|
||||||
|
copied = k + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copied === 0)
|
||||||
|
return S;
|
||||||
|
|
||||||
|
if (copied < length)
|
||||||
|
result += callFunction(String_substring, S, copied, length);
|
||||||
|
|
||||||
|
// Step 4.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// ES6 draft specification, section 21.1.3.27, version 2013-09-27.
|
// ES6 draft specification, section 21.1.3.27, version 2013-09-27.
|
||||||
function String_iterator() {
|
function String_iterator() {
|
||||||
RequireObjectCoercible(this);
|
RequireObjectCoercible(this);
|
||||||
|
|
|
||||||
|
|
@ -3344,6 +3344,8 @@ static const JSFunctionSpec string_methods[] = {
|
||||||
JS_SELF_HOSTED_FN("toLocaleUpperCase", "String_toLocaleUpperCase", 0,0),
|
JS_SELF_HOSTED_FN("toLocaleUpperCase", "String_toLocaleUpperCase", 0,0),
|
||||||
JS_SELF_HOSTED_FN("localeCompare", "String_localeCompare", 1,0),
|
JS_SELF_HOSTED_FN("localeCompare", "String_localeCompare", 1,0),
|
||||||
JS_SELF_HOSTED_FN("repeat", "String_repeat", 1,0),
|
JS_SELF_HOSTED_FN("repeat", "String_repeat", 1,0),
|
||||||
|
JS_SELF_HOSTED_FN("isWellFormed", "String_isWellFormed", 0,0),
|
||||||
|
JS_SELF_HOSTED_FN("toWellFormed", "String_toWellFormed", 0,0),
|
||||||
JS_FN("normalize", str_normalize, 0,0),
|
JS_FN("normalize", str_normalize, 0,0),
|
||||||
|
|
||||||
/* Perl-ish methods (search is actually Python-esque). */
|
/* Perl-ish methods (search is actually Python-esque). */
|
||||||
|
|
|
||||||
31
js/src/tests/non262/Promise/with-resolvers.js
Normal file
31
js/src/tests/non262/Promise/with-resolvers.js
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// |reftest| skip-if(!Promise.withResolvers)
|
||||||
|
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(Promise, "withResolvers");
|
||||||
|
assertEq(desc.enumerable, false);
|
||||||
|
assertEq(desc.configurable, true);
|
||||||
|
assertEq(desc.writable, true);
|
||||||
|
assertEq(Promise.withResolvers.length, 0);
|
||||||
|
assertEq(Promise.withResolvers.name, "withResolvers");
|
||||||
|
|
||||||
|
var capability = Promise.withResolvers();
|
||||||
|
assertEq(capability.promise instanceof Promise, true);
|
||||||
|
assertEq(typeof capability.resolve, "function");
|
||||||
|
assertEq(typeof capability.reject, "function");
|
||||||
|
assertEqArray(Object.keys(capability), ["promise", "resolve", "reject"]);
|
||||||
|
|
||||||
|
capability.resolve(42);
|
||||||
|
capability.promise.then(v => assertEq(v, 42));
|
||||||
|
|
||||||
|
class MyPromise extends Promise {}
|
||||||
|
var subCapability = Promise.withResolvers.call(MyPromise);
|
||||||
|
assertEq(subCapability.promise instanceof MyPromise, true);
|
||||||
|
subCapability.reject("rejected");
|
||||||
|
subCapability.promise.then(
|
||||||
|
() => { throw new Error("expected rejection"); },
|
||||||
|
reason => assertEq(reason, "rejected")
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => Promise.withResolvers.call({}), TypeError);
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(0, 0);
|
||||||
26
js/src/tests/non262/String/well-formed.js
Normal file
26
js/src/tests/non262/String/well-formed.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
// |reftest| skip-if(!String.prototype.isWellFormed||!String.prototype.toWellFormed)
|
||||||
|
|
||||||
|
assertEq("".isWellFormed(), true);
|
||||||
|
assertEq("abc".isWellFormed(), true);
|
||||||
|
assertEq("\uD83D\uDE00".isWellFormed(), true);
|
||||||
|
assertEq("\uD800".isWellFormed(), false);
|
||||||
|
assertEq("\uDC00".isWellFormed(), false);
|
||||||
|
assertEq("\uD800a".isWellFormed(), false);
|
||||||
|
assertEq("a\uDC00".isWellFormed(), false);
|
||||||
|
assertEq("\uD800\uD800\uDC00".isWellFormed(), false);
|
||||||
|
|
||||||
|
assertEq("abc".toWellFormed(), "abc");
|
||||||
|
assertEq("\uD83D\uDE00".toWellFormed(), "\uD83D\uDE00");
|
||||||
|
assertEq("\uD800".toWellFormed(), "\uFFFD");
|
||||||
|
assertEq("\uDC00".toWellFormed(), "\uFFFD");
|
||||||
|
assertEq("\uD800a\uDC00".toWellFormed(), "\uFFFDa\uFFFD");
|
||||||
|
assertEq("\uD800\uD800\uDC00".toWellFormed(), "\uFFFD\uD800\uDC00");
|
||||||
|
|
||||||
|
assertEq(String.prototype.isWellFormed.call(123), true);
|
||||||
|
assertEq(String.prototype.toWellFormed.call({ toString() { return "\uD800x"; } }), "\uFFFDx");
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => String.prototype.isWellFormed.call(null), TypeError);
|
||||||
|
assertThrowsInstanceOf(() => String.prototype.toWellFormed.call(undefined), TypeError);
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(0, 0);
|
||||||
34
js/src/tests/non262/collections/groupBy.js
Normal file
34
js/src/tests/non262/collections/groupBy.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
// |reftest| skip-if(!Object.groupBy||!Map.groupBy)
|
||||||
|
|
||||||
|
var objectGroups = Object.groupBy(["a", "bb", "c"], value => value.length);
|
||||||
|
assertEq(Object.getPrototypeOf(objectGroups), null);
|
||||||
|
assertEqArray(objectGroups["1"], ["a", "c"]);
|
||||||
|
assertEqArray(objectGroups["2"], ["bb"]);
|
||||||
|
|
||||||
|
var symbol = Symbol();
|
||||||
|
var symbolGroups = Object.groupBy([1, 2], value => value === 1 ? symbol : "__proto__");
|
||||||
|
assertEqArray(symbolGroups[symbol], [1]);
|
||||||
|
assertEqArray(symbolGroups.__proto__, [2]);
|
||||||
|
|
||||||
|
var indexes = [];
|
||||||
|
var mapGroups = Map.groupBy(["a", "bb", "c"], (value, index) => {
|
||||||
|
indexes.push(index);
|
||||||
|
return value.length;
|
||||||
|
});
|
||||||
|
assertEq(mapGroups instanceof Map, true);
|
||||||
|
assertEqArray(indexes, [0, 1, 2]);
|
||||||
|
assertEqArray(mapGroups.get(1), ["a", "c"]);
|
||||||
|
assertEqArray(mapGroups.get(2), ["bb"]);
|
||||||
|
|
||||||
|
var key = {};
|
||||||
|
var objectKeyGroups = Map.groupBy([1, 2], value => value === 1 ? key : NaN);
|
||||||
|
assertEqArray(objectKeyGroups.get(key), [1]);
|
||||||
|
assertEqArray(objectKeyGroups.get(NaN), [2]);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => Object.groupBy(null, x => x), TypeError);
|
||||||
|
assertThrowsInstanceOf(() => Map.groupBy(undefined, x => x), TypeError);
|
||||||
|
assertThrowsInstanceOf(() => Object.groupBy([], null), TypeError);
|
||||||
|
assertThrowsInstanceOf(() => Map.groupBy([], null), TypeError);
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(0, 0);
|
||||||
|
|
@ -270,6 +270,20 @@ intrinsic_GetBuiltinConstructor(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
intrinsic_NewMap(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
MOZ_ASSERT(args.length() == 0);
|
||||||
|
|
||||||
|
Rooted<MapObject*> map(cx, MapObject::create(cx));
|
||||||
|
if (!map)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
args.rval().setObject(*map);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp)
|
intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -2268,7 +2282,10 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||||
JS_INLINABLE_FN("std_Math_min", math_min, 2,0, MathMin),
|
JS_INLINABLE_FN("std_Math_min", math_min, 2,0, MathMin),
|
||||||
JS_INLINABLE_FN("std_Math_abs", math_abs, 1,0, MathAbs),
|
JS_INLINABLE_FN("std_Math_abs", math_abs, 1,0, MathAbs),
|
||||||
|
|
||||||
|
JS_FN("std_Map_create", intrinsic_NewMap, 0,0),
|
||||||
|
JS_FN("std_Map_get", MapObject::get, 1,0),
|
||||||
JS_FN("std_Map_has", MapObject::has, 1,0),
|
JS_FN("std_Map_has", MapObject::has, 1,0),
|
||||||
|
JS_FN("std_Map_set", MapObject::set, 2,0),
|
||||||
JS_FN("std_Map_iterator", MapObject::entries, 0,0),
|
JS_FN("std_Map_iterator", MapObject::entries, 0,0),
|
||||||
|
|
||||||
JS_FN("std_Number_valueOf", num_valueOf, 0,0),
|
JS_FN("std_Number_valueOf", num_valueOf, 0,0),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue