summaryrefslogtreecommitdiffstats
path: root/js/src/jsfun.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsfun.cpp')
-rw-r--r--js/src/jsfun.cpp50
1 files changed, 39 insertions, 11 deletions
diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp
index c952441ad..9be02b217 100644
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1682,11 +1682,9 @@ const JSFunctionSpec js::function_methods[] = {
};
static bool
-FunctionConstructor(JSContext* cx, unsigned argc, Value* vp, GeneratorKind generatorKind,
+FunctionConstructor(JSContext* cx, const CallArgs& args, 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)) {
@@ -1803,16 +1801,23 @@ FunctionConstructor(JSContext* cx, unsigned argc, Value* vp, GeneratorKind gener
* 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 (isStarGenerator) {
+ 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) {
// 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());
@@ -1921,24 +1926,47 @@ FunctionConstructor(JSContext* cx, unsigned argc, Value* vp, GeneratorKind gener
bool
js::Function(JSContext* cx, unsigned argc, Value* vp)
{
- return FunctionConstructor(cx, argc, vp, NotGenerator, SyncFunction);
+ CallArgs args = CallArgsFromVp(argc, vp);
+ return FunctionConstructor(cx, args, NotGenerator, SyncFunction);
}
bool
js::Generator(JSContext* cx, unsigned argc, Value* vp)
{
- return FunctionConstructor(cx, argc, vp, StarGenerator, SyncFunction);
+ CallArgs args = CallArgsFromVp(argc, vp);
+ return FunctionConstructor(cx, args, StarGenerator, SyncFunction);
}
bool
js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
- if (!FunctionConstructor(cx, argc, vp, StarGenerator, AsyncFunction))
+
+ // 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))
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, WrapAsyncFunction(cx, unwrapped));
+ RootedObject wrapped(cx, WrapAsyncFunctionWithProto(cx, unwrapped, proto));
if (!wrapped)
return false;