diff --git a/js/src/builtin/Intl.cpp b/js/src/builtin/Intl.cpp index f6e00018fca9d666d3fc1ec1fb6ccf88ca831627..e2c363f1a8ec3f031bf6c685f1da2dbab33d1560 100644 --- a/js/src/builtin/Intl.cpp +++ b/js/src/builtin/Intl.cpp @@ -768,54 +768,42 @@ static const JSFunctionSpec collator_methods[] = { }; /** - * 10.1.2 Intl.Collator([ locales [, options]]) - * - * ES2017 Intl draft rev 94045d234762ad107a3d09bb6f7381a65f1a2f9b + * Collator constructor. + * Spec: ECMAScript Internationalization API Specification, 10.1 */ static bool Collator(JSContext* cx, const CallArgs& args, bool construct) { RootedObject obj(cx); - // We're following ECMA-402 1st Edition when Collator is called because of - // backward compatibility issues. - // See https://github.com/tc39/ecma402/issues/57 if (!construct) { - // ES Intl 1st ed., 10.1.2.1 step 3 + // 10.1.2.1 step 3 JSObject* intl = cx->global()->getOrCreateIntlObject(cx); if (!intl) return false; RootedValue self(cx, args.thisv()); if (!self.isUndefined() && (!self.isObject() || self.toObject() != *intl)) { - // ES Intl 1st ed., 10.1.2.1 step 4 + // 10.1.2.1 step 4 obj = ToObject(cx, self); if (!obj) return false; - // ES Intl 1st ed., 10.1.2.1 step 5 + // 10.1.2.1 step 5 bool extensible; if (!IsExtensible(cx, obj, &extensible)) return false; if (!extensible) return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE); } else { - // ES Intl 1st ed., 10.1.2.1 step 3.a + // 10.1.2.1 step 3.a construct = true; } } - if (construct) { - // Steps 2-5 (Inlined 9.1.14, OrdinaryCreateFromConstructor). - RootedObject proto(cx); - if (args.isConstructing() && !GetPrototypeFromCallableConstructor(cx, args, &proto)) + // 10.1.3.1 paragraph 2 + RootedObject proto(cx, cx->global()->getOrCreateCollatorPrototype(cx)); + if (!proto) return false; - - if (!proto) { - proto = cx->global()->getOrCreateCollatorPrototype(cx); - if (!proto) - return false; - } - obj = NewObjectWithGivenProto(cx, &CollatorClass, proto); if (!obj) return false; @@ -823,13 +811,15 @@ Collator(JSContext* cx, const CallArgs& args, bool construct) obj->as<NativeObject>().setReservedSlot(UCOLLATOR_SLOT, PrivateValue(nullptr)); } + // 10.1.2.1 steps 1 and 2; 10.1.3.1 steps 1 and 2 RootedValue locales(cx, args.length() > 0 ? args[0] : UndefinedValue()); RootedValue options(cx, args.length() > 1 ? args[1] : UndefinedValue()); - // Step 6. + // 10.1.2.1 step 6; 10.1.3.1 step 3 if (!IntlInitialize(cx, obj, cx->names().InitializeCollator, locales, options)) return false; + // 10.1.2.1 steps 3.a and 7 args.rval().setObject(*obj); return true; } @@ -846,7 +836,6 @@ js::intl_Collator(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 2); - MOZ_ASSERT(!args.isConstructing()); // intl_Collator is an intrinsic for self-hosted JavaScript, so it cannot // be used with "new", but it still has to be treated as a constructor. return Collator(cx, args, true); @@ -1271,54 +1260,42 @@ static const JSFunctionSpec numberFormat_methods[] = { }; /** - * 11.2.1 Intl.NumberFormat([ locales [, options]]) - * - * ES2017 Intl draft rev 94045d234762ad107a3d09bb6f7381a65f1a2f9b + * NumberFormat constructor. + * Spec: ECMAScript Internationalization API Specification, 11.1 */ static bool NumberFormat(JSContext* cx, const CallArgs& args, bool construct) { RootedObject obj(cx); - // We're following ECMA-402 1st Edition when NumberFormat is called - // because of backward compatibility issues. - // See https://github.com/tc39/ecma402/issues/57 if (!construct) { - // ES Intl 1st ed., 11.1.2.1 step 3 + // 11.1.2.1 step 3 JSObject* intl = cx->global()->getOrCreateIntlObject(cx); if (!intl) return false; RootedValue self(cx, args.thisv()); if (!self.isUndefined() && (!self.isObject() || self.toObject() != *intl)) { - // ES Intl 1st ed., 11.1.2.1 step 4 + // 11.1.2.1 step 4 obj = ToObject(cx, self); if (!obj) return false; - // ES Intl 1st ed., 11.1.2.1 step 5 + // 11.1.2.1 step 5 bool extensible; if (!IsExtensible(cx, obj, &extensible)) return false; if (!extensible) return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE); } else { - // ES Intl 1st ed., 11.1.2.1 step 3.a + // 11.1.2.1 step 3.a construct = true; } } - if (construct) { - // Step 2 (Inlined 9.1.14, OrdinaryCreateFromConstructor). - RootedObject proto(cx); - if (args.isConstructing() && !GetPrototypeFromCallableConstructor(cx, args, &proto)) + // 11.1.3.1 paragraph 2 + RootedObject proto(cx, cx->global()->getOrCreateNumberFormatPrototype(cx)); + if (!proto) return false; - - if (!proto) { - proto = cx->global()->getOrCreateNumberFormatPrototype(cx); - if (!proto) - return false; - } - obj = NewObjectWithGivenProto(cx, &NumberFormatClass, proto); if (!obj) return false; @@ -1326,13 +1303,15 @@ NumberFormat(JSContext* cx, const CallArgs& args, bool construct) obj->as<NativeObject>().setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nullptr)); } + // 11.1.2.1 steps 1 and 2; 11.1.3.1 steps 1 and 2 RootedValue locales(cx, args.length() > 0 ? args[0] : UndefinedValue()); RootedValue options(cx, args.length() > 1 ? args[1] : UndefinedValue()); - // Step 3. + // 11.1.2.1 step 6; 11.1.3.1 step 3 if (!IntlInitialize(cx, obj, cx->names().InitializeNumberFormat, locales, options)) return false; + // 11.1.2.1 steps 3.a and 7 args.rval().setObject(*obj); return true; } @@ -1349,7 +1328,6 @@ js::intl_NumberFormat(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 2); - MOZ_ASSERT(!args.isConstructing()); // intl_NumberFormat is an intrinsic for self-hosted JavaScript, so it // cannot be used with "new", but it still has to be treated as a // constructor. @@ -1750,54 +1728,42 @@ static const JSFunctionSpec dateTimeFormat_methods[] = { }; /** - * 12.2.1 Intl.DateTimeFormat([ locales [, options]]) - * - * ES2017 Intl draft rev 94045d234762ad107a3d09bb6f7381a65f1a2f9b + * DateTimeFormat constructor. + * Spec: ECMAScript Internationalization API Specification, 12.1 */ static bool DateTimeFormat(JSContext* cx, const CallArgs& args, bool construct) { RootedObject obj(cx); - // We're following ECMA-402 1st Edition when DateTimeFormat is called - // because of backward compatibility issues. - // See https://github.com/tc39/ecma402/issues/57 if (!construct) { - // ES Intl 1st ed., 12.1.2.1 step 3 + // 12.1.2.1 step 3 JSObject* intl = cx->global()->getOrCreateIntlObject(cx); if (!intl) return false; RootedValue self(cx, args.thisv()); if (!self.isUndefined() && (!self.isObject() || self.toObject() != *intl)) { - // ES Intl 1st ed., 12.1.2.1 step 4 + // 12.1.2.1 step 4 obj = ToObject(cx, self); if (!obj) return false; - // ES Intl 1st ed., 12.1.2.1 step 5 + // 12.1.2.1 step 5 bool extensible; if (!IsExtensible(cx, obj, &extensible)) return false; if (!extensible) return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE); } else { - // ES Intl 1st ed., 12.1.2.1 step 3.a + // 12.1.2.1 step 3.a construct = true; } } - if (construct) { - // Step 2 (Inlined 9.1.14, OrdinaryCreateFromConstructor). - RootedObject proto(cx); - if (args.isConstructing() && !GetPrototypeFromCallableConstructor(cx, args, &proto)) + // 12.1.3.1 paragraph 2 + RootedObject proto(cx, cx->global()->getOrCreateDateTimeFormatPrototype(cx)); + if (!proto) return false; - - if (!proto) { - proto = cx->global()->getOrCreateDateTimeFormatPrototype(cx); - if (!proto) - return false; - } - obj = NewObjectWithGivenProto(cx, &DateTimeFormatClass, proto); if (!obj) return false; @@ -1805,13 +1771,15 @@ DateTimeFormat(JSContext* cx, const CallArgs& args, bool construct) obj->as<NativeObject>().setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(nullptr)); } + // 12.1.2.1 steps 1 and 2; 12.1.3.1 steps 1 and 2 RootedValue locales(cx, args.length() > 0 ? args[0] : UndefinedValue()); RootedValue options(cx, args.length() > 1 ? args[1] : UndefinedValue()); - // Step 3. + // 12.1.2.1 step 6; 12.1.3.1 step 3 if (!IntlInitialize(cx, obj, cx->names().InitializeDateTimeFormat, locales, options)) return false; + // 12.1.2.1 steps 3.a and 7 args.rval().setObject(*obj); return true; } @@ -1828,7 +1796,6 @@ js::intl_DateTimeFormat(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 2); - MOZ_ASSERT(!args.isConstructing()); // intl_DateTimeFormat is an intrinsic for self-hosted JavaScript, so it // cannot be used with "new", but it still has to be treated as a // constructor. diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index faabddd3215bdcc4ee17387689e9cb7ec14e2ad9..1c5374b664ea51d6b027ad435106fc1c8d5d2b68 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1630,9 +1630,11 @@ const JSFunctionSpec js::function_methods[] = { }; static bool -FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generatorKind, +FunctionConstructor(JSContext* cx, unsigned argc, Value* vp, GeneratorKind generatorKind, FunctionAsyncKind asyncKind) { + CallArgs args = CallArgsFromVp(argc, vp); + /* Block this call if security callbacks forbid it. */ Rooted<GlobalObject*> global(cx, &args.callee().global()); if (!GlobalObject::isRuntimeCodeGenEnabled(cx, global)) { @@ -1749,23 +1751,16 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator * and so would a call to f from another top-level's script or function. */ RootedAtom anonymousAtom(cx, cx->names().anonymous); - - // ES2017, draft rev 0f10dba4ad18de92d47d421f378233a2eae8f077 - // 19.2.1.1.1 Runtime Semantics: CreateDynamicFunction, step 24. RootedObject proto(cx); - if (!isAsync) { - if (!GetPrototypeFromCallableConstructor(cx, args, &proto)) - return false; - } - - // 19.2.1.1.1, step 4.d, use %Generator% as the fallback prototype. - // Also use %Generator% for the unwrapped function of async functions. - if (!proto && isStarGenerator) { + if (isStarGenerator) { // Unwrapped function of async function should use GeneratorFunction, // while wrapped function isn't generator. proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, global); if (!proto) return false; + } else { + if (!GetPrototypeFromCallableConstructor(cx, args, &proto)) + return false; } RootedObject globalLexical(cx, &global->lexicalEnvironment()); @@ -1874,47 +1869,24 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator bool js::Function(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - return FunctionConstructor(cx, args, NotGenerator, SyncFunction); + return FunctionConstructor(cx, argc, vp, NotGenerator, SyncFunction); } bool js::Generator(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - return FunctionConstructor(cx, args, StarGenerator, SyncFunction); + return FunctionConstructor(cx, argc, vp, StarGenerator, SyncFunction); } bool js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - - // Save the callee before its reset in FunctionConstructor(). - RootedObject newTarget(cx); - if (args.isConstructing()) - newTarget = &args.newTarget().toObject(); - else - newTarget = &args.callee(); - - if (!FunctionConstructor(cx, args, StarGenerator, AsyncFunction)) + if (!FunctionConstructor(cx, argc, vp, StarGenerator, AsyncFunction)) return false; - // ES2017, draft rev 0f10dba4ad18de92d47d421f378233a2eae8f077 - // 19.2.1.1.1 Runtime Semantics: CreateDynamicFunction, step 24. - RootedObject proto(cx); - if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) - return false; - - // 19.2.1.1.1, step 4.d, use %AsyncFunctionPrototype% as the fallback. - if (!proto) { - proto = GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global()); - if (!proto) - return false; - } - RootedFunction unwrapped(cx, &args.rval().toObject().as<JSFunction>()); - RootedObject wrapped(cx, WrapAsyncFunctionWithProto(cx, unwrapped, proto)); + RootedObject wrapped(cx, WrapAsyncFunction(cx, unwrapped)); if (!wrapped) return false; diff --git a/js/src/tests/Intl/Collator/construct-newtarget.js b/js/src/tests/Intl/Collator/construct-newtarget.js deleted file mode 100644 index 2bd04fe7c70127dfff33610626a181b0464dec11..0000000000000000000000000000000000000000 --- a/js/src/tests/Intl/Collator/construct-newtarget.js +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - - -// Test subclassing %Intl.Collator% works correctly. -class MyCollator extends Intl.Collator {} - -var obj = new MyCollator(); -assertEq(obj instanceof MyCollator, true); -assertEq(obj instanceof Intl.Collator, true); -assertEq(Object.getPrototypeOf(obj), MyCollator.prototype); - -obj = Reflect.construct(MyCollator, []); -assertEq(obj instanceof MyCollator, true); -assertEq(obj instanceof Intl.Collator, true); -assertEq(Object.getPrototypeOf(obj), MyCollator.prototype); - -obj = Reflect.construct(MyCollator, [], MyCollator); -assertEq(obj instanceof MyCollator, true); -assertEq(obj instanceof Intl.Collator, true); -assertEq(Object.getPrototypeOf(obj), MyCollator.prototype); - -obj = Reflect.construct(MyCollator, [], Intl.Collator); -assertEq(obj instanceof MyCollator, false); -assertEq(obj instanceof Intl.Collator, true); -assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); - - -// Set a different constructor as NewTarget. -obj = Reflect.construct(MyCollator, [], Array); -assertEq(obj instanceof MyCollator, false); -assertEq(obj instanceof Intl.Collator, false); -assertEq(obj instanceof Array, true); -assertEq(Object.getPrototypeOf(obj), Array.prototype); - -obj = Reflect.construct(Intl.Collator, [], Array); -assertEq(obj instanceof Intl.Collator, false); -assertEq(obj instanceof Array, true); -assertEq(Object.getPrototypeOf(obj), Array.prototype); - - -// The prototype defaults to %CollatorPrototype% if null. -function NewTargetNullPrototype() {} -NewTargetNullPrototype.prototype = null; - -obj = Reflect.construct(Intl.Collator, [], NewTargetNullPrototype); -assertEq(obj instanceof Intl.Collator, true); -assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); - -obj = Reflect.construct(MyCollator, [], NewTargetNullPrototype); -assertEq(obj instanceof MyCollator, false); -assertEq(obj instanceof Intl.Collator, true); -assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); - - -// "prototype" property is retrieved exactly once. -var trapLog = [], getLog = []; -var ProxiedConstructor = new Proxy(Intl.Collator, new Proxy({ - get(target, propertyKey, receiver) { - getLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -}, { - get(target, propertyKey, receiver) { - trapLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -})); - -obj = Reflect.construct(Intl.Collator, [], ProxiedConstructor); -assertEqArray(trapLog, ["get"]); -assertEqArray(getLog, ["prototype"]); -assertEq(obj instanceof Intl.Collator, true); -assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); - - -if (typeof reportCompare === "function") - reportCompare(0, 0); diff --git a/js/src/tests/Intl/DateTimeFormat/construct-newtarget.js b/js/src/tests/Intl/DateTimeFormat/construct-newtarget.js deleted file mode 100644 index 134b49a0c6026e542ac7705286de5909072d82f2..0000000000000000000000000000000000000000 --- a/js/src/tests/Intl/DateTimeFormat/construct-newtarget.js +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - - -// Test subclassing %Intl.DateTimeFormat% works correctly. -class MyDateTimeFormat extends Intl.DateTimeFormat {} - -var obj = new MyDateTimeFormat(); -assertEq(obj instanceof MyDateTimeFormat, true); -assertEq(obj instanceof Intl.DateTimeFormat, true); -assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype); - -obj = Reflect.construct(MyDateTimeFormat, []); -assertEq(obj instanceof MyDateTimeFormat, true); -assertEq(obj instanceof Intl.DateTimeFormat, true); -assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype); - -obj = Reflect.construct(MyDateTimeFormat, [], MyDateTimeFormat); -assertEq(obj instanceof MyDateTimeFormat, true); -assertEq(obj instanceof Intl.DateTimeFormat, true); -assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype); - -obj = Reflect.construct(MyDateTimeFormat, [], Intl.DateTimeFormat); -assertEq(obj instanceof MyDateTimeFormat, false); -assertEq(obj instanceof Intl.DateTimeFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); - - -// Set a different constructor as NewTarget. -obj = Reflect.construct(MyDateTimeFormat, [], Array); -assertEq(obj instanceof MyDateTimeFormat, false); -assertEq(obj instanceof Intl.DateTimeFormat, false); -assertEq(obj instanceof Array, true); -assertEq(Object.getPrototypeOf(obj), Array.prototype); - -obj = Reflect.construct(Intl.DateTimeFormat, [], Array); -assertEq(obj instanceof Intl.DateTimeFormat, false); -assertEq(obj instanceof Array, true); -assertEq(Object.getPrototypeOf(obj), Array.prototype); - - -// The prototype defaults to %DateTimeFormatPrototype% if null. -function NewTargetNullPrototype() {} -NewTargetNullPrototype.prototype = null; - -obj = Reflect.construct(Intl.DateTimeFormat, [], NewTargetNullPrototype); -assertEq(obj instanceof Intl.DateTimeFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); - -obj = Reflect.construct(MyDateTimeFormat, [], NewTargetNullPrototype); -assertEq(obj instanceof MyDateTimeFormat, false); -assertEq(obj instanceof Intl.DateTimeFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); - - -// "prototype" property is retrieved exactly once. -var trapLog = [], getLog = []; -var ProxiedConstructor = new Proxy(Intl.DateTimeFormat, new Proxy({ - get(target, propertyKey, receiver) { - getLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -}, { - get(target, propertyKey, receiver) { - trapLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -})); - -obj = Reflect.construct(Intl.DateTimeFormat, [], ProxiedConstructor); -assertEqArray(trapLog, ["get"]); -assertEqArray(getLog, ["prototype"]); -assertEq(obj instanceof Intl.DateTimeFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); - - -if (typeof reportCompare === "function") - reportCompare(0, 0); diff --git a/js/src/tests/Intl/NumberFormat/construct-newtarget.js b/js/src/tests/Intl/NumberFormat/construct-newtarget.js deleted file mode 100644 index dbdd75ac7d93ed016c158b534d853c87185af230..0000000000000000000000000000000000000000 --- a/js/src/tests/Intl/NumberFormat/construct-newtarget.js +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - - -// Test subclassing %Intl.NumberFormat% works correctly. -class MyNumberFormat extends Intl.NumberFormat {} - -var obj = new MyNumberFormat(); -assertEq(obj instanceof MyNumberFormat, true); -assertEq(obj instanceof Intl.NumberFormat, true); -assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype); - -obj = Reflect.construct(MyNumberFormat, []); -assertEq(obj instanceof MyNumberFormat, true); -assertEq(obj instanceof Intl.NumberFormat, true); -assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype); - -obj = Reflect.construct(MyNumberFormat, [], MyNumberFormat); -assertEq(obj instanceof MyNumberFormat, true); -assertEq(obj instanceof Intl.NumberFormat, true); -assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype); - -obj = Reflect.construct(MyNumberFormat, [], Intl.NumberFormat); -assertEq(obj instanceof MyNumberFormat, false); -assertEq(obj instanceof Intl.NumberFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); - - -// Set a different constructor as NewTarget. -obj = Reflect.construct(MyNumberFormat, [], Array); -assertEq(obj instanceof MyNumberFormat, false); -assertEq(obj instanceof Intl.NumberFormat, false); -assertEq(obj instanceof Array, true); -assertEq(Object.getPrototypeOf(obj), Array.prototype); - -obj = Reflect.construct(Intl.NumberFormat, [], Array); -assertEq(obj instanceof Intl.NumberFormat, false); -assertEq(obj instanceof Array, true); -assertEq(Object.getPrototypeOf(obj), Array.prototype); - - -// The prototype defaults to %NumberFormatPrototype% if null. -function NewTargetNullPrototype() {} -NewTargetNullPrototype.prototype = null; - -obj = Reflect.construct(Intl.NumberFormat, [], NewTargetNullPrototype); -assertEq(obj instanceof Intl.NumberFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); - -obj = Reflect.construct(MyNumberFormat, [], NewTargetNullPrototype); -assertEq(obj instanceof MyNumberFormat, false); -assertEq(obj instanceof Intl.NumberFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); - - -// "prototype" property is retrieved exactly once. -var trapLog = [], getLog = []; -var ProxiedConstructor = new Proxy(Intl.NumberFormat, new Proxy({ - get(target, propertyKey, receiver) { - getLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -}, { - get(target, propertyKey, receiver) { - trapLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -})); - -obj = Reflect.construct(Intl.NumberFormat, [], ProxiedConstructor); -assertEqArray(trapLog, ["get"]); -assertEqArray(getLog, ["prototype"]); -assertEq(obj instanceof Intl.NumberFormat, true); -assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); - - -if (typeof reportCompare === "function") - reportCompare(0, 0); diff --git a/js/src/tests/ecma_2017/AsyncFunctions/construct-newtarget.js b/js/src/tests/ecma_2017/AsyncFunctions/construct-newtarget.js deleted file mode 100644 index 7d75d0c939abab928d6745aa302cb21e30d78856..0000000000000000000000000000000000000000 --- a/js/src/tests/ecma_2017/AsyncFunctions/construct-newtarget.js +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - -const AsyncFunction = async function(){}.constructor; - - -// Test subclassing %AsyncFunction% works correctly. -class MyAsync extends AsyncFunction {} - -var fn = new MyAsync(); -assertEq(fn instanceof MyAsync, true); -assertEq(fn instanceof AsyncFunction, true); -assertEq(Object.getPrototypeOf(fn), MyAsync.prototype); - -fn = Reflect.construct(MyAsync, []); -assertEq(fn instanceof MyAsync, true); -assertEq(fn instanceof AsyncFunction, true); -assertEq(Object.getPrototypeOf(fn), MyAsync.prototype); - -fn = Reflect.construct(MyAsync, [], MyAsync); -assertEq(fn instanceof MyAsync, true); -assertEq(fn instanceof AsyncFunction, true); -assertEq(Object.getPrototypeOf(fn), MyAsync.prototype); - -fn = Reflect.construct(MyAsync, [], AsyncFunction); -assertEq(fn instanceof MyAsync, false); -assertEq(fn instanceof AsyncFunction, true); -assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype); - - -// Set a different constructor as NewTarget. -fn = Reflect.construct(MyAsync, [], Array); -assertEq(fn instanceof MyAsync, false); -assertEq(fn instanceof AsyncFunction, false); -assertEq(Object.getPrototypeOf(fn), Array.prototype); - -fn = Reflect.construct(AsyncFunction, [], Array); -assertEq(fn instanceof AsyncFunction, false); -assertEq(Object.getPrototypeOf(fn), Array.prototype); - - -// The prototype defaults to %AsyncFunctionPrototype% if null. -function NewTargetNullPrototype() {} -NewTargetNullPrototype.prototype = null; - -fn = Reflect.construct(AsyncFunction, [], NewTargetNullPrototype); -assertEq(fn instanceof AsyncFunction, true); -assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype); - -fn = Reflect.construct(MyAsync, [], NewTargetNullPrototype); -assertEq(fn instanceof MyAsync, false); -assertEq(fn instanceof AsyncFunction, true); -assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype); - - -// "prototype" property is retrieved exactly once. -var trapLog = [], getLog = []; -var ProxiedConstructor = new Proxy(AsyncFunction, new Proxy({ - get(target, propertyKey, receiver) { - getLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -}, { - get(target, propertyKey, receiver) { - trapLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -})); - -fn = Reflect.construct(AsyncFunction, [], ProxiedConstructor); -assertEqArray(trapLog, ["get"]); -assertEqArray(getLog, ["prototype"]); -assertEq(fn instanceof AsyncFunction, true); -assertEq(Object.getPrototypeOf(fn), AsyncFunction.prototype); - - -if (typeof reportCompare === "function") - reportCompare(0, 0); diff --git a/js/src/tests/ecma_2017/AsyncFunctions/subclass.js b/js/src/tests/ecma_2017/AsyncFunctions/subclass.js deleted file mode 100644 index da20ab19b87157ed85bf57cd551391f92e1e1764..0000000000000000000000000000000000000000 --- a/js/src/tests/ecma_2017/AsyncFunctions/subclass.js +++ /dev/null @@ -1,31 +0,0 @@ -// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - -const AsyncFunction = async function(){}.constructor; - -class MyAsync extends AsyncFunction {} - -// MyGen inherits from %AsyncFunction%. -assertEq(Object.getPrototypeOf(MyAsync), AsyncFunction); - -// MyGen.prototype inherits from %AsyncFunctionPrototype%. -assertEq(Object.getPrototypeOf(MyAsync.prototype), AsyncFunction.prototype); - -var fn = new MyAsync("return await 'ok';"); - -// fn inherits from MyAsync.prototype. -assertEq(Object.getPrototypeOf(fn), MyAsync.prototype); - -// Ensure the new async function can be executed. -var promise = fn(); - -// promise inherits from %Promise.prototype%. -assertEq(Object.getPrototypeOf(promise), Promise.prototype); - -// Computes the expected result. -assertEventuallyEq(promise, "ok"); - -if (typeof reportCompare === "function") - reportCompare(0, 0); diff --git a/js/src/tests/ecma_6/Generators/construct-newtarget.js b/js/src/tests/ecma_6/Generators/construct-newtarget.js deleted file mode 100644 index f2087852b0dc4dc77b1b82d9a494f4c9db3d3ab3..0000000000000000000000000000000000000000 --- a/js/src/tests/ecma_6/Generators/construct-newtarget.js +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - -const GeneratorFunction = function*(){}.constructor; - - -// Test subclassing %GeneratorFunction% works correctly. -class MyGenerator extends GeneratorFunction {} - -var fn = new MyGenerator(); -assertEq(fn instanceof MyGenerator, true); -assertEq(fn instanceof GeneratorFunction, true); -assertEq(Object.getPrototypeOf(fn), MyGenerator.prototype); - -fn = Reflect.construct(MyGenerator, []); -assertEq(fn instanceof MyGenerator, true); -assertEq(fn instanceof GeneratorFunction, true); -assertEq(Object.getPrototypeOf(fn), MyGenerator.prototype); - -fn = Reflect.construct(MyGenerator, [], MyGenerator); -assertEq(fn instanceof MyGenerator, true); -assertEq(fn instanceof GeneratorFunction, true); -assertEq(Object.getPrototypeOf(fn), MyGenerator.prototype); - -fn = Reflect.construct(MyGenerator, [], GeneratorFunction); -assertEq(fn instanceof MyGenerator, false); -assertEq(fn instanceof GeneratorFunction, true); -assertEq(Object.getPrototypeOf(fn), GeneratorFunction.prototype); - - -// Set a different constructor as NewTarget. -fn = Reflect.construct(MyGenerator, [], Array); -assertEq(fn instanceof MyGenerator, false); -assertEq(fn instanceof GeneratorFunction, false); -assertEq(Object.getPrototypeOf(fn), Array.prototype); - -fn = Reflect.construct(GeneratorFunction, [], Array); -assertEq(fn instanceof GeneratorFunction, false); -assertEq(Object.getPrototypeOf(fn), Array.prototype); - - -// The prototype defaults to %GeneratorFunctionPrototype% if null. -function NewTargetNullPrototype() {} -NewTargetNullPrototype.prototype = null; - -fn = Reflect.construct(GeneratorFunction, [], NewTargetNullPrototype); -assertEq(fn instanceof GeneratorFunction, true); -assertEq(Object.getPrototypeOf(fn), GeneratorFunction.prototype); - -fn = Reflect.construct(MyGenerator, [], NewTargetNullPrototype); -assertEq(fn instanceof MyGenerator, false); -assertEq(fn instanceof GeneratorFunction, true); -assertEq(Object.getPrototypeOf(fn), GeneratorFunction.prototype); - - -// "prototype" property is retrieved exactly once. -var trapLog = [], getLog = []; -var ProxiedConstructor = new Proxy(GeneratorFunction, new Proxy({ - get(target, propertyKey, receiver) { - getLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -}, { - get(target, propertyKey, receiver) { - trapLog.push(propertyKey); - return Reflect.get(target, propertyKey, receiver); - } -})); - -fn = Reflect.construct(GeneratorFunction, [], ProxiedConstructor); -assertEqArray(trapLog, ["get"]); -assertEqArray(getLog, ["prototype"]); -assertEq(fn instanceof GeneratorFunction, true); -assertEq(Object.getPrototypeOf(fn), GeneratorFunction.prototype); - - -if (typeof reportCompare === "function") - reportCompare(0, 0); diff --git a/js/src/tests/ecma_6/Generators/subclass.js b/js/src/tests/ecma_6/Generators/subclass.js deleted file mode 100644 index f93f4df4dba701235bfbad101875a1f32bbb6273..0000000000000000000000000000000000000000 --- a/js/src/tests/ecma_6/Generators/subclass.js +++ /dev/null @@ -1,33 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - -const GeneratorFunction = function*(){}.constructor; - -class MyGen extends GeneratorFunction {} - -// MyGen inherits from %GeneratorFunction%. -assertEq(Object.getPrototypeOf(MyGen), GeneratorFunction); - -// MyGen.prototype inherits from %Generator%. -assertEq(Object.getPrototypeOf(MyGen.prototype), GeneratorFunction.prototype); - -var fn = new MyGen("yield* [1, 2, 3]"); - -// fn inherits from MyGen.prototype. -assertEq(Object.getPrototypeOf(fn), MyGen.prototype); - -// fn.prototype inherits from %GeneratorPrototype%. -assertEq(Object.getPrototypeOf(fn.prototype), GeneratorFunction.prototype.prototype); - -// Ensure the new generator function can be executed. -var it = fn(); - -// it inherits from fn.prototype. -assertEq(Object.getPrototypeOf(it), fn.prototype); - -// Computes the expected result. -assertEqArray([...it], [1, 2, 3]); - -if (typeof reportCompare === "function") - reportCompare(0, 0); diff --git a/js/src/vm/AsyncFunction.cpp b/js/src/vm/AsyncFunction.cpp index 1b81fda97b404709ed90c64313c570e223bc9351..ab69afd872f2263576a01d01bbd22305fa031cb6 100644 --- a/js/src/vm/AsyncFunction.cpp +++ b/js/src/vm/AsyncFunction.cpp @@ -110,15 +110,18 @@ WrappedAsyncFunction(JSContext* cx, unsigned argc, Value* vp) // the async function's body, replacing `await` with `yield`. `wrapped` is a // function that is visible to the outside, and handles yielded values. JSObject* -js::WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto) +js::WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped) { MOZ_ASSERT(unwrapped->isStarGenerator()); - MOZ_ASSERT(proto, "We need an explicit prototype to avoid the default" - "%FunctionPrototype% fallback in NewFunctionWithProto()."); // Create a new function with AsyncFunctionPrototype, reusing the name and // the length of `unwrapped`. + // Step 1. + RootedObject proto(cx, GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global())); + if (!proto) + return nullptr; + RootedAtom funName(cx, unwrapped->name()); uint16_t length; if (!unwrapped->getLength(cx, &length)) @@ -141,16 +144,6 @@ js::WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleOb return wrapped; } -JSObject* -js::WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped) -{ - RootedObject proto(cx, GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global())); - if (!proto) - return nullptr; - - return WrapAsyncFunctionWithProto(cx, unwrapped, proto); -} - enum class ResumeKind { Normal, Throw diff --git a/js/src/vm/AsyncFunction.h b/js/src/vm/AsyncFunction.h index d7f2c13117b3625d70882f93b9fff2ecc050e7b0..ddf81a177486a0b3ab9ff3c02117c3686f031a3c 100644 --- a/js/src/vm/AsyncFunction.h +++ b/js/src/vm/AsyncFunction.h @@ -21,9 +21,6 @@ GetUnwrappedAsyncFunction(JSFunction* wrapped); bool IsWrappedAsyncFunction(JSFunction* fun); -JSObject* -WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto); - JSObject* WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped);