Added py:all-done event (#1756)

This commit is contained in:
Andrea Giammarchi
2023-09-26 15:56:50 +02:00
committed by GitHub
parent b9a1227e47
commit 3ac2ac0982
11 changed files with 239 additions and 74 deletions

View File

@@ -0,0 +1,62 @@
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;
}
// 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));
});

View File

@@ -1,16 +1,21 @@
/*! (c) PyScript Development Team */
import "@ungap/with-resolvers";
import { INVALID_CONTENT, define, XWorker } from "polyscript";
// TODO: this is not strictly polyscript related but handy ... not sure
// we should factor this utility out a part but this works anyway.
// These imports can hook more than usual and help debugging possible polyscript issues
import {
INVALID_CONTENT,
define,
XWorker,
} from "../node_modules/polyscript/esm/index.js";
import { queryTarget } from "../node_modules/polyscript/esm/script-handler.js";
import { dedent, dispatch } from "../node_modules/polyscript/esm/utils.js";
import { Hook } from "../node_modules/polyscript/esm/worker/hooks.js";
import "./all-done.js";
import TYPES from "./types.js";
import configs from "./config.js";
import hooks from "./hooks.js";
import sync from "./sync.js";
import stdlib from "./stdlib.js";
import { ErrorCode } from "./exceptions.js";
@@ -66,28 +71,6 @@ const registerModule = ({ XWorker: $XWorker, interpreter, io }) => {
interpreter.runPython(stdlib, { globals: interpreter.runPython("{}") });
};
export const hooks = {
/** @type {Set<function>} */
onBeforeRun: new Set(),
/** @type {Set<function>} */
onBeforeRunAsync: new Set(),
/** @type {Set<function>} */
onAfterRun: new Set(),
/** @type {Set<function>} */
onAfterRunAsync: new Set(),
/** @type {Set<function>} */
onInterpreterReady: new Set(),
/** @type {Set<string>} */
codeBeforeRunWorker: new Set(),
/** @type {Set<string>} */
codeBeforeRunWorkerAsync: new Set(),
/** @type {Set<string>} */
codeAfterRunWorker: new Set(),
/** @type {Set<string>} */
codeAfterRunWorkerAsync: new Set(),
};
const workerHooks = {
codeBeforeRunWorker: () =>
[stdlib, ...hooks.codeBeforeRunWorker].map(dedent).join("\n"),
@@ -100,7 +83,7 @@ const workerHooks = {
};
const exportedConfig = {};
export { exportedConfig as config };
export { exportedConfig as config, hooks };
for (const [TYPE, interpreter] of TYPES) {
const { config, plugins, error } = configs.get(TYPE);

View File

@@ -0,0 +1,21 @@
export default {
/** @type {Set<function>} */
onBeforeRun: new Set(),
/** @type {Set<function>} */
onBeforeRunAsync: new Set(),
/** @type {Set<function>} */
onAfterRun: new Set(),
/** @type {Set<function>} */
onAfterRunAsync: new Set(),
/** @type {Set<function>} */
onInterpreterReady: new Set(),
/** @type {Set<string>} */
codeBeforeRunWorker: new Set(),
/** @type {Set<string>} */
codeBeforeRunWorkerAsync: new Set(),
/** @type {Set<string>} */
codeAfterRunWorker: new Set(),
/** @type {Set<string>} */
codeAfterRunWorkerAsync: new Set(),
};