Initial commit of 001code-html Scratch frontend project.

Includes scratch-gui, scratch-vm, scratch-blocks, scratch-render, scratch-l10n, and deployment config.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-16 15:37:45 +08:00
commit 6e0a1fbcbb
11350 changed files with 965674 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
// PyodideWorkerPool.js
export default class PyodideWorkerPool {
constructor(poolSize = 2) {
this.poolSize = poolSize;
this.workers = [];
this.onMessageCallbacks = [];
this.initPool();
}
initPool() {
for (let i = 0; i < this.poolSize; i++) {
this.workers.push(this.createWorker());
}
}
createWorker() {
const workerInfo = {
worker: new Worker('js/pyodideWorker.js'),
busy: false,
loaded: false
};
// 监听 Worker 消息
workerInfo.worker.onmessage = (event) => {
const { type } = event.data;
if (type === "finish") {
workerInfo.loaded = true;
}
if (type === "executionComplete" || type === "error") {
workerInfo.busy = false;
}
// 让外部知道“是哪个 worker 发来的消息”
for (let cb of this.onMessageCallbacks) {
cb(event, workerInfo);
}
this.updateIsPythonLoadOK();
};
return workerInfo;
}
addOnMessageListener(callback) {
this.onMessageCallbacks.push(callback);
}
updateIsPythonLoadOK() {
// 只要至少一个 Worker loaded 就算可以执行
const anyLoaded = this.workers.some(w => w.loaded === true);
window.isPythonLoadOK = anyLoaded;
}
// 找到不忙、且已loaded的 Worker
getFreeWorker() {
return this.workers.find(w => w.busy === false && w.loaded === true) || null;
}
// 让指定 Worker 执行
runPython(workerInfo, code) {
if (workerInfo.busy) {
throw new Error("该 Worker 正在执行脚本,无法重复使用");
}
if (!workerInfo.loaded) {
throw new Error("该 Worker 尚未加载 Pyodide无法执行 Python");
}
workerInfo.busy = true;
workerInfo.worker.postMessage({ type: "runPython", code });
}
// 停止并替换
terminateAndReplace(workerInfo) {
workerInfo.worker.terminate();
const idx = this.workers.indexOf(workerInfo);
if (idx !== -1) {
const newW = this.createWorker();
this.workers[idx] = newW;
}
this.updateIsPythonLoadOK();
}
destroyPool() {
for (let wInfo of this.workers) {
wInfo.worker.terminate();
}
this.workers = [];
this.updateIsPythonLoadOK();
}
}