Skip to content

Commit

Permalink
Add Brython + improve signals, do not use Set
Browse files Browse the repository at this point in the history
  • Loading branch information
denis-migdal committed Feb 25, 2025
1 parent a9980a0 commit 664ea00
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 118 deletions.
85 changes: 0 additions & 85 deletions V2.old/LISSAuto.ts

This file was deleted.

13 changes: 13 additions & 0 deletions V3/assets/test-bry/index.bry
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from browser import self

WebC = self.wrapjs(self.LISS())

class DefaultExport(WebC):
def __init__(this):
this.content.replaceChildren("Hello!")

def foo(this):
print( self.document.querySelector("test-bry").faa() )

def faa(this):
print(2)
14 changes: 14 additions & 0 deletions V3/assets/test-bry/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @ts-ignore
/*
import {test} from "TEST_HELPER";
await test("cstr-params",
`<cstr-params></cstr-params>`,
async () => {
// @ts-ignore
await assertElemEquals('cstr-params', {
shadow_html: "HTML"
});
}
)*/
Binary file added V3/components/code/code-block/CodeBlocks.dia
Binary file not shown.
3 changes: 2 additions & 1 deletion V3/pages/playground/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const examples = [
"hello-world",
"auto-liss",
"auto-vanilla",
"auto-attrs"
"auto-attrs",
"test-bry"
];

const DEFAULT_EXAMPLE = "hello-world";
Expand Down
24 changes: 17 additions & 7 deletions V3/src/define/autoload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,21 @@ export async function loadComponent<T extends HTMLElement = HTMLElement>(
files["js"] = await fetchText(`${compo_dir}index.js`, true);

if( files["js"] === undefined) {
// try/catch ?
const promises = [
fetchText(`${compo_dir}index.html`, true)!,
fetchText(`${compo_dir}index.css` , true)!
];

[files["html"], files["css" ]] = await Promise.all(promises);
files["bry"] = await fetchText(`${compo_dir}index.bry`, true);

if( files["bry"] === undefined ) {

const promises = [
fetchText(`${compo_dir}index.html`, true)!,
fetchText(`${compo_dir}index.css` , true)!
];

[files["html"], files["css" ]] = await Promise.all(promises);

if( files["html"] === undefined )
throw new Error(`No files found for webcomponent ${tagname}`)
}
}

return await defineWebComponent(tagname, files, compo_dir);
Expand All @@ -130,8 +138,10 @@ async function defineWebComponent(tagname: string,
) {

let klass;
if( "js" in files )
if( files["js"] !== undefined )
klass = (await execute<any>(files["js"], "js", origin)).default;
if( files["bry"] !== undefined )
klass = (await execute<any>(files["bry"], "bry", origin)).default;

if( klass === undefined )
klass = LISS({
Expand Down
66 changes: 64 additions & 2 deletions V3/src/define/define.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { _whenDefinedPromises } from "./whenDefined";
export const WaitingDefine = new Set<string>();

export default async function define(tagname: string, Klass: new(...args:any[]) => HTMLElement) {

//TODO: Python class...

if( "$is_class" in Klass )
Klass = WrapPythonClass(Klass);

//TODO: type safe
if( "CONTENT_GENERATOR" in Klass ) {
Expand All @@ -25,6 +26,67 @@ export default async function define(tagname: string, Klass: new(...args:any[])
p.resolve();
}


function WrapPythonClass(Klass: new(...args:any[]) => HTMLElement) {

const JSKlass = (Klass as any).__bases__.filter( (e: any) => e.__name__ === "Wrapper")[0]._js_klass.$js_func as new(...args:any[]) => HTMLElement;

// @ts-ignore
const symbol = __BRYTHON__.PYOBJ;

// make it a proxy ?
return class _Wrapper extends JSKlass {
#bry: any;

// should always be built before end of brython init...
constructor(bry: any = null) {
super();

if( bry === null ) {
// @ts-ignore
globalThis.brython_wrapper_js = this;
// @ts-ignore
bry = __BRYTHON__.$call(Klass, [0,0,0])();
// @ts-ignore
globalThis.brython_wrapper_js = null;
}
this.#bry = bry;

// @ts-ignore
this[symbol] = bry;

console.warn("before call")

this.#call("foo");
}

#call(name: string, ...args: any[]) {
// @ts-ignore
return __BRYTHON__.$call(__BRYTHON__.$getattr_pep657(this.#bry, name, [0,0,0]), [0,0,0])(...args)
}

/*
get host() {
// @ts-ignore
return __BRYTHON__.$getattr_pep657(this.#bry, "host", [0,0,0])
}*/

static observedAttributes = (Klass as any)["observedAttributes"];

attributeChangedCallback(...args: any[]) {
return this.#call("attributeChangedCallback", ...args);
}
/*
connectedCallback(...args: any[]) {
return this.#call("connectedCallback", args);
}
disconnectedCallback(...args: any[]) {
return this.#call("disconnectedCallback", args);
}*/
}
}


import LISS from "@LISS/src/LISS";

declare module "@LISS/src/LISS" {
Expand Down
15 changes: 12 additions & 3 deletions V3/src/signals/SignalEvent.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@

export default class SignalEvent {

#callbacks = new Set<(pthis: SignalEvent) => void>();
#callbacks = new Array<(pthis: SignalEvent) => void>();

listen(callback: (pthis: SignalEvent) => void) {
this.#callbacks.add(callback);
this.#callbacks.push(callback);

return this;
}
unlisten(callback: (pthis: SignalEvent) => void) {
this.#callbacks.delete(callback);

// do not guarantee order ?
const idx = this.#callbacks.lastIndexOf(callback);
if( idx === -1 )
return this;

if( idx !== this.#callbacks.length - 1 )
this.#callbacks[idx] = this.#callbacks[this.#callbacks.length-1];

--this.#callbacks.length;

return this;
}
Expand Down
File renamed without changes.
61 changes: 61 additions & 0 deletions V3/src/utils/execute/bry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import executeJS from "./js";

// @ts-ignore
globalThis.getProp = function(target, name) {
return target[name];
}

// can't use WebPack require() if we want to use it directly...
const bry_wrapper = `from browser import self
def wrapjs(js_klass):
class Wrapper:
_js_klass = js_klass # TODO: replace ?
_js = None
def __new__(cls):
this = super().__new__(cls)
if "brython_wrapper_js" in self:
this._js = self.brython_wrapper_js
else:
# TODO: set it during define...
this._js = this._js_klass.new() # no args
return this
def __getattr__(this, name: str):
print( name in this._js, var(this._js) )
return self.getProp(this._js, name)
#return this._js[name]
def __setattr__(this, name: str, value):
if name == "_js":
super().__setattr__(name, value)
return
this._js[name] = value
return Wrapper
self.wrapjs = wrapjs`;

let wrapper_loaded = false;

export default async function executeBry<T>(code: string, origin: string): Promise<T> {

if( ! wrapper_loaded ) {
await executeJS(`globalThis.__BRYTHON__.runPythonSource(\`${bry_wrapper}\`, "_")`);
wrapper_loaded = true;
}

// Brython library needs to have been loaded.
const jscode = `const $B = globalThis.__BRYTHON__;
$B.runPythonSource(\`${code}\`, "_");
const module = $B.imported["_"];
export default module.DefaultExport;`;

return await executeJS(jscode, origin);
}
11 changes: 7 additions & 4 deletions V3/src/utils/execute/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import executeBry from "./bry";
import executeJS from "./js";

export default async function execute<T>(code: string, type: "js", origin: string): Promise<T> {
const EXEC = {
js : executeJS,
bry: executeBry
}

if( type === "js" )
return await executeJS<T>(code, origin);
export default async function execute<T>(code: string, type: "js"|"bry", origin: string): Promise<T> {

throw new Error('');
return await EXEC[type]<T>(code, origin);
}
8 changes: 5 additions & 3 deletions V3/src/utils/execute/js.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
export default async function executeJS<T>(code: string, origin: string): Promise<T> {
export default async function executeJS<T>(code: string, origin?: string): Promise<T> {

const file = new Blob([code], { type: 'application/javascript' });
const url = URL.createObjectURL(file);

const id = url.slice(url.lastIndexOf('/') + 1 );
((globalThis.LISSContext ??={}).execute ??= {url_map: {}}).url_map[id] = origin;
if( origin !== undefined) {
const id = url.slice(url.lastIndexOf('/') + 1 );
((globalThis.LISSContext ??={}).execute ??= {url_map: {}}).url_map[id] = origin;
}

const result = (await import(/* webpackIgnore: true */ url));

Expand Down
1 change: 1 addition & 0 deletions V3/src/utils/tests/buildTestPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function buildTestPage(args: {
background-color: white;
}
</style>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3/brython.min.js" defer></script>
<script type="module" src='${args.liss}'
liss-sw="${args.sw ?? ""}"
liss-mode="auto-load"
Expand Down
Loading

0 comments on commit 664ea00

Please sign in to comment.