From 61af7ada498ba6c065e207baecb32b04d4147646 Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Fri, 8 May 2026 14:46:42 +0100 Subject: [PATCH 1/2] Set noproject=1 to avoid MakeCode init race On slow networks, MakeCode's DOMContentLoaded chain calls loadHeaderAsync/newProject before componentDidMount finishes setting up simulator.driver, producing "Cannot read properties of undefined (reading 'preload')" and a broken UI on the embedding page. Add noproject=1 alongside controller, and respond to the resulting 'newproject' host message by importing initialProjects()[0]. The parent-driven import arrives after componentDidMount has completed, dodging the race. This is the same flow as MakeCode's initialization, but later and under our control. Trades the race for a weird interim state where there's no project but the editor is rendered. This looks janky, but is acceptable for the CreateAI scenario where MakeCode isn't initially visible. Remove once microsoft/pxt commit 50486a9 (fixing microsoft/pxt-microbit#6081) is live in deployed MakeCode. As it's not the best option for all consumers we're going to produce a one off -noproject release from this branch to tide us over until the MakeCode release. As an aside, the newproject host message currently arrives without a 'type' field (MakeCode app.tsx:6519, unlike other postHostMessageAsync call sites), so detect it by action and accept either shape so we keep working if upstream is fixed. --- src/vanilla/makecode-frame-driver.ts | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/vanilla/makecode-frame-driver.ts b/src/vanilla/makecode-frame-driver.ts index 64a7550..7a95b96 100644 --- a/src/vanilla/makecode-frame-driver.ts +++ b/src/vanilla/makecode-frame-driver.ts @@ -189,6 +189,23 @@ export class MakeCodeFrameDriver { return; } + // The 'newproject' host message (sent when started with noproject=1) currently arrives + // without a 'type' field — every other postHostMessageAsync call site in MakeCode sets + // type: 'pxthost' but app.tsx:6519 doesn't. Match on action and tolerate either shape so + // we keep working if upstream is fixed. + // Treat it as a readiness signal so the import reply can flush the queue without waiting + // for editorcontentloaded (which itself only fires after a project loads). + if ( + data.action === 'newproject' && + (!data.type || data.type === 'pxthost') + ) { + this.ready = true; + this.messageQueue.forEach((m) => this.sendMessageNoReadyCheck(m)); + this.messageQueue.length = 0; + this.handleNewProjectRequest(); + return; + } + // I think 'editorcontentloaded' isn't useful here in controller scenarios but needs confirming. // Might be the right option when waiting to render blocks or similar? if ( @@ -356,6 +373,30 @@ export class MakeCodeFrameDriver { this.iframe()?.contentWindow?.postMessage(message, '*'); }; + private async handleNewProjectRequest() { + try { + const projects = await this.options.initialProjects(); + if (projects.length > 0) { + const { filters, searchBar } = this.options; + this.sendMessageNoReadyCheck({ + type: 'pxteditor', + action: 'importproject', + project: projects[0], + filters, + searchBar, + } as EditorMessageImportProjectRequest); + } else { + this.sendMessageNoReadyCheck({ + type: 'pxteditor', + action: 'newproject', + options: { preferredEditor: 'blocksprj' }, + } as EditorMessageNewProjectRequest); + } + } catch (e) { + console.error(e); + } + } + private async handleWorkspaceSync( event: EditorWorkspaceSyncRequest | EditorWorkspaceSaveRequest ) { @@ -830,6 +871,15 @@ export const createMakeCodeURL = ( } if (controller) { url.searchParams.set('controller', controller.toString()); + // TEMPORARY: skip MakeCode's racy auto-default-project step. The driver + // responds to the resulting 'newproject' host message by importing + // initialProjects()[0]. Workaround for the race fixed by + // https://github.com/microsoft/pxt/commit/50486a92c909a56c1270a9c549aa483bbe1d74bd + // (issue https://github.com/microsoft/pxt-microbit/issues/6081). Trades + // the race for a brief loading-dimmer flash, so REMOVE this and the + // associated 'newproject' handler once that fix is live in the deployed + // MakeCode. + url.searchParams.set('noproject', '1'); } if (queryParams) { for (const [k, v] of Object.entries(queryParams)) { From 2eceb04ed35ed4b6cd409f7e015349b2191b0e42 Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Fri, 8 May 2026 14:52:42 +0100 Subject: [PATCH 2/2] Hack releases on from this branch. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 046466a..05c1ac1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,6 +28,6 @@ jobs: with: path: ./storybook-static - run: npm publish - if: github.event_name == 'release' && github.event.action == 'created' + #if: github.event_name == 'release' && github.event.action == 'created' env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}