| 145 | exceptionTracker->onError(jsEntry.exceptionTracker.extractError()); |
| 146 | } |
| 147 | return Value::undefined(); |
| 148 | } |
| 149 | |
| 150 | auto retValue = callJsFunction(jsEntry, jsValue, parameters, parametersSize, ignoreRetValue); |
| 151 | if (!jsEntry.exceptionTracker && exceptionTracker != nullptr) { |
| 152 | exceptionTracker->onError(jsEntry.exceptionTracker.extractError()); |
| 153 | } |
| 154 | |
| 155 | if (_isSingleCall) { |
| 156 | clearJsValue(jsEntry.jsContext); |
| 157 | } |
| 158 | |
| 159 | return retValue; |
| 160 | } |
| 161 | |
| 162 | void ValueFunctionWithJSValue::setIgnoreIfValdiContextIsDestroyed(bool ignoreIfValdiContextIsDestroyed) { |
| 163 | _ignoreIfValdiContextIsDestroyed = ignoreIfValdiContextIsDestroyed; |
| 164 | } |
| 165 | |
| 166 | static Valdi::SmallVector<Value, 2> captureParameters(const Value* parameters, size_t parametersSize) { |
| 167 | return Valdi::SmallVector<Value, 2>(parameters, parameters + parametersSize); |
| 168 | } |
| 169 | |
| 170 | static Valdi::SmallVector<Value, 2> captureParameters(const ValueFunctionCallContext& callContext) { |
| 171 | return captureParameters(callContext.getParameters(), callContext.getParametersSize()); |
| 172 | } |
| 173 | |
| 174 | struct MainThreadThrottledCall : public SimpleRefCountable { |
| 175 | std::promise<void> promise; |
| 176 | int callId; |
| 177 | Valdi::SmallVector<Value, 2> parameters; |
| 178 | |
| 179 | MainThreadThrottledCall(int callId, Valdi::SmallVector<Value, 2>&& parameters) |
| 180 | : callId(callId), parameters(std::move(parameters)) {} |
| 181 | ~MainThreadThrottledCall() override = default; |
| 182 | }; |
| 183 | |
| 184 | Result<Value> ValueFunctionWithJSValue::dispatchAndWaitOnJsThread(const Ref<JavaScriptTaskScheduler>& taskScheduler, |
| 185 | const std::chrono::steady_clock::time_point& deadline, |
| 186 | const Value* parameters, |
| 187 | size_t parametersSize) { |
| 188 | auto promise = std::make_shared<std::promise<Result<Value>>>(); |
| 189 | auto future = promise->get_future(); |
| 190 | |
| 191 | // The JS callback may need locks this thread holds (e.g. the ViewNodeTree lock when the call |
| 192 | // originates from the scroll path); suspend them while parked so the JS thread can make |
| 193 | // progress instead of stalling until the deadline. Same pattern as |
| 194 | // DeferredViewTransaction::flush before dispatchSync. |
| 195 | DropAllTrackedLocks dropAllTrackedLocks; |
| 196 | |
| 197 | taskScheduler->dispatchOnJsThreadAsync( |
| 198 | getContext(), |
| 199 | getANRAttribution(), |
| 200 | [self = strongSmallRef(this), parameters = captureParameters(parameters, parametersSize), promise]( |
| 201 | auto& jsEntry) { |
| 202 | MainThreadBatchAllowScope mainThreadBatchAllowScope; |
| 203 | auto result = self->doJsCall(jsEntry, parameters.data(), parameters.size(), nullptr, false); |
| 204 | promise->set_value(Result(std::move(result))); |
nothing calls this directly
no test coverage detected