mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 08:18:41 +09:00
Issue #2089 - In Promises, use a C++ version of SpeciesConstructor when calling from C++
Based-on: m-c 1344656,1386534
This commit is contained in:
parent
6b50dd5d06
commit
8322304fb3
7 changed files with 220 additions and 109 deletions
|
|
@ -2479,7 +2479,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.
|
||||
|
||||
|
|
@ -2520,6 +2531,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,
|
||||
|
|
@ -2538,10 +2555,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))
|
||||
|
|
@ -3193,11 +3209,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);
|
||||
|
|
@ -3579,7 +3594,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.
|
||||
|
|
|
|||
|
|
@ -2070,6 +2070,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)
|
||||
|
|
|
|||
|
|
@ -3864,34 +3864,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
|
||||
|
|
|
|||
|
|
@ -1347,11 +1347,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);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
// 22.2.4.3 TypedArray ( typedArray )
|
||||
|
||||
// Test [[Prototype]] of newly created typed array and its array buffer, and
|
||||
// ensure they are both created in the correct global.
|
||||
|
||||
const thisGlobal = this;
|
||||
const otherGlobal = newGlobal();
|
||||
const ta_i32 = otherGlobal.eval("new Int32Array(0)");
|
||||
|
||||
function assertBufferPrototypeFrom(newTypedArray, prototype) {
|
||||
var typedArrayName = newTypedArray.constructor.name;
|
||||
|
||||
assertEq(Object.getPrototypeOf(newTypedArray), thisGlobal[typedArrayName].prototype);
|
||||
assertEq(Object.getPrototypeOf(newTypedArray.buffer), prototype);
|
||||
}
|
||||
|
||||
const EMPTY = {};
|
||||
|
||||
// Test SpeciesConstructor() implementation selects the correct (fallback) constructor.
|
||||
const testCases = [
|
||||
// Create the array buffer from the species constructor.
|
||||
{ constructor: EMPTY, prototype: otherGlobal.ArrayBuffer.prototype },
|
||||
|
||||
// Use %ArrayBuffer% from this global if constructor is undefined.
|
||||
{ constructor: undefined, prototype: ArrayBuffer.prototype },
|
||||
|
||||
// Use %ArrayBuffer% from this global if species is undefined.
|
||||
{ constructor: {[Symbol.species]: undefined}, prototype: ArrayBuffer.prototype },
|
||||
|
||||
// Use %ArrayBuffer% from this global if species is null.
|
||||
{ constructor: {[Symbol.species]: null}, prototype: ArrayBuffer.prototype },
|
||||
];
|
||||
|
||||
for (let { constructor, prototype } of testCases) {
|
||||
if (constructor !== EMPTY) {
|
||||
ta_i32.buffer.constructor = constructor;
|
||||
}
|
||||
|
||||
// Same element type.
|
||||
assertBufferPrototypeFrom(new Int32Array(ta_i32), prototype);
|
||||
|
||||
// Different element type.
|
||||
assertBufferPrototypeFrom(new Int16Array(ta_i32), prototype);
|
||||
}
|
||||
|
||||
|
||||
// Also ensure TypeErrors are thrown from the correct global.
|
||||
const errorTestCases = [
|
||||
// Constructor property is neither undefined nor an object.
|
||||
{ constructor: null },
|
||||
{ constructor: 123 },
|
||||
|
||||
// Species property is neither undefined/null nor a constructor function.
|
||||
{ constructor: { [Symbol.species]: 123 } },
|
||||
{ constructor: { [Symbol.species]: [] } },
|
||||
{ constructor: { [Symbol.species]: () => {} } },
|
||||
];
|
||||
|
||||
for (let { constructor } of errorTestCases) {
|
||||
ta_i32.buffer.constructor = constructor;
|
||||
|
||||
// Same element type.
|
||||
assertThrowsInstanceOf(() => new Int32Array(ta_i32), TypeError);
|
||||
|
||||
// Different element type.
|
||||
assertThrowsInstanceOf(() => new Int32Array(ta_i32), TypeError);
|
||||
}
|
||||
|
||||
|
||||
// TypedArrays using SharedArrayBuffers never call the SpeciesConstructor operation.
|
||||
if (this.SharedArrayBuffer) {
|
||||
const ta_i32_shared = otherGlobal.eval("new Int32Array(new SharedArrayBuffer(0))");
|
||||
|
||||
Object.defineProperty(ta_i32_shared.buffer, "constructor", {
|
||||
get() {
|
||||
throw new Error("constructor property accessed");
|
||||
}
|
||||
});
|
||||
|
||||
// Same element type.
|
||||
assertBufferPrototypeFrom(new Int32Array(ta_i32_shared), ArrayBuffer.prototype);
|
||||
|
||||
// Different element type.
|
||||
assertBufferPrototypeFrom(new Int16Array(ta_i32_shared), ArrayBuffer.prototype);
|
||||
}
|
||||
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
||||
|
|
@ -1063,65 +1063,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 (!isWrapped) {
|
||||
if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
|
||||
return false;
|
||||
RootedValue defaultCtor(cx, cx->global()->getConstructor(JSProto_ArrayBuffer));
|
||||
// The second disjunct is an optimization.
|
||||
if (override == SpeciesConstructorOverride::ArrayBuffer || IsArrayBufferSpecies(cx, obj))
|
||||
ctor.set(defaultCtor);
|
||||
else if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
|
||||
return false;
|
||||
if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
|
||||
return nullptr;
|
||||
RootedObject defaultCtor(cx, &cx->global()->getConstructor(JSProto_ArrayBuffer).toObject());
|
||||
|
||||
return true;
|
||||
}
|
||||
// Use the current global's ArrayBuffer if the override is set.
|
||||
if (override == SpeciesConstructorOverride::ArrayBuffer)
|
||||
return defaultCtor;
|
||||
|
||||
{
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
if (!GlobalObject::ensureConstructor(cx, cx->global(), JSProto_ArrayBuffer))
|
||||
return false;
|
||||
RootedValue defaultCtor(cx, cx->global()->getConstructor(JSProto_ArrayBuffer));
|
||||
if (override == SpeciesConstructorOverride::ArrayBuffer)
|
||||
ctor.set(defaultCtor);
|
||||
else if (!SpeciesConstructor(cx, obj, defaultCtor, ctor))
|
||||
return false;
|
||||
}
|
||||
RootedObject wrappedObj(cx, obj);
|
||||
if (isWrapped && !cx->compartment()->wrap(cx, &wrappedObj))
|
||||
return nullptr;
|
||||
|
||||
return JS_WrapValue(cx, ctor);
|
||||
return SpeciesConstructor(cx, wrappedObj, defaultCtor, IsArrayBufferSpecies);
|
||||
}
|
||||
|
||||
// ES 2017 draft rev 8633ffd9394b203b8876bb23cb79aff13eb07310 24.1.1.4.
|
||||
|
|
@ -1137,9 +1100,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()) {
|
||||
|
|
@ -1181,7 +1145,8 @@ TypedArrayObjectTemplate<T>::fromArray(JSContext* cx, HandleObject other,
|
|||
return fromObject(cx, other, newTarget);
|
||||
}
|
||||
|
||||
// ES 2017 draft rev 8633ffd9394b203b8876bb23cb79aff13eb07310 22.2.4.3.
|
||||
// ES2017 draft rev 6390c2f1b34b309895d31d8c0512eac8660a0210
|
||||
// 22.2.4.3 TypedArray ( typedArray )
|
||||
template<typename T>
|
||||
/* static */ JSObject*
|
||||
TypedArrayObjectTemplate<T>::fromTypedArray(JSContext* cx, HandleObject other, bool isWrapped,
|
||||
|
|
@ -1229,61 +1194,62 @@ TypedArrayObjectTemplate<T>::fromTypedArray(JSContext* cx, HandleObject other, b
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Steps 10.
|
||||
// Step 9.
|
||||
uint32_t elementLength = srcArray->length();
|
||||
|
||||
// Steps 11-12.
|
||||
// Steps 10-11.
|
||||
Scalar::Type srcType = srcArray->type();
|
||||
|
||||
// Step 13 (skipped).
|
||||
// Step 12 (skipped).
|
||||
|
||||
// Step 14.
|
||||
// Step 13.
|
||||
uint32_t srcByteOffset = srcArray->byteOffset();
|
||||
|
||||
// Step 17, modified for SharedArrayBuffer.
|
||||
// Steps 16-17.
|
||||
bool isShared = srcArray->isSharedMemory();
|
||||
SpeciesConstructorOverride override = isShared ? SpeciesConstructorOverride::ArrayBuffer
|
||||
: SpeciesConstructorOverride::None;
|
||||
|
||||
// Steps 8-9, 17.
|
||||
// Steps 8, 16-17.
|
||||
Rooted<ArrayBufferObject*> buffer(cx);
|
||||
if (ArrayTypeID() == srcType) {
|
||||
// Step 17.a.
|
||||
// Step 16.a.
|
||||
uint32_t srcLength = srcArray->byteLength();
|
||||
|
||||
// Step 17.b, modified for SharedArrayBuffer
|
||||
// Steps 16.b-c.
|
||||
if (!CloneArrayBufferNoCopy(cx, srcData, isWrapped, srcByteOffset, srcLength, override,
|
||||
&buffer))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
// Step 18.a, modified for SharedArrayBuffer
|
||||
RootedValue bufferCtor(cx);
|
||||
if (!GetSpeciesConstructor(cx, srcData, isWrapped, override, &bufferCtor))
|
||||
// Steps 17.a-b.
|
||||
JSObject* ctorObj = GetSpeciesConstructor(cx, srcData, isWrapped, override);
|
||||
if (!ctorObj)
|
||||
return nullptr;
|
||||
RootedValue bufferCtor(cx, ObjectValue(*ctorObj));
|
||||
|
||||
// Step 15-16, 18.b.
|
||||
// Steps 14-15, 17.c.
|
||||
if (!AllocateArrayBuffer(cx, bufferCtor, elementLength, BYTES_PER_ELEMENT, &buffer))
|
||||
return nullptr;
|
||||
|
||||
// Step 18.c.
|
||||
// Step 17.d.
|
||||
if (srcArray->hasDetachedBuffer()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 3, 4 (remaining part), 19-22.
|
||||
// Steps 3-4 (remaining part), 18-21.
|
||||
Rooted<TypedArrayObject*> obj(cx, makeInstance(cx, buffer, 0, elementLength, proto));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
// Step 18.d-g or 24.1.1.4 step 11.
|
||||
// Steps 17.e-h or 24.1.1.4 step 8.
|
||||
if (!TypedArrayMethods<TypedArrayObject>::setFromTypedArray(cx, obj, srcArray))
|
||||
return nullptr;
|
||||
|
||||
// Step 23.
|
||||
// Step 22.
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue