From 3260f0126f63680e2fb8743e3474ffcdc89a2c5b Mon Sep 17 00:00:00 2001 From: BenPaoDeXiaoZhi <121215648+BenPaoDeXiaoZhi@users.noreply.github.com> Date: Fri, 17 Oct 2025 07:26:23 +0800 Subject: [PATCH 1/4] Fix typo in comment for startHatsWithParams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改了一个错误的拼写(whit)… --- src/engine/runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 959a6781..2858da87 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -2714,7 +2714,7 @@ class Runtime extends EventEmitter { /** * CCW startHatsWithParams is only used in block utility for extension, - WhitExtraMsg means skip field check when start a hat block. + WithExtraMsg means skip field check when start a hat block. define here is only for debug * @param {!string} requestedHatOpcode Opcode of hats to start. * @param {object} data Optionally, contains fields to match on the hat and parameters to ccw_hat_parameter. From e3ba8eaac40068eea88452b44c97f9476783e2fa Mon Sep 17 00:00:00 2001 From: BenPaoDeXiaoZhi Date: Sat, 16 May 2026 12:12:04 +0800 Subject: [PATCH 2/4] fix: Remove duplicated method remove a duplicated "_convertLabelForScratchBlocks" method in "runtime.js" --- src/engine/runtime.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/engine/runtime.js b/src/engine/runtime.js index 2858da87..a552ac26 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -602,6 +602,11 @@ class Runtime extends EventEmitter { * Total number of finished or errored scratch-storage load() requests since the runtime was created or cleared. */ this.finishedAssetRequests = 0; + + /** + * @type {ScratchStorage} + */ + this.storage = {}; } /** @@ -1895,19 +1900,6 @@ class Runtime extends EventEmitter { }; } - /** - * Generate a label between blocks categories or sub-categories. - * @param {ExtensionBlockMetadata} blockInfo - the block to convert - * @returns {ConvertedBlockInfo} - the converted & original block information - * @private - */ - _convertLabelForScratchBlocks (blockInfo) { - return { - info: blockInfo, - xml: `` - }; - } - /** * Convert a button for scratch-blocks. A button has no opcode but specifies a callback name in the `func` field. * @param {ExtensionBlockMetadata} buttonInfo - the button to convert From c8c868fccd49bb81da98d2c2a35edd3a551dac01 Mon Sep 17 00:00:00 2001 From: BenPaoDeXiaoZhi Date: Sat, 16 May 2026 12:49:20 +0800 Subject: [PATCH 3/4] feat: use sb3 file instead of project id use file to solve the ccw server-side encryption --- src/playground/benchmark.js | 66 ++++++++++++++++++++++--------------- src/playground/index.html | 2 +- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/playground/benchmark.js b/src/playground/benchmark.js index 85da6b49..e9c37356 100644 --- a/src/playground/benchmark.js +++ b/src/playground/benchmark.js @@ -58,10 +58,10 @@ const PROJECT_SERVER = 'https://cdn.projects.scratch.mit.edu/'; const SLOW = .1; -const projectInput = document.querySelector('#project-id'); -if (location.hash) { - projectInput.value = location.hash.substring(1); -} +/** + * @type {HTMLInputElement} + */ +const projectInput = document.querySelector('#project'); const enableCompiler = new URLSearchParams(location.search).get('compiler') === 'true'; const compilerInput = document.querySelector('#enable-compiler'); @@ -69,9 +69,10 @@ compilerInput.checked = enableCompiler; document.querySelector('.run') .addEventListener('click', () => { - const params = new URLSearchParams(location.search); - params.set('compiler', compilerInput.checked); - location.href = `${location.pathname}?${params}#${projectInput.value}`; + window.profiler.run(); + // const params = new URLSearchParams(location.search); + // params.set('compiler', compilerInput.checked); + // location.href = `${location.pathname}?${params}#${projectInput.value}`; }, false); const setShareLink = function (json) { @@ -81,7 +82,7 @@ const setShareLink = function (json) { .href = `suite.html`; }; -const getProjectMetadata = async projectId => { +const _getProjectMetadata = async projectId => { const response = await fetch(`https://trampoline.turbowarp.org/api/projects/${projectId}`); if (response.status === 404) { throw new Error('The project is unshared or does not exist'); @@ -93,10 +94,15 @@ const getProjectMetadata = async projectId => { return json; }; -const getProjectData = async projectId => { - const metadata = await getProjectMetadata(projectId); - const token = metadata.project_token; - const response = await fetch(`https://projects.scratch.mit.edu/${projectId}?token=${token}`); +const _getProjectData = async () => { + // const metadata = await getProjectMetadata(projectId); + // const token = metadata.project_token; + // const response = await fetch(`https://projects.scratch.mit.edu/${projectId}?token=${token}`); + // if (!response.ok) { + // throw new Error(`HTTP error ${response.status} fetching project data`); + // } + // eslint-disable-next-line no-alert, quotes + const response = await fetch(prompt("输入m.ccw.site sb3") ?? ""); if (!response.ok) { throw new Error(`HTTP error ${response.status} fetching project data`); } @@ -104,13 +110,18 @@ const getProjectData = async projectId => { return data; }; -const loadProject = function () { - let id = location.hash.substring(1).split(',')[0]; - if (id.length < 1 || !isFinite(id)) { - id = projectInput.value; - } - getProjectData(id).then(data => Scratch.vm.loadProject(data)); - return id; +const loadProject = function (vm) { + // let id = location.hash.substring(1).split(',')[0]; + // if (id.length < 1 || !isFinite(id)) { + // id = projectInput.value; + // } + // getProjectData(id) + new Promise(resolve => { + if (projectInput.files[0]){ + projectInput.files[0].arrayBuffer().then(dat => resolve(dat)); + } + }).then(data => vm.loadProject(data)); + return ''; }; /** @@ -539,7 +550,7 @@ class ProfilerRun { } run () { - this.projectId = loadProject(); + this.projectId = loadProject(this.vm); window.parent.postMessage({ type: 'BENCH_MESSAGE_LOADING' @@ -671,11 +682,12 @@ const runBenchmark = function () { maxRecordedTime = Number(split[2] || '0') || 6000; } - new ProfilerRun({ + window.profiler = new ProfilerRun({ vm, warmUpTime, maxRecordedTime - }).run(); + }); + window.profiler.run(); // Instantiate the renderer and connect it to the VM. const canvas = document.getElementById('scratch-stage'); @@ -695,7 +707,7 @@ const runBenchmark = function () { canvasWidth: rect.width, canvasHeight: rect.height }; - Scratch.vm.postIOData('mouse', coordinates); + vm.postIOData('mouse', coordinates); }); canvas.addEventListener('mousedown', e => { const rect = canvas.getBoundingClientRect(); @@ -706,7 +718,7 @@ const runBenchmark = function () { canvasWidth: rect.width, canvasHeight: rect.height }; - Scratch.vm.postIOData('mouse', data); + vm.postIOData('mouse', data); e.preventDefault(); }); canvas.addEventListener('mouseup', e => { @@ -718,7 +730,7 @@ const runBenchmark = function () { canvasWidth: rect.width, canvasHeight: rect.height }; - Scratch.vm.postIOData('mouse', data); + vm.postIOData('mouse', data); e.preventDefault(); }); @@ -728,7 +740,7 @@ const runBenchmark = function () { if (e.target !== document && e.target !== document.body) { return; } - Scratch.vm.postIOData('keyboard', { + vm.postIOData('keyboard', { keyCode: e.keyCode, isDown: true }); @@ -737,7 +749,7 @@ const runBenchmark = function () { document.addEventListener('keyup', e => { // Always capture up events, // even those that have switched to other targets. - Scratch.vm.postIOData('keyboard', { + vm.postIOData('keyboard', { keyCode: e.keyCode, isDown: false }); diff --git a/src/playground/index.html b/src/playground/index.html index 43b3d423..69b84d13 100644 --- a/src/playground/index.html +++ b/src/playground/index.html @@ -34,7 +34,7 @@

Scratch VM Benchmark

The benchmark is not very useful when the compiler is enabled.

- +