Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/clean-dogs-launch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@gradio/core": patch
"@self/app": patch
"@self/spa": patch
"gradio": patch
---

fix: Execute function strings passed to `Blocks.launch(js=...)`
10 changes: 0 additions & 10 deletions js/app/src/routes/[...catchall]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -301,16 +301,6 @@

await add_custom_html_head(config.head);

if (config.js) {
try {
const script = document.createElement("script");
script.textContent = config.js;
document.head.appendChild(script);
} catch (e) {
console.error("Error executing custom JS:", e);
}
}

dispatch("loaded");
if (config.dev_mode) {
setTimeout(() => {
Expand Down
11 changes: 10 additions & 1 deletion js/core/src/Blocks.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import MountComponents from "./MountComponents.svelte";
import { prefix_css } from "./css";
import { execute_custom_js } from "./custom_js";
import { reactive_formatter } from "./gradio_helper";

import logo from "./images/logo.svg";
Expand Down Expand Up @@ -467,7 +468,15 @@
});
res.observe(root_container);

app_tree.ready.then(() => {
app_tree.ready.then(async () => {
if (js) {
try {
await execute_custom_js(js);
} catch (e) {
console.error("Error executing custom JS:", e);
}
}

ready = true;
dep_manager.dispatch_load_events();
});
Expand Down
36 changes: 36 additions & 0 deletions js/core/src/custom_js.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { afterEach, describe, expect, test } from "vitest";
import { execute_custom_js } from "./custom_js";

declare global {
var custom_js_result: string | undefined;
}

afterEach(() => {
delete globalThis.custom_js_result;
});

describe("execute_custom_js", () => {
test("invokes a function expression", async () => {
await execute_custom_js(
"() => { globalThis.custom_js_result = 'function'; }"
);

expect(globalThis.custom_js_result).toBe("function");
});

test("awaits an async function expression", async () => {
await execute_custom_js(
"async () => { await Promise.resolve(); globalThis.custom_js_result = 'async'; }"
);

expect(globalThis.custom_js_result).toBe("async");
});

test("executes raw JavaScript", async () => {
await execute_custom_js(
"const result = 'raw'; globalThis.custom_js_result = result;"
);

expect(globalThis.custom_js_result).toBe("raw");
});
});
16 changes: 16 additions & 0 deletions js/core/src/custom_js.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { AsyncFunction } from "./init_utils";

export async function execute_custom_js(js: string): Promise<void> {
let custom_js: () => Promise<unknown>;

try {
custom_js = new AsyncFunction(`return (${js});`);
} catch {
custom_js = new AsyncFunction(js);
}

const result = await custom_js();
if (typeof result === "function") {
await result();
}
}
9 changes: 0 additions & 9 deletions js/spa/src/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -387,15 +387,6 @@
if (config.deep_link_state === "invalid") {
pending_deep_link_error = true;
}
if (config.js) {
try {
const script = document.createElement("script");
script.textContent = config.js;
document.head.appendChild(script);
} catch (e) {
console.error("Error executing custom JS:", e);
}
}
if (config.dev_mode) {
setTimeout(() => {
const { host } = new URL(api_url);
Expand Down
Loading