From d064e45f7bb413a5b7766ea37e728e4c041ac9b4 Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Thu, 6 Mar 2025 15:30:36 -0800 Subject: [PATCH 1/3] use offline asseteditor.html from mkc cache --- resources/assetMessaging.js | 10 +++ resources/assetframe.html | 9 ++- src/web/assetEditor.ts | 26 ++++++-- src/web/host.ts | 119 +++++++++++++++++----------------- src/web/makecodeOperations.ts | 4 ++ 5 files changed, 99 insertions(+), 69 deletions(-) diff --git a/resources/assetMessaging.js b/resources/assetMessaging.js index 8fbfc8f..8d1639a 100644 --- a/resources/assetMessaging.js +++ b/resources/assetMessaging.js @@ -4,6 +4,12 @@ window.addEventListener("message", function (m) { if (m.data._fromVscode) { + if (m.data.type === "fetch-html") { + console.log(m.data.srcDoc) + frame.srcdoc = m.data.srcDoc; + return; + } + frame.contentWindow.postMessage(m.data, "*"); if (m.data.type === "open") { @@ -20,5 +26,9 @@ }); document.addEventListener("DOMContentLoaded", function (event) { frame = document.getElementById("asset-editor-frame"); + + vscode.postMessage({ + type: "fetch-html" + }); }); }()) diff --git a/resources/assetframe.html b/resources/assetframe.html index a3aea20..2d54c0b 100644 --- a/resources/assetframe.html +++ b/resources/assetframe.html @@ -11,8 +11,13 @@
-
diff --git a/src/web/assetEditor.ts b/src/web/assetEditor.ts index f86bb69..d58baa2 100644 --- a/src/web/assetEditor.ts +++ b/src/web/assetEditor.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode"; import { activeWorkspace, findFilesAsync, readFileAsync, writeFileAsync } from "./host"; import { syncJResAsync } from "./jres"; import { readTextFileAsync, throttle } from "./util"; +import { getAssetEditorHtmlAsync } from "./makecodeOperations"; let extensionContext: vscode.ExtensionContext; // const assetUrl = "http://localhost:3232/asseteditor.html"; @@ -70,6 +71,7 @@ export class AssetEditor { protected panel: vscode.WebviewPanel; protected editing: AssetEditorState | undefined; + protected assetEditorHtml: string | undefined; protected disposables: vscode.Disposable[]; protected pendingMessages: {[index: string]: (res: any) => void} = {}; protected nextId = 0; @@ -137,6 +139,12 @@ export class AssetEditor { } switch (message.type) { + case "fetch-html": + this.postMessageCore({ + type: "fetch-html", + srcDoc: this.assetEditorHtml + }); + break; case "event": this.handleSimulatorEventAsync(message); break; @@ -158,12 +166,11 @@ export class AssetEditor { } sendMessageAsync(message: any) { - message._fromVscode = true; message.id = this.nextId++; return new Promise(resolve => { this.pendingMessages[message.id] = resolve; - this.panel.webview.postMessage(message); + this.postMessageCore(message); }); } @@ -171,9 +178,16 @@ export class AssetEditor { this.disposables.push(d); } + protected postMessageCore(message: any) { + message._fromVscode = true; + this.panel.webview.postMessage(message); + } + protected async initWebviewHtmlAsync() { this.panel.webview.html = ""; - const simulatorHTML = await getAssetEditorHtmlAsync(this.panel.webview); + + this.assetEditorHtml = await getAssetEditorHtmlAsync(activeWorkspace());; + const simulatorHTML = await getAssetEditorLoaderHtmlAsync(this.panel.webview); this.panel.webview.html = simulatorHTML; } @@ -220,16 +234,14 @@ export class AssetEditorSerializer implements vscode.WebviewPanelSerializer { } -async function getAssetEditorHtmlAsync(webview: vscode.Webview) { +async function getAssetEditorLoaderHtmlAsync(webview: vscode.Webview) { const uri = vscode.Uri.joinPath(extensionContext.extensionUri, "resources", "assetframe.html"); const contents = await readTextFileAsync(uri); const pathURL = (s: string) => webview.asWebviewUri(vscode.Uri.joinPath(extensionContext.extensionUri, "resources", s)).toString(); - return contents - .replace(/@RES@\/([\w\-\.]+)/g, (f, fn) => pathURL(fn)) - .replace("@ASSETURL@", assetUrl); + return contents.replace(/@RES@\/([\w\-\.]+)/g, (f, fn) => pathURL(fn)); } async function readProjectJResAsync() { diff --git a/src/web/host.ts b/src/web/host.ts index e59f160..86c9cc4 100644 --- a/src/web/host.ts +++ b/src/web/host.ts @@ -14,7 +14,7 @@ export function createVsCodeHost(): Host { existsAsync: async (p) => existsAsync(rmFolderPrefix(p)), unlinkAsync: async (p) => unlinkAsync(rmFolderPrefix(p)), cwdAsync: async () => getFolderName(), - symlinkAsync: async () => {}, + symlinkAsync: async () => { }, listFilesAsync: async (d, f) => listFilesAsync(rmFolderPrefix(d), f), requestAsync: httpRequestCoreAsync, createLanguageServiceAsync: async (editor) => new BrowserLanguageService(editor), @@ -24,7 +24,8 @@ export function createVsCodeHost(): Host { throw new Error(`Exit with status ${code}`); }, bufferToString: buffer => new TextDecoder().decode(buffer), - stringToBuffer + stringToBuffer, + base64EncodeBufferAsync }; } @@ -104,78 +105,65 @@ async function listFilesAsync(directory: string, filename: string) { }); } -export function httpRequestCoreAsync(options: HttpRequestOptions) { - return new Promise((resolve, reject) => { - let client: XMLHttpRequest; - let resolved = false; +export async function httpRequestCoreAsync(options: HttpRequestOptions) { + const headers = options.headers || {}; + const data = options.data; + const method = options.method || (data == null ? "GET" : "POST"); + + let buf: null | Uint8Array | string; + + if (data == null) { + buf = null; + } else if (data instanceof Uint8Array) { + buf = data; + } else if (typeof data === "object") { + buf = JSON.stringify(data); + headers["content-type"] = "application/json; charset=utf8"; + } else if (typeof data === "string") { + buf = data; + } else { + throw new Error("bad data"); + } - let headers = options.headers || {}; + const requestHeaders = new Headers(); + Object.keys(headers).forEach(k => { + requestHeaders.set(k, headers[k]); + }); - client = new XMLHttpRequest(); - client.onreadystatechange = () => { - if (resolved) {return;} // Safari/iOS likes to call this thing more than once + const resp = await fetch(options.url, { + method, + headers: requestHeaders, + body: buf + }); - if (client.readyState === 4) { - resolved = true; - let res: HttpResponse = { - statusCode: client.status, - headers: {}, - buffer: (client as any).responseBody || client.response, - text: client.responseText, - }; + const body = await resp.arrayBuffer(); - if (typeof res.buffer === "string") { - res.buffer = new TextEncoder().encode(res.buffer); - } - const allHeaders = client.getAllResponseHeaders(); - allHeaders.split(/\r?\n/).forEach(l => { - let m = /^\s*([^:]+): (.*)/.exec(l); - if (m) { - res.headers[m[1].toLowerCase()] = m[2]; - } - }); - resolve(res); - } - }; + let text: string | undefined; - let data = options.data; - let method = options.method || (data == null ? "GET" : "POST"); - - let buf: any; - - if (data == null) { - buf = null; - } else if (data instanceof Uint8Array) { - buf = data; - } else if (typeof data === "object") { - buf = JSON.stringify(data); - headers["content-type"] = "application/json; charset=utf8"; - } else if (typeof data === "string") { - buf = data; - } else { - throw new Error("bad data"); - } + try { + text = new TextDecoder().decode(body); + } + catch (e) { + // binary data + } - client.open(method, options.url); + const res: HttpResponse = { + statusCode: resp.status, + headers: {}, + buffer: new Uint8Array(body), + text, + }; - Object.keys(headers).forEach(k => { - client.setRequestHeader(k, headers[k]); - }); + resp.headers.forEach((value, key) => res.headers[key.toLowerCase()] = value); - if (buf == null) { - client.send(); - } - else { - client.send(buf); - } - }); + return res; } function resolvePath(path: string) { return vscode.Uri.joinPath(activeWorkspace().uri, path); } -export function stringToBuffer(str: string, encoding?: string){ +export function stringToBuffer(str: string, encoding?: string) { let contents: string; if (encoding === "base64") { try { @@ -237,4 +225,15 @@ export async function findFilesAsync(extension: string, root: vscode.Uri, matchW } return result; +} + +function base64EncodeBufferAsync(buffer: Uint8Array | ArrayBuffer): Promise { + return new Promise(resolve => { + const reader = new FileReader(); + reader.onload = () => { + const url = reader.result as string; + resolve(url.slice(url.indexOf(',') + 1)); + }; + reader.readAsDataURL(new Blob([buffer])); + }); } \ No newline at end of file diff --git a/src/web/makecodeOperations.ts b/src/web/makecodeOperations.ts index 6da88ff..6965e15 100644 --- a/src/web/makecodeOperations.ts +++ b/src/web/makecodeOperations.ts @@ -72,6 +72,10 @@ export function getSimHtmlAsync(folder: vscode.WorkspaceFolder, cancellationToke return enqueueOperationAsync(folder, () => cmd.getSimHTML({}), cancellationToken); } +export function getAssetEditorHtmlAsync(folder: vscode.WorkspaceFolder, cancellationToken?: vscode.CancellationToken) { + return enqueueOperationAsync(folder, () => cmd.getAssetEditorHTML({}), cancellationToken); +} + /** * The mkc CLI uses global state, so we need to perform operations in a queue just in case the * user is doing things in multiple workspaces at once From c3138ac94c0fe906503dd318b548d3c9a73045e9 Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Thu, 6 Mar 2025 15:32:54 -0800 Subject: [PATCH 2/3] remove console log --- resources/assetMessaging.js | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/assetMessaging.js b/resources/assetMessaging.js index 8d1639a..2d94141 100644 --- a/resources/assetMessaging.js +++ b/resources/assetMessaging.js @@ -5,7 +5,6 @@ window.addEventListener("message", function (m) { if (m.data._fromVscode) { if (m.data.type === "fetch-html") { - console.log(m.data.srcDoc) frame.srcdoc = m.data.srcDoc; return; } From dc8a7e840ea567bc87241a81620ec69a8f3cb324 Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Thu, 6 Mar 2025 16:51:06 -0800 Subject: [PATCH 3/3] update makecode-core and makecode-browser --- package.json | 4 +-- yarn.lock | 72 ++++++++++++++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index e68608d..4db0cfc 100644 --- a/package.json +++ b/package.json @@ -361,8 +361,8 @@ "dependencies": { "@types/path-browserify": "^1.0.0", "@vscode/extension-telemetry": "^0.7.5", - "makecode-browser": "^1.3.1", - "makecode-core": "^1.7.0", + "makecode-browser": "^1.3.2", + "makecode-core": "^1.7.1", "path-browserify": "^1.0.1" } } diff --git a/yarn.lock b/yarn.lock index 20e158b..ea78117 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,9 +19,9 @@ tslib "^2.6.2" "@azure/core-rest-pipeline@^1.10.0": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.19.0.tgz#4cc60d3f2ee68cf0ef379851b4ed175f7932c8c5" - integrity sha512-bM3308LRyg5g7r3Twprtqww0R/r7+GyVxj4BafcmVPo4WQoGt5JXuaqxHEFjw2o3rvFZcUPiqJMg6WuvEEeVUA== + version "1.19.1" + resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.19.1.tgz#e740676444777a04dc55656d8660131dfd926924" + integrity sha512-zHeoI3NCs53lLBbWNzQycjnYKsA1CVKlnzSNuSFcUDwBp8HHVObePxrM7HaX+Ha5Ks639H7chNC9HOaIhNS03w== dependencies: "@azure/abort-controller" "^2.0.0" "@azure/core-auth" "^1.8.0" @@ -310,11 +310,11 @@ integrity sha512-4VlGgo32k2EQ2wcCY3vEU28A0O13aOtHz3Xt2/2U5FAh9EfhD6t6DqL5Z6yAnRCntbTFDU4YfbpyzSlHNWycPw== "@playwright/browser-chromium@^1.48.1": - version "1.50.1" - resolved "https://registry.yarnpkg.com/@playwright/browser-chromium/-/browser-chromium-1.50.1.tgz#2a5a5e200e6de6b0b6782ffc63e65bc1d48b5753" - integrity sha512-odDVeETxPjB/TENtKVpfa/p7ZZ1/awda0tgknSDHNd4R2KrE1vrkNysc3rws3mh2ecQf6UOeI15eaUcNm5YxUg== + version "1.51.0" + resolved "https://registry.yarnpkg.com/@playwright/browser-chromium/-/browser-chromium-1.51.0.tgz#32b0c6eb0441a7cd85f06e596d0908cef0396316" + integrity sha512-ANaU19rQbK+lmmXhvBQQIZ6VHjtMxX99NBPeVBI5G7W/CI35UtWIlnmc+DEknbJd0fBWOhtWAzIBhFpDVgtWpA== dependencies: - playwright-core "1.50.1" + playwright-core "1.51.0" "@types/eslint-scope@^3.7.7": version "3.7.7" @@ -365,9 +365,9 @@ integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== "@types/vscode@^1.74.0": - version "1.97.0" - resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.97.0.tgz#62ce3a32243019aaa4fc20cee2a3de06bc71af4f" - integrity sha512-ueE73loeOTe7olaVyqP9mrRI54kVPJifUPjblZo9fYcv1CuVLPOEKEkqW0GkqPC454+nCEoigLWnC2Pp7prZ9w== + version "1.98.0" + resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.98.0.tgz#5b6fa5bd99ba15313567d3847fb1177832fee08c" + integrity sha512-+KuiWhpbKBaG2egF+51KjbGWatTH5BbmWQjSLMDCssb4xF8FJnW4nGH4nuAdOOfMbpD0QlHtI+C3tPq+DoKElg== "@types/webpack-env@^1.18.0": version "1.18.8" @@ -673,9 +673,9 @@ acorn-jsx@^5.3.2: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn@^8.14.0, acorn@^8.8.2, acorn@^8.9.0: - version "8.14.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" - integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + version "8.14.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== agent-base@^7.1.0, agent-base@^7.1.2: version "7.1.3" @@ -1247,9 +1247,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.5.73: - version "1.5.112" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.112.tgz#8d3d95d4d5653836327890282c8eda5c6f26626d" - integrity sha512-oen93kVyqSb3l+ziUgzIOlWt/oOuy4zRmpwestMn4rhFWAoFJeFuCVte9F2fASjeZZo7l/Cif9TiyrdW4CwEMA== + version "1.5.113" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.113.tgz#1175b8ba4170541e44e9afa8b992e5bbfff0d150" + integrity sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg== emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" @@ -2167,17 +2167,17 @@ lru-cache@^11.0.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39" integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA== -makecode-browser@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/makecode-browser/-/makecode-browser-1.3.1.tgz#e762dabf7565af8ea8df9c873ea70a61bdf2b441" - integrity sha512-VIlr4GG7Iz7om7b7Qz46Q1y+8h7RVgKB6S0ZpBhsPJbjM6cEDmAYWydGhq8NNFe/+NFAlSlnAnjQdbCklmpfuQ== +makecode-browser@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/makecode-browser/-/makecode-browser-1.3.2.tgz#655f1a62da2064e9aebd93c06df7e4011f7ea28b" + integrity sha512-mZ8Kpt3Ft/ls2Tpdb4YAJQSWffC4rDtdaW+Yh9HTVzfMgqwzd/cfxBgKGbvyFcFIONLU04fyjn8Jz5Ttn307Nw== dependencies: - makecode-core "^1.7.0" + makecode-core "^1.7.1" -makecode-core@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/makecode-core/-/makecode-core-1.7.0.tgz#69cbe2a5c49e20356e606557e21d1e7da9d7f674" - integrity sha512-DTdqebx3XvFkAlj8uYViDj4lhBa0h3DFPC13mcFwWSTuLtPcqC92oDY1DfnMUGAbf808MQtwNg9r7y5sC0aE9Q== +makecode-core@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/makecode-core/-/makecode-core-1.7.1.tgz#42b69d6bcc4f64e9c6f46ebfd91fa4568c509915" + integrity sha512-RM+wRcKsaO+KtIlYExFkjAlVQNcDrn4zRVHMUmahyyT9jRnYhWwb2w+wD3+tbCs/5vcmFTDsW4nd8O4MqFUkxg== dependencies: "@xmldom/xmldom" "^0.9.8" chalk "^4.1.2" @@ -2522,17 +2522,17 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.50.1: - version "1.50.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.50.1.tgz#6a0484f1f1c939168f40f0ab3828c4a1592c4504" - integrity sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ== +playwright-core@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.51.0.tgz#bb23ea6bb6298242d088ae5e966ffcf8dc9827e8" + integrity sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg== playwright@^1.48.1: - version "1.50.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.50.1.tgz#2f93216511d65404f676395bfb97b41aa052b180" - integrity sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw== + version "1.51.0" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.51.0.tgz#9ba154497ba62bc6dc199c58ee19295eb35a4707" + integrity sha512-442pTfGM0xxfCYxuBa/Pu6B2OqxqqaYq39JS8QDMGThUvIOCd6s0ANDog3uwA0cHavVlnTQzGCN7Id2YekDSXA== dependencies: - playwright-core "1.50.1" + playwright-core "1.51.0" optionalDependencies: fsevents "2.3.2" @@ -2942,9 +2942,9 @@ tar-stream@^3.1.5: streamx "^2.15.0" terser-webpack-plugin@^5.3.11: - version "5.3.12" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.12.tgz#d9518c80493081bace668aa8613b22e4a838810c" - integrity sha512-jDLYqo7oF8tJIttjXO6jBY5Hk8p3A8W4ttih7cCEq64fQFWmgJ4VqAQjKr7WwIDlmXKEc6QeoRb5ecjZ+2afcg== + version "5.3.14" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" + integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5"