mirror of
https://github.com/pyscript/pyscript.git
synced 2026-02-13 07:01:00 -05:00
Improved py:all-done event (#1778)
This commit is contained in:
committed by
GitHub
parent
fdc35ce3ed
commit
50f7ab0f34
8
pyscript.core/package-lock.json
generated
8
pyscript.core/package-lock.json
generated
@@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"polyscript": "^0.4.8",
|
||||
"polyscript": "^0.4.11",
|
||||
"type-checked-collections": "^0.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -1782,9 +1782,9 @@
|
||||
"integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA=="
|
||||
},
|
||||
"node_modules/polyscript": {
|
||||
"version": "0.4.8",
|
||||
"resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.4.8.tgz",
|
||||
"integrity": "sha512-YlgjdMeEnv/i6WOqkh7gc52iSPY1l/psA+egu7z1GNrjwq6udw4WuQPz3rHRbaFhTUdYsVulLd8SBugjbVH6sQ==",
|
||||
"version": "0.4.11",
|
||||
"resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.4.11.tgz",
|
||||
"integrity": "sha512-wNvCUJp003OR/Q9C0eZJ84MHYeJiMtPTt1pqtsRQ0odRV/M1b3qVQ23oD5DAjq1weXQv1EdfpILwFOpw6VnirA==",
|
||||
"dependencies": {
|
||||
"@ungap/structured-clone": "^1.2.0",
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"polyscript": "^0.4.8",
|
||||
"polyscript": "^0.4.11",
|
||||
"type-checked-collections": "^0.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,62 +1,17 @@
|
||||
import TYPES from "./types.js";
|
||||
import hooks from "./hooks.js";
|
||||
|
||||
const DONE = "py:all-done";
|
||||
|
||||
const {
|
||||
onAfterRun,
|
||||
onAfterRunAsync,
|
||||
codeAfterRunWorker,
|
||||
codeAfterRunWorkerAsync,
|
||||
} = hooks;
|
||||
|
||||
const waitForIt = [];
|
||||
const codes = [];
|
||||
|
||||
const codeFor = (element) => {
|
||||
const isAsync = element.hasAttribute("async");
|
||||
const { promise, resolve } = Promise.withResolvers();
|
||||
const type = `${DONE}:${waitForIt.push(promise)}`;
|
||||
|
||||
// resolve each promise once notified
|
||||
addEventListener(type, resolve, { once: true });
|
||||
|
||||
if (element.hasAttribute("worker")) {
|
||||
const code = `
|
||||
from pyscript import window as _w
|
||||
_w.dispatchEvent(_w.Event.new("${type}"))
|
||||
`;
|
||||
if (isAsync) codeAfterRunWorkerAsync.add(code);
|
||||
else codeAfterRunWorker.add(code);
|
||||
return code;
|
||||
for (const [TYPE] of TYPES) {
|
||||
const selectors = [`script[type="${TYPE}"]`, `${TYPE}-script`];
|
||||
for (const element of document.querySelectorAll(selectors.join(","))) {
|
||||
const { promise, resolve } = Promise.withResolvers();
|
||||
waitForIt.push(promise);
|
||||
element.addEventListener(`${TYPE}:done`, resolve, { once: true });
|
||||
}
|
||||
|
||||
// dispatch only once the ready element is the same
|
||||
const code = (_, el) => {
|
||||
if (el === element) dispatchEvent(new Event(type));
|
||||
};
|
||||
|
||||
if (isAsync) onAfterRunAsync.add(code);
|
||||
else onAfterRun.add(code);
|
||||
return code;
|
||||
};
|
||||
|
||||
const selector = [];
|
||||
for (const [TYPE] of TYPES)
|
||||
selector.push(`script[type="${TYPE}"]`, `${TYPE}-script`);
|
||||
|
||||
// loop over all known scripts and elements
|
||||
for (const element of document.querySelectorAll(selector.join(",")))
|
||||
codes.push(codeFor(element));
|
||||
}
|
||||
|
||||
// wait for all the things then cleanup
|
||||
Promise.all(waitForIt).then(() => {
|
||||
// cleanup unnecessary hooks
|
||||
for (const code of codes) {
|
||||
onAfterRun.delete(code);
|
||||
onAfterRunAsync.delete(code);
|
||||
codeAfterRunWorker.delete(code);
|
||||
codeAfterRunWorkerAsync.delete(code);
|
||||
}
|
||||
dispatchEvent(new Event(DONE));
|
||||
dispatchEvent(new Event("py:all-done"));
|
||||
});
|
||||
|
||||
@@ -90,6 +90,11 @@ const exportedConfig = {};
|
||||
export { exportedConfig as config, hooks };
|
||||
|
||||
for (const [TYPE, interpreter] of TYPES) {
|
||||
const dispatchDone = (element, isAsync, result) => {
|
||||
if (isAsync) result.then(() => dispatch(element, TYPE, "done"));
|
||||
else dispatch(element, TYPE, "done");
|
||||
};
|
||||
|
||||
const { config, plugins, error } = configs.get(TYPE);
|
||||
|
||||
// create a unique identifier when/if needed
|
||||
@@ -211,9 +216,13 @@ for (const [TYPE, interpreter] of TYPES) {
|
||||
defineProperty(element, "target", { value: show });
|
||||
|
||||
// notify before the code runs
|
||||
dispatch(element, TYPE);
|
||||
wrap[`run${isAsync ? "Async" : ""}`](
|
||||
await fetchSource(element, wrap.io, true),
|
||||
dispatch(element, TYPE, "ready");
|
||||
dispatchDone(
|
||||
element,
|
||||
isAsync,
|
||||
wrap[`run${isAsync ? "Async" : ""}`](
|
||||
await fetchSource(element, wrap.io, true),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// resolve PyScriptElement to allow connectedCallback
|
||||
@@ -246,18 +255,21 @@ for (const [TYPE, interpreter] of TYPES) {
|
||||
async connectedCallback() {
|
||||
if (!this.executed) {
|
||||
this.executed = true;
|
||||
const isAsync = this.hasAttribute("async");
|
||||
const { io, run, runAsync } = await this._wrap.promise;
|
||||
const runner = this.hasAttribute("async") ? runAsync : run;
|
||||
this.srcCode = await fetchSource(
|
||||
this,
|
||||
io,
|
||||
!this.childElementCount,
|
||||
);
|
||||
this.replaceChildren();
|
||||
// notify before the code runs
|
||||
dispatch(this, TYPE);
|
||||
runner(this.srcCode);
|
||||
this.style.display = "block";
|
||||
dispatch(this, TYPE, "ready");
|
||||
dispatchDone(
|
||||
this,
|
||||
isAsync,
|
||||
(isAsync ? runAsync : run)(this.srcCode),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
pyscript.core/test/display.html
Normal file
30
pyscript.core/test/display.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PyScript Next</title>
|
||||
<script>
|
||||
addEventListener("py:all-done", ({ type }) => console.log(type));
|
||||
</script>
|
||||
<link rel="stylesheet" href="../dist/core.css">
|
||||
<script type="module" src="../dist/core.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="py" worker async>
|
||||
from pyscript import display
|
||||
display('hello 1')
|
||||
|
||||
import js
|
||||
import time
|
||||
js.console.log('sleeping...')
|
||||
time.sleep(2)
|
||||
js.console.log('...done')
|
||||
</script>
|
||||
<p>hello 2</p>
|
||||
<script type="py" worker async>
|
||||
from pyscript import display
|
||||
display('hello 3')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user