Use overleaf CDN for loading pyodide packages

GitOrigin-RevId: e17ff3387166421a546a9519786d77ba12cdffc4
This commit is contained in:
Domagoj Kriskovic
2026-04-30 08:05:23 +00:00
committed by Copybot
parent a46ca0705f
commit 9e677a2c1e
15 changed files with 203 additions and 39 deletions
@@ -30,7 +30,6 @@ export type LifecycleCallback = (
export class PyodideWorkerClient {
private worker: Worker
private baseAssetPath: string
private packageBaseUrl: string | undefined
private createWorker: () => Worker
private listening = false
private destroyed = false
@@ -41,13 +40,11 @@ export class PyodideWorkerClient {
constructor(options: {
baseAssetPath: string
packageBaseUrl?: string
createWorker: () => Worker
onOutput?: OutputCallback
onLifecycle?: LifecycleCallback
}) {
this.baseAssetPath = options.baseAssetPath
this.packageBaseUrl = options.packageBaseUrl
this.createWorker = options.createWorker
this.outputCallback = options.onOutput ?? null
this.lifecycleCallback = options.onLifecycle ?? null
@@ -57,7 +54,6 @@ export class PyodideWorkerClient {
this.queueMessage({
type: 'init',
baseAssetPath: this.baseAssetPath,
packageBaseUrl: this.packageBaseUrl,
})
}
@@ -101,7 +97,6 @@ export class PyodideWorkerClient {
this.queueMessage({
type: 'init',
baseAssetPath: this.baseAssetPath,
packageBaseUrl: this.packageBaseUrl,
})
}
@@ -15,7 +15,6 @@ export type OutputFileData = {
export type InitRequest = {
type: 'init'
baseAssetPath: string
packageBaseUrl?: string
}
export type RunCodeRequest = {
@@ -15,7 +15,6 @@ type PyodideModule = typeof import('pyodide')
const PROJECT_FS_ROOT = '/project'
const PROJECT_FS_PREFIX = `${PROJECT_FS_ROOT}/`
const PYODIDE_INDEX_PATH = 'js/libs/pyodide/'
const PYODIDE_CDN_URL = 'https://cdn.jsdelivr.net/pyodide/v'
function ensureDirectoryExists(fs: PyodideFS, filePath: string) {
const directory = path.dirname(filePath)
@@ -51,7 +50,7 @@ function syncProjectFiles(fs: PyodideFS, files: ProjectFileData[]) {
}
let pyodideModule: PyodideModule | null = null
let packageBaseUrlOverride: string | undefined
let pyodideIndexUrl: string | undefined
async function loadPyodideModule(pyodideIndexUrl: string) {
const runtimeModuleUrl = `${pyodideIndexUrl}pyodide.mjs`
@@ -70,12 +69,7 @@ async function loadPyodideModule(pyodideIndexUrl: string) {
}
async function handleInit(msg: InitRequest) {
const pyodideIndexUrl = new URL(
PYODIDE_INDEX_PATH,
msg.baseAssetPath
).toString()
packageBaseUrlOverride = msg.packageBaseUrl
pyodideIndexUrl = new URL(PYODIDE_INDEX_PATH, msg.baseAssetPath).toString()
try {
pyodideModule = await loadPyodideModule(pyodideIndexUrl)
@@ -93,7 +87,7 @@ async function handleInit(msg: InitRequest) {
async function handleRunCode(msg: RunCodeRequest) {
const { fileId, executionId } = msg
if (!pyodideModule) {
if (!pyodideModule || !pyodideIndexUrl) {
self.postMessage({
type: 'output-line',
stream: 'stderr',
@@ -114,9 +108,7 @@ async function handleRunCode(msg: RunCodeRequest) {
const instance = await pyodideModule.loadPyodide({
env: { MPLBACKEND: 'Agg' },
packageBaseUrl:
packageBaseUrlOverride ??
`${PYODIDE_CDN_URL}${pyodideModule.version}/full/`,
packageBaseUrl: `${pyodideIndexUrl}${pyodideModule.version}/`,
})
const writtenPaths = new Set<string>()
@@ -43,7 +43,6 @@ export class PythonRunner {
readonly fileId: string
private client: PyodideWorkerClient | null = null
private readonly baseAssetPath: string
private readonly packageBaseUrl: string | undefined
private readonly createWorker: () => Worker
private readonly getExecutionContext: () => Promise<ExecutionContext | null>
private listeners = new Set<Listener>()
@@ -55,12 +54,10 @@ export class PythonRunner {
fileId: string,
baseAssetPath: string,
getExecutionContext: () => Promise<ExecutionContext | null>,
createWorker: () => Worker,
packageBaseUrl?: string
createWorker: () => Worker
) {
this.fileId = fileId
this.baseAssetPath = baseAssetPath
this.packageBaseUrl = packageBaseUrl
this.createWorker = createWorker
this.getExecutionContext = getExecutionContext
}
@@ -102,7 +99,6 @@ export class PythonRunner {
this.client = new PyodideWorkerClient({
baseAssetPath: this.baseAssetPath,
packageBaseUrl: this.packageBaseUrl,
createWorker: this.createWorker,
onLifecycle: event => {
switch (event.type) {
@@ -37,9 +37,9 @@ export const PythonExecutionContext = createContext<
PythonExecutionContextValue | undefined
>(undefined)
export const PythonExecutionProvider: FC<
PropsWithChildren<{ packageBaseUrl?: string }>
> = ({ children, packageBaseUrl }) => {
export const PythonExecutionProvider: FC<PropsWithChildren> = ({
children,
}) => {
const { openDocs } = useEditorManagerContext()
const { projectSnapshot } = useProjectContext()
const { pathInFolder } = useFileTreePathContext()
@@ -99,14 +99,13 @@ export const PythonExecutionProvider: FC<
fileId,
baseAssetPathRef.current,
() => getExecutionContext(fileId),
createPyodideWorker,
packageBaseUrl
createPyodideWorker
)
runner.init()
runnersRef.current.set(fileId, runner)
return runner
},
[getExecutionContext, packageBaseUrl]
[getExecutionContext]
)
useEffect(() => {