| 145 | ~MainThreadThrottledCall() override = default; |
| 146 | }; |
| 147 | |
| 148 | Result<Value> ValueFunctionWithJSValue::dispatchAndWaitOnJsThread(const Ref<JavaScriptTaskScheduler>& taskScheduler, |
| 149 | const std::chrono::steady_clock::time_point& deadline, |
| 150 | const Value* parameters, |
| 151 | size_t parametersSize) { |
| 152 | auto promise = std::make_shared<std::promise<Result<Value>>>(); |
| 153 | auto future = promise->get_future(); |
| 154 | |
| 155 | taskScheduler->dispatchOnJsThreadAsync( |
| 156 | getContext(), |
| 157 | [self = strongSmallRef(this), parameters = captureParameters(parameters, parametersSize), promise]( |
| 158 | auto& jsEntry) { |
| 159 | MainThreadBatchAllowScope mainThreadBatchAllowScope; |
| 160 | auto result = self->doJsCall(jsEntry, parameters.data(), parameters.size(), nullptr, false); |
| 161 | promise->set_value(Result(std::move(result))); |
| 162 | }); |
| 163 | |
| 164 | if (std::future_status::ready == future.wait_until(deadline)) { |
| 165 | return future.get(); |
| 166 | } |
| 167 | |
| 168 | return Error("JS function timeout"); |
| 169 | } |
| 170 | |
| 171 | Value ValueFunctionWithJSValue::callSync(ValueFunctionFlags flags, |
| 172 | const Ref<JavaScriptTaskScheduler>& taskScheduler, |
| 173 | const ValueFunctionCallContext& callContext) { |
| 174 | auto retValue = Value::undefined(); |
| 175 | getContext()->withAttribution([&]() { |
| 176 | auto shouldStartMainThreadBatch = |
| 177 | _shouldBlockMainThread && _mainThreadManager != nullptr && _mainThreadManager->currentThreadIsMainThread(); |
| 178 | auto propagatesError = ((flags & ValueFunctionFlagsPropagatesError) != ValueFunctionFlagsNone); |
| 179 | |
| 180 | if (shouldStartMainThreadBatch) { |
| 181 | _mainThreadManager->beginBatch(); |
| 182 | |
| 183 | if ((flags & ValueFunctionFlagsAllowThrottling) != ValueFunctionFlagsNone) { |
| 184 | // When using a main thread batch with allow throttling, we only allow locking |
| 185 | // the main thread for up to 100ms |
| 186 | |
| 187 | auto throttledCall = |
| 188 | makeShared<MainThreadThrottledCall>(++_callSequence, captureParameters(callContext)); |
| 189 | auto future = throttledCall->promise.get_future(); |
| 190 | |
| 191 | taskScheduler->dispatchOnJsThreadAsync( |
| 192 | getContext(), [self = strongSmallRef(this), throttledCall](auto& jsEntry) { |
| 193 | auto currentCallId = self->_callSequence.load(); |
| 194 | if (currentCallId != throttledCall->callId) { |
| 195 | // Throttling call, our callId doesn't match what is in the |
| 196 | // sequence. |
| 197 | throttledCall->promise.set_value(); |
| 198 | return; |
| 199 | } |
| 200 | |
| 201 | MainThreadBatchAllowScope mainThreadBatchAllowScope; |
| 202 | self->doJsCall( |
| 203 | jsEntry, throttledCall->parameters.data(), throttledCall->parameters.size(), nullptr, true); |
| 204 | throttledCall->promise.set_value(); |
nothing calls this directly
no test coverage detected