Files
pyscript/pyscript.core/esm/index.js
Andrea Giammarchi f6dfc5361e Implement PyScript custom <script type> (#1548)
* updated MicroPython to latest in order to have `globals` API available
  * reduced code around helpers for both MicroPython and Pyodide as now these are more aligned
  * updated all dependencies and brought in latest [coincident/window](https://github.com/WebReflection/coincident#coincidentwindow) goodness to any `xworker`, preserving the `sync` previous behavior
  * using [@ungap/structured-clone/json](https://github.com/ungap/structured-clone#tojson) as *coincident* default `parse` and `stringify` utility to allow recursive and more complex data to travel back from the *Worker* (forward data is still fully [structured clone algorithm compatible](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm))
  * renamed all *plugin/s* references to *custom/s* as plugin as a word was too misleading
  * changed *custom types* helpers logic to allow any single node to have its own version of the interpreter wrapper, and all the extra fields it carries with it, including a way to augment every interpreter execution, among as every worker code execution
  * created a `custom` folder where I've landed the very first `pyscript.js` custom type
  * created an exhaustive test page to demonstrate the current abilities of *PyScript Next* among its ability to expose utilities that can be used to create *PyScript* plugins
2023-06-22 17:29:07 +02:00

69 lines
2.3 KiB
JavaScript

import { $$ } from "basic-devtools";
import xworker from "./worker/class.js";
import { handle } from "./script-handler.js";
import { assign } from "./utils.js";
import { selectors, prefixes } from "./interpreters.js";
import { CUSTOM_SELECTORS, handleCustomType } from "./custom.js";
import { listener, addAllListeners } from "./listeners.js";
export { define, whenDefined } from "./custom.js";
export const XWorker = xworker();
const INTERPRETER_SELECTORS = selectors.join(",");
const mo = new MutationObserver((records) => {
for (const { type, target, attributeName, addedNodes } of records) {
// attributes are tested via integration / e2e
/* c8 ignore next 17 */
if (type === "attributes") {
const i = attributeName.lastIndexOf("-") + 1;
if (i) {
const prefix = attributeName.slice(0, i);
for (const p of prefixes) {
if (prefix === p) {
const type = attributeName.slice(i);
if (type !== "env") {
const method = target.hasAttribute(attributeName)
? "add"
: "remove";
target[`${method}EventListener`](type, listener);
}
break;
}
}
}
continue;
}
for (const node of addedNodes) {
if (node.nodeType === 1) {
addAllListeners(node);
if (node.matches(INTERPRETER_SELECTORS)) handle(node);
else {
$$(INTERPRETER_SELECTORS, node).forEach(handle);
if (!CUSTOM_SELECTORS.length) continue;
handleCustomType(node);
$$(CUSTOM_SELECTORS.join(","), node).forEach(
handleCustomType,
);
}
}
}
}
});
const observe = (root) => {
mo.observe(root, { childList: true, subtree: true, attributes: true });
return root;
};
const { attachShadow } = Element.prototype;
assign(Element.prototype, {
attachShadow(init) {
return observe(attachShadow.call(this, init));
},
});
addAllListeners(observe(document));
$$(INTERPRETER_SELECTORS, document).forEach(handle);