Allow nodes in shadow roots to be addressed via Element (#1454)

This commit is contained in:
Andrea Giammarchi
2023-05-09 17:42:09 +02:00
committed by GitHub
parent 82e5b64bad
commit d3bcd87cfa
8 changed files with 76 additions and 5 deletions

View File

@@ -1,5 +1,6 @@
import { $$, $x } from 'basic-devtools';
import { shadowRoots } from '../shadow_roots';
import { ltrim, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
import { getLogger } from '../logger';
import { pyExec, displayPyException } from '../pyexec';
@@ -174,7 +175,9 @@ export function make_PyScript(interpreter: InterpreterClient, app: PyScriptApp)
const { attachShadow } = Element.prototype;
Object.assign(Element.prototype, {
attachShadow(init: ShadowRootInit) {
return observe(attachShadow.call(this as Element, init));
const shadowRoot = observe(attachShadow.call(this as Element, init));
shadowRoots.add(shadowRoot);
return shadowRoot;
},
});

View File

@@ -2,6 +2,7 @@ import time
from textwrap import dedent
import js
from _pyscript_js import deepQuerySelector
from . import _internal
from ._mime import format_mime as _format_mime
@@ -55,7 +56,7 @@ class Element:
def element(self):
"""Return the dom element"""
if not self._element:
self._element = js.document.querySelector(f"#{self._id}")
self._element = deepQuerySelector(f"#{self._id}")
return self._element
@property

View File

@@ -9,6 +9,7 @@ import type { ProxyMarked } from 'synclink';
import * as Synclink from 'synclink';
import { showWarning } from './utils';
import { define_custom_element } from './plugin';
import { deepQuerySelector } from './shadow_roots';
import { python_package } from './python_package';
@@ -100,7 +101,7 @@ export class RemoteInterpreter extends Object {
*/
async loadInterpreter(config: AppConfig, stdio: Synclink.Remote<Stdio & ProxyMarked>): Promise<void> {
// TODO: move this to "main thread"!
const _pyscript_js_main = { define_custom_element, showWarning };
const _pyscript_js_main = { define_custom_element, showWarning, deepQuerySelector };
this.interface = Synclink.proxy(
await loadPyodide({

View File

@@ -0,0 +1,18 @@
import { $ } from 'basic-devtools';
import { WSet } from 'not-so-weak';
// weakly retain shadow root nodes in an iterable way
// so that it's possible to query these and find elements by ID
export const shadowRoots: WSet<ShadowRoot> = new WSet();
// returns an element by ID if present within any of the live shadow roots
const findInShadowRoots = (selector: string): Element | null => {
for (const shadowRoot of shadowRoots) {
const element = $(selector, shadowRoot);
if (element) return element;
}
return null;
};
// find an element by ID either via document or via any live shadow root
export const deepQuerySelector = (selector: string) => $(selector, document) || findInShadowRoots(selector);