| 741 | } |
| 742 | |
| 743 | static bool array_map(JSContext *cx, unsigned argc, JS::Value *vp) { |
| 744 | JS::CallArgs args = JS::CallArgsFromVp(argc, vp); |
| 745 | |
| 746 | if (!args.requireAtLeast(cx, "map", 1)) { |
| 747 | return false; |
| 748 | } |
| 749 | |
| 750 | JS::RootedObject proxy(cx, JS::ToObject(cx, args.thisv())); |
| 751 | if (!proxy) { |
| 752 | return false; |
| 753 | } |
| 754 | PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot); |
| 755 | |
| 756 | JS::Value callbackfn = args[0].get(); |
| 757 | |
| 758 | if (!callbackfn.isObject() || !JS::IsCallable(&callbackfn.toObject())) { |
| 759 | // Decompiling the faulty arg is not accessible through the JSAPI so we do the best effort for the error message |
| 760 | JS_ReportErrorNumberASCII(cx, js::GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION, "map: callback"); |
| 761 | return false; |
| 762 | } |
| 763 | |
| 764 | Py_ssize_t len = PyList_GET_SIZE(self); |
| 765 | |
| 766 | JSObject *retArray = JS::NewArrayObject(cx, len); |
| 767 | JS::RootedObject rootedRetArray(cx, retArray); |
| 768 | |
| 769 | JS::RootedValue selfValue(cx, jsTypeFactory(cx, self)); |
| 770 | JS::RootedValue callBack(cx, callbackfn); |
| 771 | |
| 772 | JS::Rooted<JS::ValueArray<3>> jArgs(cx); |
| 773 | JS::RootedValue rval(cx); |
| 774 | |
| 775 | JS::RootedObject rootedThisArg(cx); |
| 776 | if (args.length() > 1) { |
| 777 | JS::Value thisArg = args[1].get(); |
| 778 | if (!thisArg.isObjectOrNull()) { |
| 779 | JS_ReportErrorNumberASCII(cx, js::GetErrorMessage, nullptr, JSMSG_NOT_OBJORNULL, "'this' argument"); |
| 780 | return false; |
| 781 | } |
| 782 | |
| 783 | // TODO support null, currently gets TypeError |
| 784 | rootedThisArg.set(thisArg.toObjectOrNull()); |
| 785 | // check if callback is a PyMethod, need to make a new method bound to thisArg |
| 786 | if (!makeNewPyMethod(cx, &callBack, rootedThisArg)) { |
| 787 | return false; |
| 788 | } |
| 789 | } |
| 790 | else { |
| 791 | rootedThisArg.set(nullptr); |
| 792 | } |
| 793 | |
| 794 | for (Py_ssize_t index = 0; index < len; index++) { |
| 795 | jArgs[0].set(jsTypeFactory(cx, PyList_GetItem(self, index))); |
| 796 | jArgs[1].setInt32(index); |
| 797 | jArgs[2].set(selfValue); |
| 798 | |
| 799 | if (!JS_CallFunctionValue(cx, rootedThisArg, callBack, jArgs, &rval)) { |
| 800 | return false; |
nothing calls this directly
no test coverage detected