| 1120 | } |
| 1121 | |
| 1122 | static bool array_find(JSContext *cx, unsigned argc, JS::Value *vp) { |
| 1123 | JS::CallArgs args = JS::CallArgsFromVp(argc, vp); |
| 1124 | |
| 1125 | if (!args.requireAtLeast(cx, "find", 1)) { |
| 1126 | return false; |
| 1127 | } |
| 1128 | |
| 1129 | JS::RootedObject proxy(cx, JS::ToObject(cx, args.thisv())); |
| 1130 | if (!proxy) { |
| 1131 | return false; |
| 1132 | } |
| 1133 | PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot); |
| 1134 | |
| 1135 | JS::Value callbackfn = args[0].get(); |
| 1136 | |
| 1137 | if (!callbackfn.isObject() || !JS::IsCallable(&callbackfn.toObject())) { |
| 1138 | JS_ReportErrorNumberASCII(cx, js::GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION, "find: callback"); |
| 1139 | return false; |
| 1140 | } |
| 1141 | |
| 1142 | JS::RootedValue selfValue(cx, jsTypeFactory(cx, self)); |
| 1143 | JS::RootedValue callBack(cx, callbackfn); |
| 1144 | |
| 1145 | JS::Rooted<JS::ValueArray<3>> jArgs(cx); |
| 1146 | JS::RootedValue rval(cx); |
| 1147 | |
| 1148 | JS::RootedObject rootedThisArg(cx); |
| 1149 | if (args.length() > 1) { |
| 1150 | JS::Value thisArg = args[1].get(); |
| 1151 | if (!thisArg.isObjectOrNull()) { |
| 1152 | JS_ReportErrorNumberASCII(cx, js::GetErrorMessage, nullptr, JSMSG_NOT_OBJORNULL, "'this' argument"); |
| 1153 | return false; |
| 1154 | } |
| 1155 | |
| 1156 | // TODO support null, currently gets TypeError |
| 1157 | rootedThisArg.set(thisArg.toObjectOrNull()); |
| 1158 | // check if callback is a PyMethod, need to make a new method bound to thisArg |
| 1159 | if (!makeNewPyMethod(cx, &callBack, rootedThisArg)) { |
| 1160 | return false; |
| 1161 | } |
| 1162 | } |
| 1163 | else { |
| 1164 | rootedThisArg.set(nullptr); |
| 1165 | } |
| 1166 | |
| 1167 | Py_ssize_t len = PyList_GET_SIZE(self); |
| 1168 | for (Py_ssize_t index = 0, toIndex = 0; index < len; index++) { |
| 1169 | JS::Value item = jsTypeFactory(cx, PyList_GetItem(self, index)); |
| 1170 | jArgs[0].set(item); |
| 1171 | jArgs[1].setInt32(index); |
| 1172 | jArgs[2].set(selfValue); |
| 1173 | |
| 1174 | if (!JS_CallFunctionValue(cx, rootedThisArg, callBack, jArgs, &rval)) { |
| 1175 | return false; |
| 1176 | } |
| 1177 | |
| 1178 | if (rval.toBoolean()) { |
| 1179 | args.rval().set(item); |
nothing calls this directly
no test coverage detected