MCPcopy
hub / github.com/pyodide/pyodide / callPyObjectKwargsPromising

Function callPyObjectKwargsPromising

src/core/pyproxy.ts:576–651  ·  view source on GitHub ↗

* A version of callPyObjectKwargs that supports the JSPI. * * It returns a promise. Inside Python, JS promises can be syncified, which * switches the stack to synchronously wait for them to be resolved. * * Pretty much everything is the same as callPyObjectKwargs except we use the * special JS

(
  ptrobj: number,
  jsargs: any,
  kwargs: any,
)

Source from the content-addressed store, hash-verified

574 * _pyproxy_apply with the same arguments we gave to `promisingApply`.
575 */
576async function callPyObjectKwargsPromising(
577 ptrobj: number,
578 jsargs: any,
579 kwargs: any,
580) {
581 if (!Module.jspiSupported) {
582 throw new Error(
583 "WebAssembly stack switching not supported in this JavaScript runtime",
584 );
585 }
586 // We don't do any checking for kwargs, checks are in PyProxy.callKwargs
587 // which only is used when the keyword arguments come from the user.
588 const num_pos_args = jsargs.length;
589 const kwargs_names = Object.keys(kwargs);
590 const kwargs_values = Object.values(kwargs);
591 const num_kwargs = kwargs_names.length;
592 jsargs.push(...kwargs_values);
593 // We have to take ownership of the pointer before we sleep or else it could
594 // get freed out from under us. This also fixes a bug that was around before
595 // we added the sleep.
596 _Py_IncRef(ptrobj);
597 // Yield to the event loop before starting the task. We may have been called by
598 // WebAssembly stack frames which own data on the stack. We can't overwrite that
599 // data until those stack frames are finished with it. Returning to the event
600 // loop first unwinds all the caller frames. That way enterTask() is free to
601 // place the task wherever it likes.
602 await new Promise<void>((res) => API.scheduleCallback(res, 0));
603 let result;
604 const exc = _malloc(4);
605 try {
606 // enterTask() decides where the stackStop of the new task should be.
607 enterTask();
608 Py_ENTER();
609 // promisingApply clears the error flag and saves any error into excStatus.
610 // This ensures that tasks that are run between when promisingApply resolves
611 // and when this task resumes here won't incorrectly observe the error flag.
612 // See test_stack_switching.test_throw_from_switcher for a detailed
613 // explanation.
614 //
615 // The result of promisingApply() is wrapped in a one element list
616 // (regardless of whether there was an error or not) to ensure that we only
617 // await the stack switches and not a thenable result.
618 result = await Module.promisingApply(
619 ptrobj,
620 jsargs,
621 num_pos_args,
622 kwargs_names,
623 num_kwargs,
624 exc,
625 );
626 Py_EXIT();
627 } catch (e) {
628 API.fatal_error(e);
629 }
630 try {
631 // Unwrap result
632 result = result[0];
633 if (result === Module.error) {

Callers 3

pyproxy.tsFile · 0.85
callPromisingMethod · 0.85
callPromisingKwargsMethod · 0.85

Calls 5

enterTaskFunction · 0.85
_ensure_futureMethod · 0.80
keysMethod · 0.45
valuesMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…