| 680 | } |
| 681 | |
| 682 | static bool array_forEach(JSContext *cx, unsigned argc, JS::Value *vp) { |
| 683 | JS::CallArgs args = JS::CallArgsFromVp(argc, vp); |
| 684 | |
| 685 | if (!args.requireAtLeast(cx, "forEach", 1)) { |
| 686 | return false; |
| 687 | } |
| 688 | |
| 689 | JS::RootedObject proxy(cx, JS::ToObject(cx, args.thisv())); |
| 690 | if (!proxy) { |
| 691 | return false; |
| 692 | } |
| 693 | PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot); |
| 694 | |
| 695 | JS::Value callbackfn = args[0].get(); |
| 696 | |
| 697 | if (!callbackfn.isObject() || !JS::IsCallable(&callbackfn.toObject())) { |
| 698 | JS_ReportErrorNumberASCII(cx, js::GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION, "forEach: callback"); |
| 699 | return false; |
| 700 | } |
| 701 | |
| 702 | JS::RootedValue selfValue(cx, jsTypeFactory(cx, self)); |
| 703 | JS::RootedValue callBack(cx, callbackfn); |
| 704 | |
| 705 | JS::Rooted<JS::ValueArray<3>> jArgs(cx); |
| 706 | JS::RootedValue rval(cx); |
| 707 | |
| 708 | Py_ssize_t len = PyList_GET_SIZE(self); |
| 709 | |
| 710 | JS::RootedObject rootedThisArg(cx); |
| 711 | |
| 712 | if (args.length() > 1) { |
| 713 | JS::Value thisArg = args[1].get(); |
| 714 | if (!thisArg.isObjectOrNull()) { |
| 715 | JS_ReportErrorNumberASCII(cx, js::GetErrorMessage, nullptr, JSMSG_NOT_OBJORNULL, "'this' argument"); |
| 716 | return false; |
| 717 | } |
| 718 | // TODO support null, currently gets TypeError |
| 719 | rootedThisArg.set(thisArg.toObjectOrNull()); |
| 720 | // check if callback is a PyMethod, need to make a new method bound to thisArg |
| 721 | if (!makeNewPyMethod(cx, &callBack, rootedThisArg)) { |
| 722 | return false; |
| 723 | } |
| 724 | } |
| 725 | else { |
| 726 | rootedThisArg.set(nullptr); |
| 727 | } |
| 728 | |
| 729 | for (Py_ssize_t index = 0; index < len; index++) { |
| 730 | jArgs[0].set(jsTypeFactory(cx, PyList_GetItem(self, index))); |
| 731 | jArgs[1].setInt32(index); |
| 732 | jArgs[2].set(selfValue); |
| 733 | |
| 734 | if (!JS_CallFunctionValue(cx, rootedThisArg, callBack, jArgs, &rval)) { |
| 735 | return false; |
| 736 | } |
| 737 | } |
| 738 | |
| 739 | args.rval().setUndefined(); |
nothing calls this directly
no test coverage detected