Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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 @@
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;

Comment thread
Copilot marked this conversation as resolved.
Outdated
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