зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1314055 - Part 1: Port async/await implementation from self-hosted JS to C++. r=till
This commit is contained in:
Родитель
f3e7540d57
Коммит
679dffd17a
|
@ -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);
|
||||
});
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<JSFunction>());
|
||||
RootedObject wrapped(cx, WrapAsyncFunction(cx, unwrapped));
|
||||
if (!wrapped)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*wrapped);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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<GlobalObject*> 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<JSFunction>());
|
||||
RootedValue unwrappedVal(cx, wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT));
|
||||
RootedFunction unwrapped(cx, &unwrappedVal.toObject().as<JSFunction>());
|
||||
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<PromiseObject*> resolvePromise(cx, resolveObj.as<PromiseObject>());
|
||||
|
||||
// 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<JSFunction>());
|
||||
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<JSFunction>());
|
||||
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<JSFunction>();
|
||||
return &unwrapped->getExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT).toObject().as<JSFunction>();
|
||||
}
|
||||
|
||||
JSFunction*
|
||||
js::GetUnwrappedAsyncFunction(JSFunction* wrapper)
|
||||
js::GetUnwrappedAsyncFunction(JSFunction* wrapped)
|
||||
{
|
||||
JSFunction* unwrapped = &wrapper->getExtendedSlot(ASYNC_UNWRAPPED_SLOT).toObject().as<JSFunction>();
|
||||
MOZ_ASSERT(IsWrappedAsyncFunction(wrapped));
|
||||
JSFunction* unwrapped = &wrapped->getExtendedSlot(WRAPPED_ASYNC_UNWRAPPED_SLOT).toObject().as<JSFunction>();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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") \
|
||||
|
|
|
@ -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<JSFunction*> unwrapped(&rootFunction0,
|
||||
®S.sp[-1].toObject().as<JSFunction>());
|
||||
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());
|
||||
|
|
|
@ -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)'.
|
||||
|
|
|
@ -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<JSFunction>());
|
||||
RootedFunction unwrapped(cx, &args[1].toObject().as<JSFunction>());
|
||||
|
||||
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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче