зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1386534 - Use a C++ version of SpeciesConstructor when calling from C++. r=anba,rs=jonco
MozReview-Commit-ID: qyU0pqt0tV
This commit is contained in:
Родитель
f979e78b8c
Коммит
718ce2a817
|
@ -2177,7 +2177,18 @@ PromiseObject::unforgeableResolve(JSContext* cx, HandleValue value)
|
|||
return CommonStaticResolveRejectImpl(cx, cVal, value, ResolveMode);
|
||||
}
|
||||
|
||||
// ES2016, 25.4.4.6, implemented in Promise.js.
|
||||
/**
|
||||
* ES2016, 25.4.4.6 get Promise [ @@species ]
|
||||
*/
|
||||
static bool
|
||||
Promise_static_species(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Step 1: Return the this value.
|
||||
args.rval().set(args.thisv());
|
||||
return true;
|
||||
}
|
||||
|
||||
// ES2016, 25.4.5.1, implemented in Promise.js.
|
||||
|
||||
|
@ -2209,6 +2220,12 @@ NewReactionRecord(JSContext* cx, HandleObject resultPromise, HandleValue onFulfi
|
|||
return reaction;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsPromiseSpecies(JSContext* cx, JSFunction* species)
|
||||
{
|
||||
return species->maybeNative() == Promise_static_species;
|
||||
}
|
||||
|
||||
// ES2016, 25.4.5.3., steps 3-5.
|
||||
MOZ_MUST_USE bool
|
||||
js::OriginalPromiseThen(JSContext* cx, Handle<PromiseObject*> promise,
|
||||
|
@ -2227,10 +2244,9 @@ js::OriginalPromiseThen(JSContext* cx, Handle<PromiseObject*> promise,
|
|||
|
||||
if (createDependent) {
|
||||
// Step 3.
|
||||
RootedValue ctorVal(cx);
|
||||
if (!SpeciesConstructor(cx, promiseObj, JSProto_Promise, &ctorVal))
|
||||
RootedObject C(cx, SpeciesConstructor(cx, promiseObj, JSProto_Promise, IsPromiseSpecies));
|
||||
if (!C)
|
||||
return false;
|
||||
RootedObject C(cx, &ctorVal.toObject());
|
||||
|
||||
// Step 4.
|
||||
if (!NewPromiseCapability(cx, C, &resultPromise, &resolve, &reject, true))
|
||||
|
@ -2875,11 +2891,10 @@ BlockOnPromise(JSContext* cx, HandleValue promiseVal, HandleObject blockedPromis
|
|||
RootedObject PromiseCtor(cx);
|
||||
if (!GetBuiltinConstructor(cx, JSProto_Promise, &PromiseCtor))
|
||||
return false;
|
||||
RootedValue PromiseCtorVal(cx, ObjectValue(*PromiseCtor));
|
||||
RootedValue CVal(cx);
|
||||
if (!SpeciesConstructor(cx, promiseObj, PromiseCtorVal, &CVal))
|
||||
|
||||
RootedObject C(cx, SpeciesConstructor(cx, PromiseCtor, JSProto_Promise, IsPromiseSpecies));
|
||||
if (!C)
|
||||
return false;
|
||||
RootedObject C(cx, &CVal.toObject());
|
||||
|
||||
RootedObject resultPromise(cx, blockedPromise_);
|
||||
RootedObject resolveFun(cx);
|
||||
|
@ -3471,7 +3486,7 @@ static const JSFunctionSpec promise_static_methods[] = {
|
|||
};
|
||||
|
||||
static const JSPropertySpec promise_static_properties[] = {
|
||||
JS_SELF_HOSTED_SYM_GET(species, "Promise_static_get_species", 0),
|
||||
JS_SYM_GET(species, Promise_static_species, 0),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
|
|
|
@ -2,13 +2,6 @@
|
|||
* 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/. */
|
||||
|
||||
// ES6, 25.4.4.6.
|
||||
function Promise_static_get_species() {
|
||||
// Step 1.
|
||||
return this;
|
||||
}
|
||||
_SetCanonicalName(Promise_static_get_species, "get [Symbol.species]");
|
||||
|
||||
// ES6, 25.4.5.1.
|
||||
function Promise_catch(onRejected) {
|
||||
// Steps 1-2.
|
||||
|
|
|
@ -2294,6 +2294,9 @@ inline int CheckIsSetterOp(JSSetterOp op);
|
|||
#define JS_PSGS(name, getter, setter, flags) \
|
||||
JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \
|
||||
JSPROP_SHARED)
|
||||
#define JS_SYM_GET(symbol, getter, flags) \
|
||||
JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
|
||||
JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, JSPROP_SHARED)
|
||||
#define JS_SELF_HOSTED_GET(name, getterName, flags) \
|
||||
JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
|
||||
JSPROP_SHARED | JSPROP_GETTER)
|
||||
|
|
|
@ -3998,34 +3998,77 @@ JSObject::maybeConstructorDisplayAtom() const
|
|||
return displayAtomFromObjectGroup(*group());
|
||||
}
|
||||
|
||||
bool
|
||||
js::SpeciesConstructor(JSContext* cx, HandleObject obj, HandleValue defaultCtor, MutableHandleValue pctor)
|
||||
// ES 2016 7.3.20.
|
||||
MOZ_MUST_USE JSObject*
|
||||
js::SpeciesConstructor(JSContext* cx, HandleObject obj, HandleObject defaultCtor,
|
||||
bool (*isDefaultSpecies)(JSContext*, JSFunction*))
|
||||
{
|
||||
HandlePropertyName shName = cx->names().SpeciesConstructor;
|
||||
RootedValue func(cx);
|
||||
if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, shName, 2, &func))
|
||||
return false;
|
||||
// Step 1 (implicit).
|
||||
|
||||
FixedInvokeArgs<2> args(cx);
|
||||
// Fast-path for steps 2 - 8. Applies if all of the following conditions
|
||||
// are met:
|
||||
// - obj.constructor can be retrieved without side-effects.
|
||||
// - obj.constructor[[@@species]] can be retrieved without side-effects.
|
||||
// - obj.constructor[[@@species]] is the builtin's original @@species
|
||||
// getter.
|
||||
RootedValue ctor(cx);
|
||||
bool ctorGetSucceeded = GetPropertyPure(cx, obj, NameToId(cx->names().constructor),
|
||||
ctor.address());
|
||||
if (ctorGetSucceeded && ctor.isObject() && &ctor.toObject() == defaultCtor) {
|
||||
RootedObject ctorObj(cx, &ctor.toObject());
|
||||
RootedId speciesId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().species));
|
||||
JSFunction* getter;
|
||||
if (GetGetterPure(cx, ctorObj, speciesId, &getter) && getter &&
|
||||
isDefaultSpecies(cx, getter))
|
||||
{
|
||||
return defaultCtor;
|
||||
}
|
||||
}
|
||||
|
||||
args[0].setObject(*obj);
|
||||
args[1].set(defaultCtor);
|
||||
// Step 2.
|
||||
if (!ctorGetSucceeded && !GetProperty(cx, obj, obj, cx->names().constructor, &ctor))
|
||||
return nullptr;
|
||||
|
||||
if (!Call(cx, func, UndefinedHandleValue, args, pctor))
|
||||
return false;
|
||||
// Step 3.
|
||||
if (ctor.isUndefined())
|
||||
return defaultCtor;
|
||||
|
||||
pctor.set(args.rval());
|
||||
return true;
|
||||
// Step 4.
|
||||
if (!ctor.isObject()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT,
|
||||
"object's 'constructor' property");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
RootedObject ctorObj(cx, &ctor.toObject());
|
||||
RootedValue s(cx);
|
||||
RootedId speciesId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().species));
|
||||
if (!GetProperty(cx, ctorObj, ctor, speciesId, &s))
|
||||
return nullptr;
|
||||
|
||||
// Step 6.
|
||||
if (s.isNullOrUndefined())
|
||||
return defaultCtor;
|
||||
|
||||
// Step 7.
|
||||
if (IsConstructor(s))
|
||||
return &s.toObject();
|
||||
|
||||
// Step 8.
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_CONSTRUCTOR,
|
||||
"[Symbol.species] property of object's constructor");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
MOZ_MUST_USE JSObject*
|
||||
js::SpeciesConstructor(JSContext* cx, HandleObject obj, JSProtoKey ctorKey,
|
||||
MutableHandleValue pctor)
|
||||
bool (*isDefaultSpecies)(JSContext*, JSFunction*))
|
||||
{
|
||||
if (!GlobalObject::ensureConstructor(cx, cx->global(), ctorKey))
|
||||
return false;
|
||||
RootedValue defaultCtor(cx, cx->global()->getConstructor(ctorKey));
|
||||
return SpeciesConstructor(cx, obj, defaultCtor, pctor);
|
||||
return nullptr;
|
||||
RootedObject defaultCtor(cx, &cx->global()->getConstructor(ctorKey).toObject());
|
||||
return SpeciesConstructor(cx, obj, defaultCtor, isDefaultSpecies);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -1418,11 +1418,13 @@ FreezeObject(JSContext* cx, HandleObject obj)
|
|||
extern bool
|
||||
TestIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level, bool* resultp);
|
||||
|
||||
extern bool
|
||||
SpeciesConstructor(JSContext* cx, HandleObject obj, HandleValue defaultCtor, MutableHandleValue pctor);
|
||||
extern MOZ_MUST_USE JSObject*
|
||||
SpeciesConstructor(JSContext* cx, HandleObject obj, HandleObject defaultCtor,
|
||||
bool (*isDefaultSpecies)(JSContext*, JSFunction*));
|
||||
|
||||
extern bool
|
||||
SpeciesConstructor(JSContext* cx, HandleObject obj, JSProtoKey ctorKey, MutableHandleValue pctor);
|
||||
extern MOZ_MUST_USE JSObject*
|
||||
SpeciesConstructor(JSContext* cx, HandleObject obj, JSProtoKey ctorKey,
|
||||
bool (*isDefaultSpecies)(JSContext*, JSFunction*));
|
||||
|
||||
extern bool
|
||||
GetObjectFromIncumbentGlobal(JSContext* cx, MutableHandleObject obj);
|
||||
|
|
|
@ -1067,70 +1067,28 @@ TypedArrayObjectTemplate<T>::AllocateArrayBuffer(JSContext* cx, HandleValue ctor
|
|||
}
|
||||
|
||||
static bool
|
||||
IsArrayBufferConstructor(const Value& v)
|
||||
IsArrayBufferSpecies(JSContext* cx, JSFunction* species)
|
||||
{
|
||||
return v.isObject() &&
|
||||
v.toObject().is<JSFunction>() &&
|
||||
v.toObject().as<JSFunction>().isNative() &&
|
||||
v.toObject().as<JSFunction>().native() == ArrayBufferObject::class_constructor;
|
||||
return IsSelfHostedFunctionWithName(species, cx->names().ArrayBufferSpecies);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsArrayBufferSpecies(JSContext* cx, HandleObject origBuffer)
|
||||
{
|
||||
RootedValue ctor(cx);
|
||||
if (!GetPropertyPure(cx, origBuffer, NameToId(cx->names().constructor), ctor.address()))
|
||||
return false;
|
||||
|
||||
if (!IsArrayBufferConstructor(ctor))
|
||||
return false;
|
||||
|
||||
RootedObject ctorObj(cx, &ctor.toObject());
|
||||
RootedId speciesId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().species));
|
||||
JSFunction* getter;
|
||||
if (!GetGetterPure(cx, ctorObj, speciesId, &getter))
|
||||
return false;
|
||||
|
||||
if (!getter)
|
||||
return false;
|
||||
|
||||
return IsSelfHostedFunctionWithName(getter, cx->names().ArrayBufferSpecies);
|
||||
}
|
||||
|
||||
static bool
|
||||
static JSObject*
|
||||
GetSpeciesConstructor(JSContext* cx, HandleObject obj, bool isWrapped,
|
||||
SpeciesConstructorOverride override, MutableHandleValue ctor)
|
||||
SpeciesConstructorOverride override)
|
||||
{
|
||||
if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
|
||||
return false;
|
||||
RootedValue defaultCtor(cx, cx->global()->getConstructor(JSProto_ArrayBuffer));
|
||||
return nullptr;
|
||||
RootedObject defaultCtor(cx, &cx->global()->getConstructor(JSProto_ArrayBuffer).toObject());
|
||||
|
||||
// Use the current global's ArrayBuffer if the override is set.
|
||||
if (override == SpeciesConstructorOverride::ArrayBuffer) {
|
||||
ctor.set(defaultCtor);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isWrapped) {
|
||||
// As an optimization, avoid calling into self-hosted code if |obj|'s
|
||||
// constructor is the built-in ArrayBuffer and the constructor's
|
||||
// species property is the original ArrayBuffer[@@species] function.
|
||||
if (IsArrayBufferSpecies(cx, obj))
|
||||
ctor.set(defaultCtor);
|
||||
else if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
if (override == SpeciesConstructorOverride::ArrayBuffer)
|
||||
return defaultCtor;
|
||||
|
||||
RootedObject wrappedObj(cx, obj);
|
||||
if (!cx->compartment()->wrap(cx, &wrappedObj))
|
||||
return false;
|
||||
if (isWrapped && !cx->compartment()->wrap(cx, &wrappedObj))
|
||||
return nullptr;
|
||||
|
||||
if (!SpeciesConstructor(cx, wrappedObj, defaultCtor, ctor))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return SpeciesConstructor(cx, wrappedObj, defaultCtor, IsArrayBufferSpecies);
|
||||
}
|
||||
|
||||
// ES 2017 draft rev 8633ffd9394b203b8876bb23cb79aff13eb07310 24.1.1.4.
|
||||
|
@ -1146,9 +1104,10 @@ TypedArrayObjectTemplate<T>::CloneArrayBufferNoCopy(JSContext* cx,
|
|||
// Step 1 (skipped).
|
||||
|
||||
// Step 2.a.
|
||||
RootedValue cloneCtor(cx);
|
||||
if (!GetSpeciesConstructor(cx, srcBuffer, isWrapped, override, &cloneCtor))
|
||||
JSObject* ctorObj = GetSpeciesConstructor(cx, srcBuffer, isWrapped, override);
|
||||
if (!ctorObj)
|
||||
return false;
|
||||
RootedValue cloneCtor(cx, ObjectValue(*ctorObj));
|
||||
|
||||
// Step 2.b.
|
||||
if (srcBuffer->isDetached()) {
|
||||
|
@ -1266,9 +1225,10 @@ TypedArrayObjectTemplate<T>::fromTypedArray(JSContext* cx, HandleObject other, b
|
|||
}
|
||||
} else {
|
||||
// Steps 17.a-b.
|
||||
RootedValue bufferCtor(cx);
|
||||
if (!GetSpeciesConstructor(cx, srcData, isWrapped, override, &bufferCtor))
|
||||
JSObject* ctorObj = GetSpeciesConstructor(cx, srcData, isWrapped, override);
|
||||
if (!ctorObj)
|
||||
return nullptr;
|
||||
RootedValue bufferCtor(cx, ObjectValue(*ctorObj));
|
||||
|
||||
// Steps 14-15, 17.c.
|
||||
if (!AllocateArrayBuffer(cx, bufferCtor, elementLength, BYTES_PER_ELEMENT, &buffer))
|
||||
|
|
Загрузка…
Ссылка в новой задаче