From bccd5e3750e9009723be882d82a4afc60be6415d Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 16 Jun 2023 15:34:05 +0200 Subject: [PATCH] Fix #1538 - use same customElements Registry utilities (#1542) --- .pre-commit-config.yaml | 3 +- .../esm/{plugins.js => custom-types.js} | 105 +++++++++++++----- pyscript.core/esm/index.js | 87 +++------------ pyscript.core/esm/listeners.js | 71 ++++++++++++ pyscript.core/esm/worker/class.js | 2 +- pyscript.core/test/plugins/index.html | 21 +++- pyscript.core/test/plugins/lua.html | 12 +- pyscript.core/test/plugins/py-script.js | 6 +- 8 files changed, 194 insertions(+), 113 deletions(-) rename pyscript.core/esm/{plugins.js => custom-types.js} (63%) create mode 100644 pyscript.core/esm/listeners.js diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 14e99e2a..1abc5212 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: check-docstring-first - id: check-executables-have-shebangs - id: check-json - exclude: tsconfig.json pyscript.core/cjs/package.json + exclude: tsconfig\.json|pyscript\.core/cjs/package\.json - id: check-toml - id: check-xml - id: check-yaml @@ -46,6 +46,7 @@ repos: rev: "v3.0.0-alpha.6" hooks: - id: prettier + exclude: pyscript\.core/test args: [--tab-width, "4"] - repo: https://github.com/pre-commit/mirrors-eslint diff --git a/pyscript.core/esm/plugins.js b/pyscript.core/esm/custom-types.js similarity index 63% rename from pyscript.core/esm/plugins.js rename to pyscript.core/esm/custom-types.js index d51366e1..854882bb 100644 --- a/pyscript.core/esm/plugins.js +++ b/pyscript.core/esm/custom-types.js @@ -1,18 +1,23 @@ +import "@ungap/with-resolvers"; import { $$ } from "basic-devtools"; -import { create } from "./utils.js"; +import { assign, create } from "./utils.js"; import { getDetails } from "./script-handler.js"; -import { registry, configs } from "./interpreters.js"; +import { + registry as defaultRegistry, + prefixes, + configs, +} from "./interpreters.js"; import { getRuntimeID } from "./loader.js"; import { io } from "./interpreter/_utils.js"; +import { addAllListeners } from "./listeners.js"; import workerHooks from "./worker/hooks.js"; -export const PLUGINS_SELECTORS = []; +export const CUSTOM_SELECTORS = []; /** - * @typedef {Object} Runtime plugin configuration - * @prop {string} type the interpreter type + * @typedef {Object} Runtime custom configuration * @prop {object} interpreter the bootstrapped interpreter * @prop {(url:string, options?: object) => Worker} XWorker an XWorker constructor that defaults to same interpreter on the Worker. * @prop {object} config a cloned config used to bootstrap the interpreter @@ -22,23 +27,33 @@ export const PLUGINS_SELECTORS = []; */ const patched = new Map(); +const types = new Map(); +const waitList = new Map(); // REQUIRES INTEGRATION TEST /* c8 ignore start */ /** - * @param {Element} node any DOM element registered via plugin. + * @param {Element} node any DOM element registered via define. */ -export const handlePlugin = (node) => { - for (const name of PLUGINS_SELECTORS) { - if (node.matches(name)) { - const { options, known } = plugins.get(name); +export const handleCustomType = (node) => { + for (const selector of CUSTOM_SELECTORS) { + if (node.matches(selector)) { + const type = types.get(selector); + const { resolve } = waitList.get(type); + const { options, known } = registry.get(type); if (!known.has(node)) { known.add(node); - const { type, version, config, env, onRuntimeReady } = options; - const name = getRuntimeID(type, version); + const { + interpreter: runtime, + version, + config, + env, + onRuntimeReady, + } = options; + const name = getRuntimeID(runtime, version); const id = env || `${name}${config ? `|${config}` : ""}`; const { interpreter: engine, XWorker } = getDetails( - type, + runtime, id, name, version, @@ -46,7 +61,7 @@ export const handlePlugin = (node) => { ); engine.then((interpreter) => { if (!patched.has(id)) { - const module = create(registry.get(type)); + const module = create(defaultRegistry.get(runtime)); const { onBeforeRun, onBeforeRunAsync, @@ -120,9 +135,10 @@ export const handlePlugin = (node) => { }; patched.set(id, resolved); + resolve(resolved); } - onRuntimeReady(patched.get(id), node); + onRuntimeReady?.(patched.get(id), node); }); } } @@ -132,27 +148,58 @@ export const handlePlugin = (node) => { /** * @type {Map}>} */ -const plugins = new Map(); +const registry = new Map(); /** - * @typedef {Object} PluginOptions plugin configuration - * @prop {string} type the interpreter/interpreter type to receive + * @typedef {Object} PluginOptions custom configuration + * @prop {'pyodide' | 'micropython' | 'wasmoon' | 'ruby-wasm-wasi'} interpreter the interpreter to use * @prop {string} [version] the optional interpreter version to use * @prop {string} [config] the optional config to use within such interpreter - * @prop {string} [env] the optional environment to use - * @prop {(node: Element, interpreter: Runtime) => void} onRuntimeReady the callback that will be invoked once + * @prop {(environment: object, node: Element) => void} [onRuntimeReady] the callback that will be invoked once */ /** - * Allows plugins and components on the page to receive interpreters to execute any code. - * @param {string} name the unique plugin name - * @param {PluginOptions} options the plugin configuration + * Allows custom types and components on the page to receive interpreters to execute any code + * @param {string} type the unique ` - print('Hello Console!') + + def test_click(event): + print(event.type) + + print('Hello Console!') + diff --git a/pyscript.core/test/plugins/lua.html b/pyscript.core/test/plugins/lua.html index 32a154b6..921dc3f5 100644 --- a/pyscript.core/test/plugins/lua.html +++ b/pyscript.core/test/plugins/lua.html @@ -5,7 +5,7 @@ Plugins @@ -13,9 +13,9 @@ { "imports": { "@pyscript/core": "../../min.js" } } - print('Hello Console!') + + print('Hello Console!') + diff --git a/pyscript.core/test/plugins/py-script.js b/pyscript.core/test/plugins/py-script.js index 35f0657b..8b05d7b2 100644 --- a/pyscript.core/test/plugins/py-script.js +++ b/pyscript.core/test/plugins/py-script.js @@ -1,4 +1,4 @@ -import { registerPlugin } from "@pyscript/core"; +import { define } from "@pyscript/core"; // append ASAP CSS to avoid showing content document.head.appendChild(document.createElement("style")).textContent = ` @@ -17,9 +17,9 @@ let bootstrap = true, const sharedPyodide = new Promise((resolve) => { const pyConfig = document.querySelector("py-config"); const config = pyConfig?.getAttribute("src") || pyConfig?.textContent; - registerPlugin("py-script", { + define("py", { config, - type: "pyodide", + interpreter: "pyodide", codeBeforeRunWorker: `print('codeBeforeRunWorker')`, codeAfterRunWorker: `print('codeAfterRunWorker')`, onBeforeRun(pyodide, node) {