From 679dffd17a54dc81428ddc09d6bb2b9bc4f820fb Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 9 Nov 2016 03:27:49 +0900 Subject: [PATCH] Bug 1314055 - Part 1: Port async/await implementation from self-hosted JS to C++. r=till --- js/src/builtin/AsyncFunctions.js | 47 ----- js/src/builtin/SelfHostingDefines.h | 3 - js/src/frontend/BytecodeEmitter.cpp | 24 +-- js/src/jsfun.cpp | 13 +- js/src/moz.build | 1 - js/src/vm/AsyncFunction.cpp | 305 +++++++++++++++++++++++----- js/src/vm/AsyncFunction.h | 9 +- js/src/vm/CommonPropertyNames.h | 3 +- js/src/vm/Interpreter.cpp | 14 +- js/src/vm/Opcodes.h | 10 +- js/src/vm/SelfHosting.cpp | 20 -- 11 files changed, 293 insertions(+), 156 deletions(-) delete mode 100644 js/src/builtin/AsyncFunctions.js diff --git a/js/src/builtin/AsyncFunctions.js b/js/src/builtin/AsyncFunctions.js deleted file mode 100644 index 220faa672213..000000000000 --- a/js/src/builtin/AsyncFunctions.js +++ /dev/null @@ -1,47 +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/. */ - -// Called when creating async function. -// See the comment for js::CreateAsyncFunction what unwrapped, wrapped and the -// return value are. -function AsyncFunction_wrap(unwrapped) { - var wrapper = function() { - // The try block is required to handle throws in default arguments properly. - try { - return AsyncFunction_start(callFunction(std_Function_apply, unwrapped, this, arguments)); - } catch (e) { - var promiseCtor = GetBuiltinConstructor('Promise'); - return callFunction(Promise_static_reject, promiseCtor, e); - } - }; - return CreateAsyncFunction(wrapper, unwrapped); -} - -function AsyncFunction_start(generator) { - return AsyncFunction_resume(generator, undefined, generator.next); -} - -function AsyncFunction_resume(gen, v, method) { - var promiseCtor = GetBuiltinConstructor('Promise'); - let result; - try { - // get back into async function, run to next await point - result = callFunction(method, gen, v); - } catch (exc) { - // The async function itself failed. - return callFunction(Promise_static_reject, promiseCtor, exc); - } - - if (result.done) - return callFunction(Promise_static_resolve, promiseCtor, result.value); - - // If we get here, `await` occurred. `gen` is paused at a yield point. - return callFunction(Promise_then, - callFunction(Promise_static_resolve, promiseCtor, result.value), - function(val) { - return AsyncFunction_resume(gen, val, gen.next); - }, function (err) { - return AsyncFunction_resume(gen, err, gen.throw); - }); -} diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h index ff4e36b06ecc..b57c172691d5 100644 --- a/js/src/builtin/SelfHostingDefines.h +++ b/js/src/builtin/SelfHostingDefines.h @@ -93,9 +93,6 @@ #define REGEXP_STICKY_FLAG 0x08 #define REGEXP_UNICODE_FLAG 0x10 -#define ASYNC_WRAPPED_SLOT 1 -#define ASYNC_UNWRAPPED_SLOT 1 - #define MODULE_OBJECT_ENVIRONMENT_SLOT 2 #define MODULE_STATE_FAILED 0 diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index e139f51e6563..a1384e115b76 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -7135,17 +7135,16 @@ BytecodeEmitter::emitAsyncWrapperLambda(unsigned index, bool isArrow) { } bool -BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow) { +BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isArrow) +{ // needsHomeObject can be true for propertyList for extended class. // In that case push both unwrapped and wrapped function, in order to // initialize home object of unwrapped function, and set wrapped function // as a property. // // lambda // unwrapped - // getintrinsic // unwrapped AsyncFunction_wrap - // undefined // unwrapped AsyncFunction_wrap undefined - // dupat 2 // unwrapped AsyncFunction_wrap undefined unwrapped - // call 1 // unwrapped wrapped + // dup // unwrapped unwrapped + // toasync // unwrapped wrapped // // Emitted code is surrounded by the following code. // @@ -7162,22 +7161,13 @@ BytecodeEmitter::emitAsyncWrapper(unsigned index, bool needsHomeObject, bool isA // pop // classObj classCtor classProto // // needsHomeObject is false for other cases, push wrapped function only. - if (needsHomeObject) { - if (!emitAsyncWrapperLambda(index, isArrow)) - return false; - } - if (!emitAtomOp(cx->names().AsyncFunction_wrap, JSOP_GETINTRINSIC)) - return false; - if (!emit1(JSOP_UNDEFINED)) + if (!emitAsyncWrapperLambda(index, isArrow)) return false; if (needsHomeObject) { - if (!emitDupAt(2)) - return false; - } else { - if (!emitAsyncWrapperLambda(index, isArrow)) + if (!emit1(JSOP_DUP)) return false; } - if (!emitCall(JSOP_CALL, 1)) + if (!emit1(JSOP_TOASYNC)) return false; return true; } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 04d6ed77f859..2c8d637d268a 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -991,7 +991,7 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool lambdaParen) if (IsAsmJSFunction(fun)) return AsmJSFunctionToString(cx, fun); - if (IsWrappedAsyncFunction(cx, fun)) { + if (IsWrappedAsyncFunction(fun)) { RootedFunction unwrapped(cx, GetUnwrappedAsyncFunction(fun)); return FunctionToString(cx, unwrapped, lambdaParen); } @@ -1930,10 +1930,13 @@ js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp) if (!FunctionConstructor(cx, argc, vp, StarGenerator, AsyncFunction)) return false; - FixedInvokeArgs<1> args2(cx); - args2[0].set(args.rval()); - return CallSelfHostedFunction(cx, cx->names().AsyncFunction_wrap, - NullHandleValue, args2, args.rval()); + RootedFunction unwrapped(cx, &args.rval().toObject().as()); + RootedObject wrapped(cx, WrapAsyncFunction(cx, unwrapped)); + if (!wrapped) + return false; + + args.rval().setObject(*wrapped); + return true; } bool diff --git a/js/src/moz.build b/js/src/moz.build index 72c63a56124b..35e1ed71b4dd 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -750,7 +750,6 @@ selfhosted.inputs = [ 'builtin/SelfHostingDefines.h', 'builtin/Utilities.js', 'builtin/Array.js', - 'builtin/AsyncFunctions.js', 'builtin/Classes.js', 'builtin/Date.js', 'builtin/Error.js', diff --git a/js/src/vm/AsyncFunction.cpp b/js/src/vm/AsyncFunction.cpp index a0a3cfac0763..d8192a293e9b 100644 --- a/js/src/vm/AsyncFunction.cpp +++ b/js/src/vm/AsyncFunction.cpp @@ -8,8 +8,9 @@ #include "jscompartment.h" -#include "builtin/SelfHostingDefines.h" +#include "builtin/Promise.h" #include "vm/GlobalObject.h" +#include "vm/Interpreter.h" #include "vm/SelfHosting.h" using namespace js; @@ -46,73 +47,267 @@ GlobalObject::initAsyncFunction(JSContext* cx, Handle global) return true; } +static bool AsyncFunctionStart(JSContext* cx, HandleValue generatorVal, MutableHandleValue rval); + +#define UNWRAPPED_ASYNC_WRAPPED_SLOT 1 +#define WRAPPED_ASYNC_UNWRAPPED_SLOT 0 + +// Async Functions proposal 1.1.8 and 1.2.14. +static bool +WrappedAsyncFunction(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + RootedFunction wrapped(cx, &args.callee().as()); + RootedValue unwrappedVal(cx, wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT)); + RootedFunction unwrapped(cx, &unwrappedVal.toObject().as()); + RootedValue thisValue(cx, args.thisv()); + + // Step 2. + // Also does a part of 2.2 steps 1-2. + RootedValue generatorVal(cx); + InvokeArgs args2(cx); + if (!args2.init(cx, argc)) + return false; + for (size_t i = 0, len = argc; i < len; i++) + args2[i].set(args[i]); + if (Call(cx, unwrappedVal, thisValue, args2, &generatorVal)) { + // Steps 3, 5. + return AsyncFunctionStart(cx, generatorVal, args.rval()); + } + + // Step 4. + RootedValue exc(cx); + if (!GetAndClearException(cx, &exc)) + return false; + RootedObject rejectPromise(cx, PromiseObject::unforgeableReject(cx, exc)); + if (!rejectPromise) + return false; + + // Step 5. + args.rval().setObject(*rejectPromise); + return true; +} + +// Async Functions proposal 2.1 steps 1, 3 (partially). +// In the spec it creates a function, but we create 2 functions `unwrapped` and +// `wrapped`. `unwrapped` is a generator that corresponds to +// 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::WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped) +{ + MOZ_ASSERT(unwrapped->isStarGenerator()); + + // 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)) + return nullptr; + + // Steps 3 (partially). + RootedFunction wrapped(cx, NewFunctionWithProto(cx, WrappedAsyncFunction, length, + JSFunction::NATIVE_FUN, nullptr, + funName, proto, + AllocKind::FUNCTION_EXTENDED, + TenuredObject)); + if (!wrapped) + return nullptr; + + // Link them to each other to make GetWrappedAsyncFunction and + // GetUnwrappedAsyncFunction work. + unwrapped->setExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT, ObjectValue(*wrapped)); + wrapped->setExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT, ObjectValue(*unwrapped)); + + return wrapped; +} + +// Async Functions proposal 2.2 steps 3.f, 3.g. +static bool +AsyncFunctionThrown(JSContext* cx, MutableHandleValue rval) +{ + // Step 3.f. + RootedValue exc(cx); + if (!GetAndClearException(cx, &exc)) + return false; + + RootedObject rejectPromise(cx, PromiseObject::unforgeableReject(cx, exc)); + if (!rejectPromise) + return false; + + // Step 3.g. + rval.setObject(*rejectPromise); + return true; +} + +// Async Functions proposal 2.2 steps 3.d-e, 3.g. +static bool +AsyncFunctionReturned(JSContext* cx, HandleValue value, MutableHandleValue rval) +{ + // Steps 3.d-e. + RootedObject resolveObj(cx, PromiseObject::unforgeableResolve(cx, value)); + if (!resolveObj) + return false; + + // Step 3.g. + rval.setObject(*resolveObj); + return true; +} + +static bool AsyncFunctionAwait(JSContext* cx, HandleValue generatorVal, HandleValue value, + MutableHandleValue rval); + +enum class ResumeKind { + Normal, + Throw +}; + +// Async Functions proposal 2.2 steps 3-8, 2.4 steps 2-7, 2.5 steps 2-7. +static bool +AsyncFunctionResume(JSContext* cx, HandleValue generatorVal, ResumeKind kind, + HandleValue valueOrReason, MutableHandleValue rval) +{ + // Execution context switching is handled in generator. + HandlePropertyName funName = kind == ResumeKind::Normal + ? cx->names().StarGeneratorNext + : cx->names().StarGeneratorThrow; + FixedInvokeArgs<1> args(cx); + args[0].set(valueOrReason); + RootedValue result(cx); + if (!CallSelfHostedFunction(cx, funName, generatorVal, args, &result)) + return AsyncFunctionThrown(cx, rval); + + RootedObject resultObj(cx, &result.toObject()); + RootedValue doneVal(cx); + RootedValue value(cx); + if (!GetProperty(cx, resultObj, resultObj, cx->names().done, &doneVal)) + return false; + if (!GetProperty(cx, resultObj, resultObj, cx->names().value, &value)) + return false; + + if (doneVal.toBoolean()) + return AsyncFunctionReturned(cx, value, rval); + + return AsyncFunctionAwait(cx, generatorVal, value, rval); +} + +// Async Functions proposal 2.2 steps 3-8. +static bool +AsyncFunctionStart(JSContext* cx, HandleValue generatorVal, MutableHandleValue rval) +{ + return AsyncFunctionResume(cx, generatorVal, ResumeKind::Normal, UndefinedHandleValue, rval); +} + +#define AWAITED_FUNC_GENERATOR_SLOT 0 + +static bool AsyncFunctionAwaitedFulfilled(JSContext* cx, unsigned argc, Value* vp); +static bool AsyncFunctionAwaitedRejected(JSContext* cx, unsigned argc, Value* vp); + +// Async Functions proposal 2.3 steps 1-8. +static bool +AsyncFunctionAwait(JSContext* cx, HandleValue generatorVal, HandleValue value, + MutableHandleValue rval) +{ + // Step 1 (implicit). + + // Steps 2-3. + RootedObject resolveObj(cx, PromiseObject::unforgeableResolve(cx, value)); + if (!resolveObj) + return false; + + Rooted resolvePromise(cx, resolveObj.as()); + + // Step 4. + RootedAtom funName(cx, cx->names().empty); + RootedFunction onFulfilled(cx, NewNativeFunction(cx, AsyncFunctionAwaitedFulfilled, 1, + funName, gc::AllocKind::FUNCTION_EXTENDED, + GenericObject)); + if (!onFulfilled) + return false; + + // Step 5. + RootedFunction onRejected(cx, NewNativeFunction(cx, AsyncFunctionAwaitedRejected, 1, + funName, gc::AllocKind::FUNCTION_EXTENDED, + GenericObject)); + if (!onRejected) + return false; + + // Step 6. + onFulfilled->setExtendedSlot(AWAITED_FUNC_GENERATOR_SLOT, generatorVal); + onRejected->setExtendedSlot(AWAITED_FUNC_GENERATOR_SLOT, generatorVal); + + // Step 8. + RootedValue onFulfilledVal(cx, ObjectValue(*onFulfilled)); + RootedValue onRejectedVal(cx, ObjectValue(*onRejected)); + RootedObject resultPromise(cx, OriginalPromiseThen(cx, resolvePromise, onFulfilledVal, + onRejectedVal)); + if (!resultPromise) + return false; + + rval.setObject(*resultPromise); + return true; +} + +// Async Functions proposal 2.4. +static bool +AsyncFunctionAwaitedFulfilled(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 1); + + RootedFunction F(cx, &args.callee().as()); + RootedValue value(cx, args[0]); + + // Step 1. + RootedValue generatorVal(cx, F->getExtendedSlot(AWAITED_FUNC_GENERATOR_SLOT)); + + // Steps 2-7. + return AsyncFunctionResume(cx, generatorVal, ResumeKind::Normal, value, args.rval()); +} + +// Async Functions proposal 2.5. +static bool +AsyncFunctionAwaitedRejected(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 1); + + RootedFunction F(cx, &args.callee().as()); + RootedValue reason(cx, args[0]); + + // Step 1. + RootedValue generatorVal(cx, F->getExtendedSlot(AWAITED_FUNC_GENERATOR_SLOT)); + + // Step 2-7. + return AsyncFunctionResume(cx, generatorVal, ResumeKind::Throw, reason, args.rval()); +} + JSFunction* js::GetWrappedAsyncFunction(JSFunction* unwrapped) { MOZ_ASSERT(unwrapped->isAsync()); - return &unwrapped->getExtendedSlot(ASYNC_WRAPPED_SLOT).toObject().as(); + return &unwrapped->getExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT).toObject().as(); } JSFunction* -js::GetUnwrappedAsyncFunction(JSFunction* wrapper) +js::GetUnwrappedAsyncFunction(JSFunction* wrapped) { - JSFunction* unwrapped = &wrapper->getExtendedSlot(ASYNC_UNWRAPPED_SLOT).toObject().as(); + MOZ_ASSERT(IsWrappedAsyncFunction(wrapped)); + JSFunction* unwrapped = &wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT).toObject().as(); MOZ_ASSERT(unwrapped->isAsync()); return unwrapped; } bool -js::IsWrappedAsyncFunction(JSContext* cx, JSFunction* wrapper) +js::IsWrappedAsyncFunction(JSFunction* fun) { - return IsSelfHostedFunctionWithName(wrapper, cx->names().AsyncWrapped); + return fun->maybeNative() == WrappedAsyncFunction; } -bool -js::CreateAsyncFunction(JSContext* cx, HandleFunction wrapper, HandleFunction unwrapped, - MutableHandleFunction result) -{ - // Create a new function with AsyncFunctionPrototype, reusing the script - // and the environment of `wrapper` function, and the name and the length - // of `unwrapped` function. - RootedObject proto(cx, GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global())); - RootedObject scope(cx, wrapper->environment()); - RootedAtom atom(cx, unwrapped->name()); - RootedFunction wrapped(cx, NewFunctionWithProto(cx, nullptr, 0, - JSFunction::INTERPRETED_LAMBDA, - scope, atom, proto, - AllocKind::FUNCTION_EXTENDED, TenuredObject)); - if (!wrapped) - return false; - - wrapped->initScript(wrapper->nonLazyScript()); - - // Link them each other to make GetWrappedAsyncFunction and - // GetUnwrappedAsyncFunction work. - unwrapped->setExtendedSlot(ASYNC_WRAPPED_SLOT, ObjectValue(*wrapped)); - wrapped->setExtendedSlot(ASYNC_UNWRAPPED_SLOT, ObjectValue(*unwrapped)); - - // The script of `wrapper` is self-hosted, so `wrapped` should also be - // set as self-hosted function. - wrapped->setIsSelfHostedBuiltin(); - - // Set LAZY_FUNCTION_NAME_SLOT to "AsyncWrapped" to make it detectable in - // IsWrappedAsyncFunction. - wrapped->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(cx->names().AsyncWrapped)); - - // The length of the script of `wrapper` is different than the length of - // `unwrapped`. We should set actual length as resolved length, to avoid - // using the length of the script. - uint16_t length; - if (!unwrapped->getLength(cx, &length)) - return false; - - RootedValue lengthValue(cx, NumberValue(length)); - if (!DefineProperty(cx, wrapped, cx->names().length, lengthValue, - nullptr, nullptr, JSPROP_READONLY)) - { - return false; - } - - result.set(wrapped); - return true; -} diff --git a/js/src/vm/AsyncFunction.h b/js/src/vm/AsyncFunction.h index 62fce6aa5ac8..eb7a08412cdf 100644 --- a/js/src/vm/AsyncFunction.h +++ b/js/src/vm/AsyncFunction.h @@ -16,14 +16,13 @@ JSFunction* GetWrappedAsyncFunction(JSFunction* unwrapped); JSFunction* -GetUnwrappedAsyncFunction(JSFunction* wrapper); +GetUnwrappedAsyncFunction(JSFunction* wrapped); bool -IsWrappedAsyncFunction(JSContext* cx, JSFunction* wrapper); +IsWrappedAsyncFunction(JSFunction* fun); -bool -CreateAsyncFunction(JSContext* cx, HandleFunction wrapper, HandleFunction unwrapped, - MutableHandleFunction result); +JSObject* +WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped); } // namespace js diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index b74cd755af8c..bd0705446d87 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -30,7 +30,6 @@ macro(as, as, "as") \ macro(Async, Async, "Async") \ macro(AsyncFunction, AsyncFunction, "AsyncFunction") \ - macro(AsyncFunction_wrap, AsyncFunction_wrap, "AsyncFunction_wrap") \ macro(AsyncWrapped, AsyncWrapped, "AsyncWrapped") \ macro(async, async, "async") \ macro(await, await, "await") \ @@ -280,6 +279,8 @@ macro(stack, stack, "stack") \ macro(star, star, "*") \ macro(starDefaultStar, starDefaultStar, "*default*") \ + macro(StarGeneratorNext, StarGeneratorNext, "StarGeneratorNext") \ + macro(StarGeneratorThrow, StarGeneratorThrow, "StarGeneratorThrow") \ macro(startTimestamp, startTimestamp, "startTimestamp") \ macro(state, state, "state") \ macro(static, static_, "static") \ diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 291e9b2de013..df6f8ef4b1a1 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -38,6 +38,7 @@ #include "jit/BaselineJIT.h" #include "jit/Ion.h" #include "jit/IonAnalysis.h" +#include "vm/AsyncFunction.h" #include "vm/Debugger.h" #include "vm/GeneratorObject.h" #include "vm/Opcodes.h" @@ -1869,7 +1870,6 @@ CASE(EnableInterruptsPseudoOpcode) /* Various 1-byte no-ops. */ CASE(JSOP_NOP) CASE(JSOP_NOP_DESTRUCTURING) -CASE(JSOP_UNUSED149) CASE(JSOP_UNUSED182) CASE(JSOP_UNUSED183) CASE(JSOP_UNUSED187) @@ -3480,6 +3480,18 @@ CASE(JSOP_LAMBDA_ARROW) } END_CASE(JSOP_LAMBDA_ARROW) +CASE(JSOP_TOASYNC) +{ + ReservedRooted unwrapped(&rootFunction0, + ®S.sp[-1].toObject().as()); + JSObject* wrapped = WrapAsyncFunction(cx, unwrapped); + if (!wrapped) + goto error; + + REGS.sp[-1].setObject(*wrapped); +} +END_CASE(JSOP_TOASYNC) + CASE(JSOP_CALLEE) MOZ_ASSERT(REGS.fp()->isFunctionFrame()); PUSH_COPY(REGS.fp()->calleev()); diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index 38f351575c80..18ae6f07364a 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -1529,7 +1529,15 @@ * Stack: => new.target */ \ macro(JSOP_NEWTARGET, 148, "newtarget", NULL, 1, 0, 1, JOF_BYTE) \ - macro(JSOP_UNUSED149, 149, "unused149", NULL, 1, 0, 0, JOF_BYTE) \ + /* + * Pops the top of stack value as 'unwrapped', converts it to async + * function 'wrapped', and pushes 'wrapped' back on the stack. + * Category: Statements + * Type: Function + * Operands: + * Stack: unwrapped => wrapped + */ \ + macro(JSOP_TOASYNC, 149, "toasync", NULL, 1, 1, 1, JOF_BYTE) \ /* * Pops the top two values 'lval' and 'rval' from the stack, then pushes * the result of 'Math.pow(lval, rval)'. diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 61f10771ebaa..0c00867953bd 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -38,7 +38,6 @@ #include "jit/InlinableNatives.h" #include "js/CharacterEncoding.h" #include "js/Date.h" -#include "vm/AsyncFunction.h" #include "vm/Compression.h" #include "vm/GeneratorObject.h" #include "vm/Interpreter.h" @@ -1865,23 +1864,6 @@ js::ReportIncompatibleSelfHostedMethod(JSContext* cx, const CallArgs& args) return false; } -bool -intrinsic_CreateAsyncFunction(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - MOZ_ASSERT(args.length() == 2); - - RootedFunction wrapper(cx, &args[0].toObject().as()); - RootedFunction unwrapped(cx, &args[1].toObject().as()); - - RootedFunction wrapped(cx); - if (!CreateAsyncFunction(cx, wrapper, unwrapped, &wrapped)) - return false; - - args.rval().setObject(*wrapped); - return true; -} - /** * Returns the default locale as a well-formed, but not necessarily canonicalized, * BCP-47 language tag. @@ -2281,8 +2263,6 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0), JS_FN("AddContentTelemetry", intrinsic_AddContentTelemetry, 2,0), - JS_FN("CreateAsyncFunction", intrinsic_CreateAsyncFunction, 1,0), - JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing, 0,0, IntrinsicIsConstructing), JS_INLINABLE_FN("SubstringKernel", intrinsic_SubstringKernel, 3,0,