mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-20 10:47:35 -05:00
186 lines
4.7 KiB
TypeScript
186 lines
4.7 KiB
TypeScript
import * as jsyaml from 'js-yaml';
|
|
import { BaseEvalElement } from './base';
|
|
import {
|
|
initializers,
|
|
loadedEnvironments,
|
|
postInitializers,
|
|
pyodideLoaded,
|
|
scriptsQueue,
|
|
globalLoader,
|
|
appConfig,
|
|
Initializer,
|
|
} from '../stores';
|
|
import { loadInterpreter } from '../interpreter';
|
|
import type { PyLoader } from './pyloader';
|
|
import type { PyScript } from './pyscript';
|
|
import type { PyodideInterface } from '../pyodide';
|
|
|
|
const DEFAULT_RUNTIME = {
|
|
src: 'https://cdn.jsdelivr.net/pyodide/v0.20.0/full/pyodide.js',
|
|
name: 'pyodide-default',
|
|
lang: 'python',
|
|
};
|
|
|
|
export type Runtime = {
|
|
src: string;
|
|
name?: string;
|
|
lang?: string;
|
|
};
|
|
|
|
export type AppConfig = {
|
|
autoclose_loader: boolean;
|
|
name?: string;
|
|
version?: string;
|
|
runtimes?: Array<Runtime>;
|
|
};
|
|
|
|
let appConfig_: AppConfig = {
|
|
autoclose_loader: true,
|
|
};
|
|
|
|
appConfig.subscribe((value: AppConfig) => {
|
|
if (value) {
|
|
appConfig_ = value;
|
|
}
|
|
console.log('config set!');
|
|
});
|
|
|
|
let initializers_: Initializer[];
|
|
initializers.subscribe((value: Initializer[]) => {
|
|
initializers_ = value;
|
|
console.log('initializers set');
|
|
});
|
|
|
|
let postInitializers_: Initializer[];
|
|
postInitializers.subscribe((value: Initializer[]) => {
|
|
postInitializers_ = value;
|
|
console.log('post initializers set');
|
|
});
|
|
|
|
let scriptsQueue_: PyScript[];
|
|
scriptsQueue.subscribe((value: PyScript[]) => {
|
|
scriptsQueue_ = value;
|
|
console.log('post initializers set');
|
|
});
|
|
|
|
let loader: PyLoader | undefined;
|
|
globalLoader.subscribe(value => {
|
|
loader = value;
|
|
});
|
|
|
|
export class PyodideRuntime extends Object {
|
|
src: string;
|
|
|
|
constructor(url: string) {
|
|
super();
|
|
this.src = url;
|
|
}
|
|
|
|
async initialize() {
|
|
loader?.log('Loading runtime...');
|
|
const pyodide: PyodideInterface = await loadInterpreter(this.src);
|
|
const newEnv = {
|
|
id: 'a',
|
|
runtime: pyodide,
|
|
state: 'loading',
|
|
};
|
|
pyodideLoaded.set(pyodide);
|
|
|
|
// Inject the loader into the runtime namespace
|
|
// eslint-disable-next-line
|
|
pyodide.globals.set('pyscript_loader', loader);
|
|
|
|
loader?.log('Runtime created...');
|
|
loadedEnvironments.update(environments => ({
|
|
...environments,
|
|
[newEnv['id']]: newEnv,
|
|
}));
|
|
|
|
// now we call all initializers before we actually executed all page scripts
|
|
loader?.log('Initializing components...');
|
|
for (const initializer of initializers_) {
|
|
await initializer();
|
|
}
|
|
|
|
loader?.log('Initializing scripts...');
|
|
for (const script of scriptsQueue_) {
|
|
await script.evaluate();
|
|
}
|
|
scriptsQueue.set([]);
|
|
|
|
// now we call all post initializers AFTER we actually executed all page scripts
|
|
loader?.log('Running post initializers...');
|
|
|
|
if (appConfig_ && appConfig_.autoclose_loader) {
|
|
loader?.close();
|
|
console.log('------ loader closed ------');
|
|
}
|
|
|
|
for (const initializer of postInitializers_) {
|
|
await initializer();
|
|
}
|
|
}
|
|
}
|
|
|
|
export class PyConfig extends BaseEvalElement {
|
|
shadow: ShadowRoot;
|
|
wrapper: HTMLElement;
|
|
theme: string;
|
|
widths: Array<string>;
|
|
label: string;
|
|
mount_name: string;
|
|
details: HTMLElement;
|
|
operation: HTMLElement;
|
|
code: string;
|
|
values: AppConfig;
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.code = this.innerHTML;
|
|
this.innerHTML = '';
|
|
|
|
const loadedValues = jsyaml.load(this.code);
|
|
if (loadedValues === undefined) {
|
|
this.values = {
|
|
autoclose_loader: true,
|
|
};
|
|
} else {
|
|
// eslint-disable-next-line
|
|
// @ts-ignore
|
|
this.values = loadedValues;
|
|
}
|
|
if (this.values.runtimes === undefined) {
|
|
this.values.runtimes = [DEFAULT_RUNTIME];
|
|
}
|
|
appConfig.set(this.values);
|
|
console.log('config set', this.values);
|
|
|
|
this.loadRuntimes();
|
|
}
|
|
|
|
log(msg: string) {
|
|
const newLog = document.createElement('p');
|
|
newLog.innerText = msg;
|
|
this.details.appendChild(newLog);
|
|
}
|
|
|
|
close() {
|
|
this.remove();
|
|
}
|
|
|
|
loadRuntimes() {
|
|
console.log('Initializing runtimes...');
|
|
for (const runtime of this.values.runtimes) {
|
|
const script = document.createElement('script'); // create a script DOM node
|
|
const runtimeSpec = new PyodideRuntime(runtime.src);
|
|
script.src = runtime.src; // set its src to the provided URL
|
|
script.addEventListener('load', () => {
|
|
void runtimeSpec.initialize();
|
|
});
|
|
document.head.appendChild(script);
|
|
}
|
|
}
|
|
}
|