File size: 6,023 Bytes
0bd62e5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
<script lang="ts">
import "@gradio/theme/reset.css";
import "@gradio/theme/global.css";
import "@gradio/theme/pollen.css";
import "@gradio/theme/typography.css";
import { onDestroy, SvelteComponent } from "svelte";
import Index from "@self/spa";
import Playground from "./Playground.svelte";
import ErrorDisplay from "./ErrorDisplay.svelte";
import type { ThemeMode } from "@gradio/core";
import { WorkerProxy, type WorkerProxyOptions } from "@gradio/wasm";
import { FAKE_LITE_HOST } from "@gradio/wasm/network";
import { Client } from "@gradio/client";
import { wasm_proxied_fetch } from "./fetch";
import { wasm_proxied_stream_factory } from "./sse";
import { wasm_proxied_mount_css, mount_prebuilt_css } from "./css";
import type { mount_css } from "@gradio/core";
// These imports are aliased at built time with Vite. See the `resolve.alias` config in `vite.config.ts`.
import gradioWheel from "gradio.whl";
import gradioClientWheel from "gradio_client.whl";
export let info: boolean;
export let container: boolean;
export let is_embed: boolean;
export let initial_height: string;
export let eager: boolean;
export let version: string;
export let theme_mode: ThemeMode | null;
export let autoscroll: boolean;
export let control_page_title: boolean;
export let app_mode: boolean;
// For Wasm mode
export let files: WorkerProxyOptions["files"] | undefined;
export let requirements: WorkerProxyOptions["requirements"] | undefined;
export let code: string | undefined;
export let entrypoint: string | undefined;
export let sharedWorkerMode: boolean | undefined;
// For playground
export let playground = false;
export let layout: string | null;
const worker_proxy = new WorkerProxy({
gradioWheelUrl: new URL(gradioWheel, import.meta.url).href,
gradioClientWheelUrl: new URL(gradioClientWheel, import.meta.url).href,
files: files ?? {},
requirements: requirements ?? [],
sharedWorkerMode: sharedWorkerMode ?? false
});
onDestroy(() => {
worker_proxy.terminate();
});
let error: Error | null = null;
const wrapFunctionWithAppLogic = <TArgs extends any[], TRet extends any>(
func: (...args: TArgs) => Promise<TRet>
): ((...args: TArgs) => Promise<TRet>) => {
return async (...args: TArgs) => {
try {
error = null;
const retval = await func(...args);
refresh_index_component();
return retval;
} catch (err) {
error = err as Error;
throw err;
}
};
};
worker_proxy.runPythonCode = wrapFunctionWithAppLogic(
worker_proxy.runPythonCode.bind(worker_proxy)
);
worker_proxy.runPythonFile = wrapFunctionWithAppLogic(
worker_proxy.runPythonFile.bind(worker_proxy)
);
worker_proxy.writeFile = wrapFunctionWithAppLogic(
worker_proxy.writeFile.bind(worker_proxy)
);
worker_proxy.renameFile = wrapFunctionWithAppLogic(
worker_proxy.renameFile.bind(worker_proxy)
);
worker_proxy.unlink = wrapFunctionWithAppLogic(
worker_proxy.unlink.bind(worker_proxy)
);
worker_proxy.install = wrapFunctionWithAppLogic(
worker_proxy.install.bind(worker_proxy)
);
worker_proxy.addEventListener("initialization-error", (event) => {
error = (event as CustomEvent).detail;
});
// Internally, the execution of `runPythonCode()` or `runPythonFile()` is queued
// and its promise will be resolved after the Pyodide is loaded and the worker initialization is done
// (see the await in the `onmessage` callback in the webworker code)
// So we don't await this promise because we want to mount the `Index` immediately and start the app initialization asynchronously.
if (code != null) {
worker_proxy.runPythonCode(code);
} else if (entrypoint != null) {
worker_proxy.runPythonFile(entrypoint);
} else {
throw new Error("Either code or entrypoint must be provided.");
}
mount_prebuilt_css(document.head);
class LiteClient extends Client {
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
return wasm_proxied_fetch(worker_proxy, input, init);
}
stream(url: URL): EventSource {
return wasm_proxied_stream_factory(worker_proxy, url);
}
}
const overridden_mount_css: typeof mount_css = async (url, target) => {
return wasm_proxied_mount_css(worker_proxy, url, target);
};
let index_component_key = 0;
function refresh_index_component(): void {
index_component_key += 1;
}
let playground_component: SvelteComponent | null = null;
$: playground_component?.$on("code", (event) => {
const { code } = event.detail;
worker_proxy.runPythonCode(code);
});
export const run_code = worker_proxy.runPythonCode;
export const run_file = worker_proxy.runPythonFile;
export const write = worker_proxy.writeFile;
export const rename = worker_proxy.renameFile;
export const unlink = worker_proxy.unlink;
export const install = worker_proxy.install;
</script>
{#if playground}
<Playground
bind:this={playground_component}
{worker_proxy}
{layout}
{code}
{is_embed}
>
{#key index_component_key}
{#if error}
<ErrorDisplay {error} is_embed />
{:else}
<Index
space={null}
src={null}
host={null}
{info}
{container}
{is_embed}
{initial_height}
{eager}
{version}
{theme_mode}
{autoscroll}
{control_page_title}
{app_mode}
{worker_proxy}
Client={LiteClient}
mount_css={overridden_mount_css}
/>
{/if}
{/key}
</Playground>
{:else}
{#key index_component_key}
{#if error}
<ErrorDisplay {error} {is_embed} />
{:else}
<Index
space={null}
src={null}
host={FAKE_LITE_HOST}
{info}
{container}
{is_embed}
{initial_height}
{eager}
{version}
{theme_mode}
{autoscroll}
{control_page_title}
{app_mode}
{worker_proxy}
Client={LiteClient}
mount_css={overridden_mount_css}
/>
{/if}
{/key}
{/if}
|