// ES6 (22 May, 2014) 9.5.14 Proxy.[[Construct]]
bool
ScriptedDirectProxyHandler::construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const
{
    // step 1
    RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));

    // step 2
    if (!handler) {
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
        return false;
    }

    // step 3
    RootedObject target(cx, proxy->as<ProxyObject>().target());
    MOZ_ASSERT(target->isConstructor());

    // step 7
    RootedObject argsArray(cx, NewDenseCopiedArray(cx, args.length(), args.array()));
    if (!argsArray)
        return false;

    // step 4-5
    RootedValue trap(cx);
    if (!GetProperty(cx, handler, handler, cx->names().construct, &trap))
        return false;

    // step 6
    if (trap.isUndefined()) {
        ConstructArgs cargs(cx);
        if (!FillArgumentsFromArraylike(cx, cargs, args))
            return false;

        RootedValue targetv(cx, ObjectValue(*target));
        RootedObject obj(cx);
        if (!Construct(cx, targetv, cargs, args.newTarget(), &obj))
            return false;

        args.rval().setObject(*obj);
        return true;
    }

    // step 8-9
    Value constructArgv[] = {
        ObjectValue(*target),
        ObjectValue(*argsArray),
        args.newTarget()
    };
    RootedValue thisValue(cx, ObjectValue(*handler));
    if (!Invoke(cx, thisValue, trap, ArrayLength(constructArgv), constructArgv, args.rval()))
        return false;

    // step 10
    if (!args.rval().isObject()) {
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_CONSTRUCT_OBJECT);
        return false;
    }
    return true;
}
/*
 * new ArrayBuffer(byteLength)
 */
bool
ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    if (!ThrowIfNotConstructing(cx, args, "ArrayBuffer"))
        return false;

    int32_t nbytes = 0;
    if (argc > 0 && !ToInt32(cx, args[0], &nbytes))
        return false;

    if (nbytes < 0) {
        /*
         * We're just not going to support arrays that are bigger than what will fit
         * as an integer value; if someone actually ever complains (validly), then we
         * can fix.
         */
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
        return false;
    }

    RootedObject proto(cx);
    RootedObject newTarget(cx, &args.newTarget().toObject());
    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
        return false;

    JSObject* bufobj = create(cx, uint32_t(nbytes), proto);
    if (!bufobj)
        return false;
    args.rval().setObject(*bufobj);
    return true;
}
Beispiel #3
0
bool
MapObject::construct(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    if (!ThrowIfNotConstructing(cx, args, "Map"))
        return false;

    RootedObject proto(cx);
    RootedObject newTarget(cx, &args.newTarget().toObject());
    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
        return false;

    Rooted<MapObject*> obj(cx, MapObject::create(cx, proto));
    if (!obj)
        return false;

    if (!args.get(0).isNullOrUndefined()) {
        FixedInvokeArgs<1> args2(cx);
        args2[0].set(args[0]);

        RootedValue thisv(cx, ObjectValue(*obj));
        if (!CallSelfHostedFunction(cx, cx->names().MapConstructorInit, thisv, args2, args2.rval()))
            return false;
    }

    args.rval().setObject(*obj);
    return true;
}
bool
SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    if (!ThrowIfNotConstructing(cx, args, "SharedArrayBuffer"))
        return false;

    // Bugs 1068458, 1161298: Limit length to 2^31-1.
    uint32_t length;
    bool overflow_unused;
    if (!ToLengthClamped(cx, args.get(0), &length, &overflow_unused) || length > INT32_MAX) {
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_BAD_LENGTH);
        return false;
    }

    RootedObject proto(cx);
    RootedObject newTarget(cx, &args.newTarget().toObject());
    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
        return false;

    JSObject* bufobj = New(cx, length, proto);
    if (!bufobj)
        return false;
    args.rval().setObject(*bufobj);
    return true;
}
// ES2017 draft rev 6390c2f1b34b309895d31d8c0512eac8660a0210
// 24.2.2.1 SharedArrayBuffer( length )
bool
SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    // Step 1.
    if (!ThrowIfNotConstructing(cx, args, "SharedArrayBuffer"))
        return false;

    // Step 2.
    uint64_t byteLength;
    if (!ToIndex(cx, args.get(0), &byteLength))
        return false;

    // Step 3 (Inlined 24.2.1.1 AllocateSharedArrayBuffer).
    // 24.2.1.1, step 1 (Inlined 9.1.14 OrdinaryCreateFromConstructor).
    RootedObject proto(cx);
    RootedObject newTarget(cx, &args.newTarget().toObject());
    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
        return false;

    // 24.2.1.1, step 3 (Inlined 6.2.7.2 CreateSharedByteDataBlock, step 2).
    // Refuse to allocate too large buffers, currently limited to ~2 GiB.
    if (byteLength > INT32_MAX) {
        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_BAD_LENGTH);
        return false;
    }

    // 24.2.1.1, steps 1 and 4-6.
    JSObject* bufobj = New(cx, uint32_t(byteLength), proto);
    if (!bufobj)
        return false;
    args.rval().setObject(*bufobj);
    return true;
}
Beispiel #6
0
bool
SetObject::construct(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    if (!ThrowIfNotConstructing(cx, args, "Set"))
        return false;

    RootedObject proto(cx);
    RootedObject newTarget(cx, &args.newTarget().toObject());
    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
        return false;

    Rooted<SetObject*> obj(cx, SetObject::create(cx, proto));
    if (!obj)
        return false;

    if (!args.get(0).isNullOrUndefined()) {
        RootedValue iterable(cx, args[0]);
        bool optimized = false;
        if (!IsOptimizableInitForSet<GlobalObject::getOrCreateSetPrototype, isBuiltinAdd>(cx, obj, iterable, &optimized))
            return false;

        if (optimized) {
            RootedValue keyVal(cx);
            Rooted<HashableValue> key(cx);
            ValueSet* set = obj->getData();
            ArrayObject* array = &iterable.toObject().as<ArrayObject>();
            for (uint32_t index = 0; index < array->getDenseInitializedLength(); ++index) {
                keyVal.set(array->getDenseElement(index));
                MOZ_ASSERT(!keyVal.isMagic(JS_ELEMENTS_HOLE));

                if (!key.setValue(cx, keyVal))
                    return false;
                if (!WriteBarrierPost(cx->runtime(), obj, keyVal) ||
                    !set->put(key))
                {
                    ReportOutOfMemory(cx);
                    return false;
                }
            }
        } else {
            FixedInvokeArgs<1> args2(cx);
            args2[0].set(args[0]);

            RootedValue thisv(cx, ObjectValue(*obj));
            if (!CallSelfHostedFunction(cx, cx->names().SetConstructorInit, thisv, args2, args2.rval()))
                return false;
        }
    }

    args.rval().setObject(*obj);
    return true;
}
Beispiel #7
0
bool
js::obj_construct(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    RootedObject obj(cx, nullptr);
    if (args.isConstructing() && (&args.newTarget().toObject() != &args.callee())) {
        RootedObject newTarget(cx, &args.newTarget().toObject());
        obj = CreateThis(cx, &PlainObject::class_, newTarget);
        if (!obj)
            return false;
    } else if (args.length() > 0 && !args[0].isNullOrUndefined()) {
        obj = ToObject(cx, args[0]);
        if (!obj)
            return false;
    } else {
        /* Make an object whether this was called with 'new' or not. */
        if (!NewObjectScriptedCall(cx, &obj))
            return false;
    }

    args.rval().setObject(*obj);
    return true;
}
bool
DirectProxyHandler::construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const
{
    assertEnteredPolicy(cx, proxy, JSID_VOID, CALL);

    RootedValue target(cx, proxy->as<ProxyObject>().private_());
    if (!IsConstructor(target)) {
        ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, target, nullptr);
        return false;
    }

    ConstructArgs cargs(cx);
    if (!FillArgumentsFromArraylike(cx, cargs, args))
        return false;

    return Construct(cx, target, cargs, args.newTarget(), args.rval());
}
bool
CrossCompartmentWrapper::construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
{
    RootedObject wrapped(cx, wrappedObject(wrapper));
    {
        AutoCompartment call(cx, wrapped);

        for (size_t n = 0; n < args.length(); ++n) {
            if (!cx->compartment()->wrap(cx, args[n]))
                return false;
        }
        if (!cx->compartment()->wrap(cx, args.newTarget()))
            return false;
        if (!Wrapper::construct(cx, wrapper, args))
            return false;
    }
    return cx->compartment()->wrap(cx, args.rval());
}
Beispiel #10
0
bool
MapObject::construct(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    if (!ThrowIfNotConstructing(cx, args, "Map"))
        return false;

    RootedObject proto(cx);
    RootedObject newTarget(cx, &args.newTarget().toObject());
    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
        return false;

    Rooted<MapObject*> obj(cx, MapObject::create(cx, proto));
    if (!obj)
        return false;

    if (!args.get(0).isNullOrUndefined()) {
        RootedValue adderVal(cx);
        if (!GetProperty(cx, obj, obj, cx->names().set, &adderVal))
            return false;

        if (!IsCallable(adderVal))
            return ReportIsNotFunction(cx, adderVal);

        bool isOriginalAdder = IsNativeFunction(adderVal, MapObject::set);
        RootedValue mapVal(cx, ObjectValue(*obj));
        FastCallGuard fig(cx, adderVal);
        InvokeArgs& args2 = fig.args();

        ForOfIterator iter(cx);
        if (!iter.init(args[0]))
            return false;

        RootedValue pairVal(cx);
        RootedObject pairObj(cx);
        RootedValue dummy(cx);
        Rooted<HashableValue> hkey(cx);
        ValueMap* map = obj->getData();
        while (true) {
            bool done;
            if (!iter.next(&pairVal, &done))
                return false;
            if (done)
                break;
            if (!pairVal.isObject()) {
                JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
                                     JSMSG_INVALID_MAP_ITERABLE, "Map");
                return false;
            }

            pairObj = &pairVal.toObject();
            if (!pairObj)
                return false;

            RootedValue key(cx);
            if (!GetElement(cx, pairObj, pairObj, 0, &key))
                return false;

            RootedValue val(cx);
            if (!GetElement(cx, pairObj, pairObj, 1, &val))
                return false;

            if (isOriginalAdder) {
                if (!hkey.setValue(cx, key))
                    return false;

                HeapPtr<Value> rval(val);
                if (!map->put(hkey, rval)) {
                    ReportOutOfMemory(cx);
                    return false;
                }
                WriteBarrierPost(cx->runtime(), map, key);
            } else {
                if (!args2.init(2))
                    return false;

                args2[0].set(key);
                args2[1].set(val);

                if (!fig.call(cx, adderVal, mapVal, &dummy))
                    return false;
            }
        }
    }

    args.rval().setObject(*obj);
    return true;
}
Beispiel #11
0
bool
SetObject::construct(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    if (!ThrowIfNotConstructing(cx, args, "Set"))
        return false;

    RootedObject proto(cx);
    RootedObject newTarget(cx, &args.newTarget().toObject());
    if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
        return false;

    Rooted<SetObject*> obj(cx, SetObject::create(cx, proto));
    if (!obj)
        return false;

    if (!args.get(0).isNullOrUndefined()) {
        RootedValue adderVal(cx);
        if (!GetProperty(cx, obj, obj, cx->names().add, &adderVal))
            return false;

        if (!IsCallable(adderVal))
            return ReportIsNotFunction(cx, adderVal);

        bool isOriginalAdder = IsNativeFunction(adderVal, SetObject::add);
        RootedValue setVal(cx, ObjectValue(*obj));
        FastCallGuard fig(cx, adderVal);
        InvokeArgs& args2 = fig.args();

        RootedValue keyVal(cx);
        ForOfIterator iter(cx);
        if (!iter.init(args[0]))
            return false;
        Rooted<HashableValue> key(cx);
        RootedValue dummy(cx);
        ValueSet* set = obj->getData();
        while (true) {
            bool done;
            if (!iter.next(&keyVal, &done))
                return false;
            if (done)
                break;

            if (isOriginalAdder) {
                if (!key.setValue(cx, keyVal))
                    return false;
                if (!set->put(key)) {
                    ReportOutOfMemory(cx);
                    return false;
                }
                WriteBarrierPost(cx->runtime(), set, keyVal);
            } else {
                if (!args2.init(1))
                    return false;

                args2[0].set(keyVal);

                if (!fig.call(cx, adderVal, setVal, &dummy))
                    return false;
            }
        }
    }

    args.rval().setObject(*obj);
    return true;
}
Beispiel #12
0
static bool
WeakMap_construct(JSContext* cx, unsigned argc, Value* vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);

    // ES6 draft rev 31 (15 Jan 2015) 23.3.1.1 step 1.
    if (!ThrowIfNotConstructing(cx, args, "WeakMap"))
        return false;

    RootedObject newTarget(cx, &args.newTarget().toObject());
    RootedObject obj(cx, CreateThis(cx, &WeakMapObject::class_, newTarget));
    if (!obj)
        return false;

    // Steps 5-6, 11.
    if (!args.get(0).isNullOrUndefined()) {
        // Steps 7a-b.
        RootedValue adderVal(cx);
        if (!GetProperty(cx, obj, obj, cx->names().set, &adderVal))
            return false;

        // Step 7c.
        if (!IsCallable(adderVal))
            return ReportIsNotFunction(cx, adderVal);

        bool isOriginalAdder = IsNativeFunction(adderVal, WeakMap_set);
        RootedValue mapVal(cx, ObjectValue(*obj));
        FastInvokeGuard fig(cx, adderVal);
        InvokeArgs& args2 = fig.args();

        // Steps 7d-e.
        JS::ForOfIterator iter(cx);
        if (!iter.init(args[0]))
            return false;

        RootedValue pairVal(cx);
        RootedObject pairObject(cx);
        RootedValue keyVal(cx);
        RootedObject keyObject(cx);
        RootedValue val(cx);
        while (true) {
            // Steps 12a-e.
            bool done;
            if (!iter.next(&pairVal, &done))
                return false;
            if (done)
                break;

            // Step 12f.
            if (!pairVal.isObject()) {
                JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
                                     JSMSG_INVALID_MAP_ITERABLE, "WeakMap");
                return false;
            }

            pairObject = &pairVal.toObject();
            if (!pairObject)
                return false;

            // Steps 12g-h.
            if (!GetElement(cx, pairObject, pairObject, 0, &keyVal))
                return false;

            // Steps 12i-j.
            if (!GetElement(cx, pairObject, pairObject, 1, &val))
                return false;

            // Steps 12k-l.
            if (isOriginalAdder) {
                if (keyVal.isPrimitive()) {
                    UniquePtr<char[], JS::FreePolicy> bytes =
                        DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, keyVal, nullptr);
                    if (!bytes)
                        return false;
                    JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, bytes.get());
                    return false;
                }

                keyObject = &keyVal.toObject();
                if (!SetWeakMapEntry(cx, obj, keyObject, val))
                    return false;
            } else {
                if (!args2.init(2))
                    return false;

                args2.setCallee(adderVal);
                args2.setThis(mapVal);
                args2[0].set(keyVal);
                args2[1].set(val);

                if (!fig.invoke(cx))
                    return false;
            }
        }
    }

    args.rval().setObject(*obj);
    return true;
}
// ES7 0c1bd3004329336774cbc90de727cd0cf5f11e93 9.5.14 Proxy.[[Construct]]
bool
ScriptedProxyHandler::construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const
{
    // Steps 1-3.
    RootedObject handler(cx, ScriptedProxyHandler::handlerObject(proxy));
    if (!handler) {
        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
        return false;
    }

    // Step 4.
    RootedObject target(cx, proxy->as<ProxyObject>().target());
    MOZ_ASSERT(target);
    MOZ_ASSERT(target->isConstructor());

    // Step 5.
    RootedValue trap(cx);
    if (!GetProxyTrap(cx, handler, cx->names().construct, &trap))
        return false;

    // Step 6.
    if (trap.isUndefined()) {
        ConstructArgs cargs(cx);
        if (!FillArgumentsFromArraylike(cx, cargs, args))
            return false;

        RootedValue targetv(cx, ObjectValue(*target));
        RootedObject obj(cx);
        if (!Construct(cx, targetv, cargs, args.newTarget(), &obj))
            return false;

        args.rval().setObject(*obj);
        return true;
    }

    // Step 7.
    RootedObject argArray(cx, NewDenseCopiedArray(cx, args.length(), args.array()));
    if (!argArray)
        return false;

    // Steps 8, 10.
    {
        FixedInvokeArgs<3> iargs(cx);

        iargs[0].setObject(*target);
        iargs[1].setObject(*argArray);
        iargs[2].set(args.newTarget());

        RootedValue thisv(cx, ObjectValue(*handler));
        if (!Call(cx, trap, thisv, iargs, args.rval()))
            return false;
    }

    // Step 9.
    if (!args.rval().isObject()) {
        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_PROXY_CONSTRUCT_OBJECT);
        return false;
    }

    return true;
}