// 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; }
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; }
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; }
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()); }
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; }
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; }
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; }