From 43ac3f5fab0c51b98ed59673f438f60768d001fb Mon Sep 17 00:00:00 2001 From: bodhibuurstede-sys Date: Mon, 11 May 2026 13:41:34 +0200 Subject: [PATCH 1/3] Fix local resource file URLs with hash characters --- newIDE/app/src/ResourcesLoader/index.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/newIDE/app/src/ResourcesLoader/index.js b/newIDE/app/src/ResourcesLoader/index.js index 43f2d79d6d80..a80731b81d46 100644 --- a/newIDE/app/src/ResourcesLoader/index.js +++ b/newIDE/app/src/ResourcesLoader/index.js @@ -79,6 +79,21 @@ const isLocalFile = (urlOrFilename: string) => { ); }; +export const getLocalFileUrl = (resourceAbsolutePath: string): string => { + const normalizedPath = resourceAbsolutePath.replace(/\\/g, '/'); + const pathWithLeadingSlash = normalizedPath.startsWith('/') + ? normalizedPath + : '/' + normalizedPath; + + return ( + 'file://' + + pathWithLeadingSlash + .split('/') + .map(pathSegment => encodeURIComponent(pathSegment).replace(/%3A/g, ':')) + .join('/') + ); +}; + /** * A class globally used in the whole IDE to get URLs to resources of games * (notably images). @@ -140,7 +155,7 @@ export default class ResourcesLoader { return this._cache.cacheLocalFileUrl( project, urlOrFilename, - 'file://' + resourceAbsolutePath, + getLocalFileUrl(resourceAbsolutePath), !!disableCacheBurst ); } From c939ba6f9c2fbfcd29cb011190202a18a405a180 Mon Sep 17 00:00:00 2001 From: bodhibuurstede-sys Date: Mon, 11 May 2026 13:41:49 +0200 Subject: [PATCH 2/3] Add coverage for local resource URLs with hashes --- newIDE/app/src/ResourcesLoader/index.spec.js | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 newIDE/app/src/ResourcesLoader/index.spec.js diff --git a/newIDE/app/src/ResourcesLoader/index.spec.js b/newIDE/app/src/ResourcesLoader/index.spec.js new file mode 100644 index 000000000000..01a20d2d252b --- /dev/null +++ b/newIDE/app/src/ResourcesLoader/index.spec.js @@ -0,0 +1,25 @@ +// @flow +import { getLocalFileUrl } from './index'; + +describe('ResourcesLoader', () => { + it('encodes hash characters in local file paths', () => { + const localFileUrl = getLocalFileUrl( + 'E:/Realisations/GDevelop_branding/Press/itch.io/Game Jam/Weekend Jam #1/Parts/hero.png' + ); + + expect(localFileUrl).toBe( + 'file:///E:/Realisations/GDevelop_branding/Press/itch.io/Game%20Jam/Weekend%20Jam%20%231/Parts/hero.png' + ); + expect(new URL(localFileUrl).hash).toBe(''); + }); + + it('keeps cache-busting parameters outside of the local file path', () => { + const cachedLocalFileUrl = + getLocalFileUrl('C:/Project/Sprites/hero#idle.png') + '?cache=123'; + const parsedUrl = new URL(cachedLocalFileUrl); + + expect(parsedUrl.pathname).toBe('/C:/Project/Sprites/hero%23idle.png'); + expect(parsedUrl.search).toBe('?cache=123'); + expect(parsedUrl.hash).toBe(''); + }); +}); From 2e7cf7ac4863566af41d5af6994132ef2c806189 Mon Sep 17 00:00:00 2001 From: bodhibuurstede-sys Date: Tue, 12 May 2026 21:40:58 +0200 Subject: [PATCH 3/3] Try master commit libGD builds before master latest --- newIDE/app/scripts/import-libGD.js | 131 ++++++++++++++++++----------- 1 file changed, 84 insertions(+), 47 deletions(-) diff --git a/newIDE/app/scripts/import-libGD.js b/newIDE/app/scripts/import-libGD.js index 2accaaeac2f9..7c705358265e 100644 --- a/newIDE/app/scripts/import-libGD.js +++ b/newIDE/app/scripts/import-libGD.js @@ -66,17 +66,28 @@ if (shell.test('-f', path.join(sourceDirectory, 'libGD.js'))) { return branch; }; - // Try to download libGD.js from a specific commit on the current branch - const downloadCommitLibGdJs = (branch, gitRef) => + const getHashFromGitRef = gitRef => { + const hashShellString = shell.exec(`git rev-parse "${gitRef}"`, { + silent: true, + }); + const hash = (hashShellString.stdout || 'unknown-hash').trim(); + + if (hashShellString.stderr || hashShellString.code) { + shell.echo(`⚠️ Can't find the hash of the associated commit.`); + return null; + } + + return hash; + }; + + // Try to download libGD.js from a specific commit on the inferred branch. + const downloadCommitLibGdJs = gitRef => new Promise((resolve, reject) => { shell.echo(`ℹ️ Trying to download libGD.js for ${gitRef}.`); - var hashShellString = shell.exec(`git rev-parse "${gitRef}"`, { - silent: true, - }); - const hash = (hashShellString.stdout || 'unknown-hash').trim(); + const hash = getHashFromGitRef(gitRef); const branch = getBranchFromGitRef(gitRef); - if (hashShellString.stderr || hashShellString.code || !branch) { + if (!hash || !branch) { shell.echo( `⚠️ Can't find the hash or branch of the associated commit.` ); @@ -91,6 +102,25 @@ if (shell.test('-f', path.join(sourceDirectory, 'libGD.js'))) { ); }); + const downloadMasterCommitLibGdJs = gitRef => + new Promise((resolve, reject) => { + shell.echo( + `ℹ️ Trying to download libGD.js for ${gitRef} from master.` + ); + + const hash = getHashFromGitRef(gitRef); + if (!hash) { + reject(); + return; + } + + resolve( + downloadLibGdJs( + `https://s3.amazonaws.com/gdevelop-gdevelop.js/master/commit/${hash}` + ) + ); + }); + // Try to download libGD.js from the latest version built for master branch. const downloadBranchLatestLibGdJs = branchName => { shell.echo( @@ -151,48 +181,55 @@ if (shell.test('-f', path.join(sourceDirectory, 'libGD.js'))) { }; const branch = getBranchFromGitRef('HEAD'); + const downloadCommitLibGdJsWithMasterFallback = gitRef => + downloadCommitLibGdJs(gitRef).catch(() => + downloadMasterCommitLibGdJs(gitRef) + ); + const tryDownloadInOrder = downloaders => + downloaders.reduce( + (previousDownload, download) => previousDownload.catch(() => download()), + Promise.reject() + ); // Try to download the latest libGD.js, fallback to previous or master ones // if not found (including different parents, for handling of merge commits). - downloadCommitLibGdJs(branch, 'HEAD').then(onLibGdJsDownloaded, () => { - // Force the exact version of GDevelop.js to be downloaded for AppVeyor - because - // this means we build the app and we don't want to risk mismatch (Core C++ not up to date - // with the IDE JavaScript). - if (process.env.APPVEYOR || process.env.REQUIRES_EXACT_LIBGD_JS_VERSION) { - shell.echo( - `❌ Can't download the exact required version of libGD.js - check it was built by CircleCI before running this CI.` - ); - shell.echo( - `ℹ️ See the pipeline on https://app.circleci.com/pipelines/github/4ian/GDevelop.` - ); - shell.exit(1); - } + downloadCommitLibGdJsWithMasterFallback('HEAD').then( + onLibGdJsDownloaded, + () => { + // Force the exact version of GDevelop.js to be downloaded for AppVeyor - because + // this means we build the app and we don't want to risk mismatch (Core C++ not up to date + // with the IDE JavaScript). + if (process.env.APPVEYOR || process.env.REQUIRES_EXACT_LIBGD_JS_VERSION) { + shell.echo( + `❌ Can't download the exact required version of libGD.js - check it was built by CircleCI before running this CI.` + ); + shell.echo( + `ℹ️ See the pipeline on https://app.circleci.com/pipelines/github/4ian/GDevelop.` + ); + shell.exit(1); + } - downloadCommitLibGdJs(branch, 'HEAD~1').then(onLibGdJsDownloaded, () => - downloadCommitLibGdJs(branch, 'HEAD~2').then(onLibGdJsDownloaded, () => - downloadCommitLibGdJs(branch, 'HEAD~3').then(onLibGdJsDownloaded, () => - downloadBranchLatestLibGdJs(branch).then(onLibGdJsDownloaded, () => - downloadBranchLatestLibGdJs('master').then( - onLibGdJsDownloaded, - () => { - if (alreadyHasLibGdJs) { - shell.echo( - `ℹ️ Can't download any version of libGD.js, assuming you can go ahead with the existing one.` - ); - shell.exit(0); - return; - } else { - shell.echo( - `❌ Can't download any version of libGD.js, please check your internet connection.` - ); - shell.exit(1); - return; - } - } - ) - ) - ) - ) - ); - }); + tryDownloadInOrder([ + () => downloadCommitLibGdJsWithMasterFallback('HEAD~1'), + () => downloadCommitLibGdJsWithMasterFallback('HEAD~2'), + () => downloadCommitLibGdJsWithMasterFallback('HEAD~3'), + () => downloadBranchLatestLibGdJs(branch), + () => downloadBranchLatestLibGdJs('master'), + ]).then(onLibGdJsDownloaded, () => { + if (alreadyHasLibGdJs) { + shell.echo( + `ℹ️ Can't download any version of libGD.js, assuming you can go ahead with the existing one.` + ); + shell.exit(0); + return; + } else { + shell.echo( + `❌ Can't download any version of libGD.js, please check your internet connection.` + ); + shell.exit(1); + return; + } + }); + } + ); }