Bug 1288457 - Part 15: Add JSProtoKey for AsyncGeneratorFunction. r=mgaudet

Differential Revision: https://phabricator.services.mozilla.com/D42885

--HG--
extra : moz-landing-system : lando
This commit is contained in:
André Bargull 2019-10-16 12:35:36 +00:00
parent d80c1ed430
commit 7a5b5e0a24
10 changed files with 83 additions and 51 deletions

View File

@ -746,7 +746,7 @@ static const uint32_t JSCLASS_FOREGROUND_FINALIZE =
// application.
static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 28;
JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 26;
static constexpr uint32_t JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(uint32_t n) {
return JSCLASS_IS_GLOBAL |

View File

@ -119,6 +119,7 @@
REAL(Promise, InitViaClassSpec, OCLASP(Promise)) \
REAL(AsyncFunction, InitAsyncFunction, nullptr) \
REAL(GeneratorFunction, InitGeneratorFunction, nullptr) \
REAL(AsyncGeneratorFunction, InitAsyncGeneratorFunction, nullptr) \
REAL(ReadableStream, InitViaClassSpec, &js::ReadableStream::class_) \
REAL(ReadableStreamDefaultReader, InitViaClassSpec, \
&js::ReadableStreamDefaultReader::class_) \

View File

@ -912,7 +912,8 @@ JS_PUBLIC_API bool JS_ResolveStandardClass(JSContext* cx, HandleObject obj,
// property, so we won't resolve anything.
JSProtoKey key = stdnm ? stdnm->key : JSProto_Null;
if (key != JSProto_Null && key != JSProto_AsyncFunction &&
key != JSProto_GeneratorFunction) {
key != JSProto_GeneratorFunction &&
key != JSProto_AsyncGeneratorFunction) {
const JSClass* clasp = ProtoKeyToClass(key);
if (!clasp || clasp->specShouldDefineConstructor()) {
if (!GlobalObject::ensureConstructor(cx, global, key)) {
@ -988,8 +989,9 @@ static bool EnumerateStandardClassesInTable(JSContext* cx,
continue;
}
// AsyncFunction and Generator don't yet use ClassSpec.
if (key == JSProto_AsyncFunction || key == JSProto_GeneratorFunction) {
// Async(Function|Generator) and Generator don't yet use ClassSpec.
if (key == JSProto_AsyncFunction || key == JSProto_GeneratorFunction ||
key == JSProto_AsyncGeneratorFunction) {
continue;
}

View File

@ -406,21 +406,17 @@ static const JSFunctionSpec async_generator_methods[] = {
JS_FN("throw", AsyncGeneratorThrow, 1, 0),
JS_FN("return", AsyncGeneratorReturn, 1, 0), JS_FS_END};
/* static */ MOZ_MUST_USE bool GlobalObject::initAsyncGenerators(
JSContext* cx, Handle<GlobalObject*> global) {
if (global->getReservedSlot(ASYNC_ITERATOR_PROTO).isObject()) {
return true;
}
JSObject* js::InitAsyncGeneratorFunction(JSContext* cx,
Handle<GlobalObject*> global) {
// 25.1.3 The %AsyncIteratorPrototype% Object
RootedObject asyncIterProto(
cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
if (!asyncIterProto) {
return false;
return nullptr;
}
if (!DefinePropertiesAndFunctions(cx, asyncIterProto, nullptr,
async_iterator_proto_methods)) {
return false;
return nullptr;
}
// 25.1.4.2 The %AsyncFromSyncIteratorPrototype% Object
@ -428,44 +424,44 @@ static const JSFunctionSpec async_generator_methods[] = {
cx, GlobalObject::createBlankPrototypeInheriting(cx, &PlainObject::class_,
asyncIterProto));
if (!asyncFromSyncIterProto) {
return false;
return nullptr;
}
if (!DefinePropertiesAndFunctions(cx, asyncFromSyncIterProto, nullptr,
async_from_sync_iter_methods) ||
!DefineToStringTag(cx, asyncFromSyncIterProto,
cx->names().AsyncFromSyncIterator)) {
return false;
return nullptr;
}
// 25.5 AsyncGenerator Objects
RootedObject asyncGenProto(cx, GlobalObject::createBlankPrototypeInheriting(
cx, &PlainObject::class_, asyncIterProto));
if (!asyncGenProto) {
return false;
return nullptr;
}
if (!DefinePropertiesAndFunctions(cx, asyncGenProto, nullptr,
async_generator_methods) ||
!DefineToStringTag(cx, asyncGenProto, cx->names().AsyncGenerator)) {
return false;
return nullptr;
}
// 25.3.3 Properties of the AsyncGeneratorFunction Prototype Object
RootedObject asyncGenerator(
cx, NewSingletonObjectWithFunctionPrototype(cx, global));
if (!asyncGenerator) {
return false;
return nullptr;
}
if (!LinkConstructorAndPrototype(cx, asyncGenerator, asyncGenProto,
JSPROP_READONLY, JSPROP_READONLY) ||
!DefineToStringTag(cx, asyncGenerator,
cx->names().AsyncGeneratorFunction)) {
return false;
return nullptr;
}
RootedObject proto(
cx, GlobalObject::getOrCreateFunctionConstructor(cx, cx->global()));
if (!proto) {
return false;
return nullptr;
}
HandlePropertyName name = cx->names().AsyncGeneratorFunction;
@ -475,20 +471,21 @@ static const JSFunctionSpec async_generator_methods[] = {
FunctionFlags::NATIVE_CTOR, nullptr, name, proto,
gc::AllocKind::FUNCTION, SingletonObject));
if (!asyncGenFunction) {
return false;
return nullptr;
}
if (!LinkConstructorAndPrototype(cx, asyncGenFunction, asyncGenerator,
JSPROP_PERMANENT | JSPROP_READONLY,
JSPROP_READONLY)) {
return false;
return nullptr;
}
global->setReservedSlot(ASYNC_ITERATOR_PROTO, ObjectValue(*asyncIterProto));
global->setReservedSlot(ASYNC_FROM_SYNC_ITERATOR_PROTO,
ObjectValue(*asyncFromSyncIterProto));
global->setReservedSlot(ASYNC_GENERATOR, ObjectValue(*asyncGenerator));
global->setReservedSlot(ASYNC_GENERATOR_FUNCTION,
ObjectValue(*asyncGenFunction));
global->setReservedSlot(ASYNC_GENERATOR_PROTO, ObjectValue(*asyncGenProto));
return true;
global->setAsyncIteratorPrototype(asyncIterProto);
global->setAsyncFromSyncIteratorPrototype(asyncFromSyncIterProto);
global->setAsyncGeneratorPrototype(asyncGenProto);
global->setConstructor(JSProto_AsyncGeneratorFunction,
ObjectValue(*asyncGenFunction));
global->setPrototype(JSProto_AsyncGeneratorFunction,
ObjectValue(*asyncGenerator));
return asyncGenFunction;
}

View File

@ -17,6 +17,7 @@
namespace js {
class AsyncGeneratorObject;
class GlobalObject;
// Resume the async generator when the `await` operand fulfills to `value`.
MOZ_MUST_USE bool AsyncGeneratorAwaitedFulfilled(
@ -294,6 +295,9 @@ MOZ_MUST_USE bool AsyncGeneratorResume(
JSContext* cx, Handle<AsyncGeneratorObject*> asyncGenObj,
CompletionKind completionKind, HandleValue argument);
extern JSObject* InitAsyncGeneratorFunction(JSContext* cx,
js::Handle<GlobalObject*> global);
} // namespace js
#endif /* vm_AsyncIteration_h */

View File

@ -36,8 +36,6 @@
MACRO(AsyncFunctionNext, AsyncFunctionNext, "AsyncFunctionNext") \
MACRO(AsyncFunctionThrow, AsyncFunctionThrow, "AsyncFunctionThrow") \
MACRO(AsyncGenerator, AsyncGenerator, "AsyncGenerator") \
MACRO(AsyncGeneratorFunction, AsyncGeneratorFunction, \
"AsyncGeneratorFunction") \
MACRO(AsyncGeneratorNext, AsyncGeneratorNext, "AsyncGeneratorNext") \
MACRO(AsyncGeneratorReturn, AsyncGeneratorReturn, "AsyncGeneratorReturn") \
MACRO(AsyncGeneratorThrow, AsyncGeneratorThrow, "AsyncGeneratorThrow") \

View File

@ -42,6 +42,7 @@
#include "gc/FreeOp.h"
#include "js/ProtoKey.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "vm/DateObject.h"
#include "vm/EnvironmentObject.h"
#include "vm/GeneratorObject.h"
@ -402,7 +403,8 @@ bool GlobalObject::resolveOffThreadConstructor(JSContext* cx,
MOZ_ASSERT(global->zone()->createdForHelperThread());
MOZ_ASSERT(key == JSProto_Object || key == JSProto_Function ||
key == JSProto_Array || key == JSProto_RegExp ||
key == JSProto_AsyncFunction || key == JSProto_GeneratorFunction);
key == JSProto_AsyncFunction || key == JSProto_GeneratorFunction ||
key == JSProto_AsyncGeneratorFunction);
Rooted<OffThreadPlaceholderObject*> placeholder(cx);
placeholder = OffThreadPlaceholderObject::New(cx, prototypeSlot(key));
@ -439,9 +441,8 @@ JSObject* GlobalObject::createOffThreadObject(JSContext* cx,
// compartment.
MOZ_ASSERT(global->zone()->createdForHelperThread());
MOZ_ASSERT(slot == ASYNC_GENERATOR || slot == MODULE_PROTO ||
slot == IMPORT_ENTRY_PROTO || slot == EXPORT_ENTRY_PROTO ||
slot == REQUESTED_MODULE_PROTO);
MOZ_ASSERT(slot == MODULE_PROTO || slot == IMPORT_ENTRY_PROTO ||
slot == EXPORT_ENTRY_PROTO || slot == REQUESTED_MODULE_PROTO);
auto placeholder = OffThreadPlaceholderObject::New(cx, slot);
if (!placeholder) {

View File

@ -79,8 +79,6 @@ class GlobalObject : public NativeObject {
GENERATOR_OBJECT_PROTO,
ASYNC_ITERATOR_PROTO,
ASYNC_FROM_SYNC_ITERATOR_PROTO,
ASYNC_GENERATOR,
ASYNC_GENERATOR_FUNCTION,
ASYNC_GENERATOR_PROTO,
MAP_ITERATOR_PROTO,
SET_ITERATOR_PROTO,
@ -624,34 +622,66 @@ class GlobalObject : public NativeObject {
return &global->getConstructor(JSProto_AsyncFunction).toObject();
}
void setAsyncIteratorPrototype(JSObject* obj) {
MOZ_ASSERT(getReservedSlot(ASYNC_ITERATOR_PROTO).isUndefined());
MOZ_ASSERT(obj != nullptr);
setSlot(ASYNC_ITERATOR_PROTO, ObjectValue(*obj));
}
void setAsyncFromSyncIteratorPrototype(JSObject* obj) {
MOZ_ASSERT(getReservedSlot(ASYNC_FROM_SYNC_ITERATOR_PROTO).isUndefined());
MOZ_ASSERT(obj != nullptr);
setSlot(ASYNC_FROM_SYNC_ITERATOR_PROTO, ObjectValue(*obj));
}
static NativeObject* getOrCreateAsyncIteratorPrototype(
JSContext* cx, Handle<GlobalObject*> global) {
return MaybeNativeObject(getOrCreateObject(cx, global, ASYNC_ITERATOR_PROTO,
initAsyncGenerators));
if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return nullptr;
}
return &global->getSlot(ASYNC_ITERATOR_PROTO).toObject().as<NativeObject>();
}
static NativeObject* getOrCreateAsyncFromSyncIteratorPrototype(
JSContext* cx, Handle<GlobalObject*> global) {
return MaybeNativeObject(getOrCreateObject(
cx, global, ASYNC_FROM_SYNC_ITERATOR_PROTO, initAsyncGenerators));
if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return nullptr;
}
return &global->getSlot(ASYNC_FROM_SYNC_ITERATOR_PROTO)
.toObject()
.as<NativeObject>();
}
static NativeObject* getOrCreateAsyncGenerator(JSContext* cx,
Handle<GlobalObject*> global) {
return MaybeNativeObject(
getOrCreateObject(cx, global, ASYNC_GENERATOR, initAsyncGenerators));
if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return nullptr;
}
return &global->getPrototype(JSProto_AsyncGeneratorFunction)
.toObject()
.as<NativeObject>();
}
static JSObject* getOrCreateAsyncGeneratorFunction(
JSContext* cx, Handle<GlobalObject*> global) {
return getOrCreateObject(cx, global, ASYNC_GENERATOR_FUNCTION,
initAsyncGenerators);
if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return nullptr;
}
return &global->getConstructor(JSProto_AsyncGeneratorFunction).toObject();
}
void setAsyncGeneratorPrototype(JSObject* obj) {
setSlot(ASYNC_GENERATOR_PROTO, ObjectValue(*obj));
}
static NativeObject* getOrCreateAsyncGeneratorPrototype(
JSContext* cx, Handle<GlobalObject*> global) {
return MaybeNativeObject(getOrCreateObject(
cx, global, ASYNC_GENERATOR_PROTO, initAsyncGenerators));
if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return nullptr;
}
return &global->getSlot(ASYNC_GENERATOR_PROTO)
.toObject()
.as<NativeObject>();
}
static JSObject* getOrCreateMapIteratorPrototype(
@ -789,8 +819,6 @@ class GlobalObject : public NativeObject {
static bool initRegExpStringIteratorProto(JSContext* cx,
Handle<GlobalObject*> global);
static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
// Implemented in builtin/MapObject.cpp.
static bool initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);

View File

@ -850,7 +850,7 @@ static bool EnsureParserCreatedClasses(JSContext* cx, ParseTaskKind kind) {
return false; // needed by async function() {}
}
if (!GlobalObject::initAsyncGenerators(cx, global)) {
if (!EnsureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
return false; // needed by async function*() {}
}

View File

@ -1941,13 +1941,14 @@ static bool CreateDynamicFunction(JSContext* cx, const CallArgs& args,
return false;
}
JSProtoKey protoKey = JSProto_Null;
JSProtoKey protoKey;
if (isAsync) {
if (isGenerator) {
if (!CompileStandaloneAsyncGenerator(cx, &fun, options, srcBuf,
parameterListEnd)) {
return false;
}
protoKey = JSProto_AsyncGeneratorFunction;
} else {
if (!CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf,
parameterListEnd)) {