From 37480bc97401f9a37938886be2c9b0ceeac76428 Mon Sep 17 00:00:00 2001 From: Jonas Amundsen Date: Mon, 3 Nov 2025 15:52:11 +0100 Subject: [PATCH 1/4] Await resolving on 1st run unti bunde has made it to fs Void of this, users running a spec for the 1st time would get a ENOENT error momentarily before before the preprocessor would emit 'rerun'. Users using watchForFileChanges: false would see said error until explicitly pressing rerun in the runner GUI. --- src/index.js | 108 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 40 deletions(-) diff --git a/src/index.js b/src/index.js index ab50c75..725a803 100644 --- a/src/index.js +++ b/src/index.js @@ -76,53 +76,81 @@ const createBundler = (esBuildUserOptions = {}) => { outfile: outputPath, bundle: true, } - // our plugin for new watch mode of esbuild 0.17.0 - const customBuildPlugin = { - name: 'cypress-esbuild-watch-plugin', - setup(build) { - build.onEnd((result) => { - if (result.errors.length > 0) { - debug( - 'watch on %s build failed, errors %o', - filePath, - result.errors, - ) - - bundled[filePath] = new Promise((resolve, reject) => { - esbuild + + let isResolved = false; + + bundled[filePath] = new Promise((resolve, reject) => { + // our plugin for new watch mode of esbuild 0.17.0 + const customBuildPlugin = { + name: 'cypress-esbuild-watch-plugin', + setup(build) { + build.onEnd(async (result) => { + if (result.errors.length > 0) { + debug( + 'watch on %s build failed, errors %o', + filePath, + result.errors, + ) + + result = [undefined, await esbuild .formatMessages(result.errors, { kind: 'error', color: false, }) .then((messages) => reject(new Error(messages.join('\n\n')))) - }) - - file.emit('rerun') - return - } - - debug( - 'watch on %s build succeeded, warnings %o', - filePath, - result.warnings, - ) - file.emit('rerun') - }) - }, - } - const plugins = esBuildOptions.plugins ? [...esBuildOptions.plugins, customBuildPlugin] : [customBuildPlugin]; - bundled[filePath] = esbuild.context({...esBuildOptions, plugins}).then((watcher) => { - watcher.watch().then((_) => { - // when the test runner closes this spec - file.on('close', () => { - debug('file %s close, removing bundle promise', filePath) - delete bundled[filePath] - watcher.dispose() + ] + } else { + result = [outputPath, undefined] + + debug( + 'watch on %s build succeeded, warnings %o', + filePath, + result.warnings, + ) + } + + if (isResolved) { + debug( + 'rerun %s', + filePath, + ) + debug((await require("fs/promises").readFile(outputPath)).toString()) + bundled[filePath] = result[0] ? Promise.resolve(result[0]) : Promise.reject(result[1]) + file.emit('rerun') + } else { + if (result[0]) { + debug( + 'resolving %s for the 1st time', + filePath, + ) + resolve(result[0]) + } else { + debug( + 'rejecting %s for the 1st time', + filePath, + ) + reject(result[1]) + } + + isResolved = true; + } + }) + }, + } + + const plugins = esBuildOptions.plugins ? [...esBuildOptions.plugins, customBuildPlugin] : [customBuildPlugin]; + + esbuild.context({...esBuildOptions, plugins}).then((watcher) => { + watcher.watch().then((_) => { + // when the test runner closes this spec + file.on('close', () => { + debug('file %s close, removing bundle promise', filePath) + delete bundled[filePath] + watcher.dispose() + }) }) }) - - return outputPath - }) + }); return bundled[filePath] } From 171516e212bbceac97acca8658ec1844c5211344 Mon Sep 17 00:00:00 2001 From: Jonas Amundsen Date: Mon, 3 Nov 2025 16:00:20 +0100 Subject: [PATCH 2/4] Remove debug output --- src/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/index.js b/src/index.js index 725a803..365697f 100644 --- a/src/index.js +++ b/src/index.js @@ -114,7 +114,6 @@ const createBundler = (esBuildUserOptions = {}) => { 'rerun %s', filePath, ) - debug((await require("fs/promises").readFile(outputPath)).toString()) bundled[filePath] = result[0] ? Promise.resolve(result[0]) : Promise.reject(result[1]) file.emit('rerun') } else { From d6ef90afa4cd0b719a1b21290616eaeca8c1bd81 Mon Sep 17 00:00:00 2001 From: Jonas Amundsen Date: Mon, 3 Nov 2025 19:53:32 +0100 Subject: [PATCH 3/4] Prettier --- src/index.js | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/src/index.js b/src/index.js index 365697f..8f5f1c6 100644 --- a/src/index.js +++ b/src/index.js @@ -77,7 +77,7 @@ const createBundler = (esBuildUserOptions = {}) => { bundle: true, } - let isResolved = false; + let isResolved = false bundled[filePath] = new Promise((resolve, reject) => { // our plugin for new watch mode of esbuild 0.17.0 @@ -92,12 +92,14 @@ const createBundler = (esBuildUserOptions = {}) => { result.errors, ) - result = [undefined, await esbuild - .formatMessages(result.errors, { - kind: 'error', - color: false, - }) - .then((messages) => reject(new Error(messages.join('\n\n')))) + result = [ + undefined, + await esbuild + .formatMessages(result.errors, { + kind: 'error', + color: false, + }) + .then((messages) => reject(new Error(messages.join('\n\n')))), ] } else { result = [outputPath, undefined] @@ -110,36 +112,31 @@ const createBundler = (esBuildUserOptions = {}) => { } if (isResolved) { - debug( - 'rerun %s', - filePath, - ) - bundled[filePath] = result[0] ? Promise.resolve(result[0]) : Promise.reject(result[1]) + debug('rerun %s', filePath) + bundled[filePath] = result[0] + ? Promise.resolve(result[0]) + : Promise.reject(result[1]) file.emit('rerun') } else { if (result[0]) { - debug( - 'resolving %s for the 1st time', - filePath, - ) + debug('resolving %s for the 1st time', filePath) resolve(result[0]) } else { - debug( - 'rejecting %s for the 1st time', - filePath, - ) + debug('rejecting %s for the 1st time', filePath) reject(result[1]) } - isResolved = true; + isResolved = true } }) }, } - const plugins = esBuildOptions.plugins ? [...esBuildOptions.plugins, customBuildPlugin] : [customBuildPlugin]; + const plugins = esBuildOptions.plugins + ? [...esBuildOptions.plugins, customBuildPlugin] + : [customBuildPlugin] - esbuild.context({...esBuildOptions, plugins}).then((watcher) => { + esbuild.context({ ...esBuildOptions, plugins }).then((watcher) => { watcher.watch().then((_) => { // when the test runner closes this spec file.on('close', () => { @@ -149,7 +146,7 @@ const createBundler = (esBuildUserOptions = {}) => { }) }) }) - }); + }) return bundled[filePath] } From 67ad427fecf9e53c9c46b31a073d3a66fc9a1a4f Mon Sep 17 00:00:00 2001 From: Jonas Amundsen Date: Mon, 3 Nov 2025 19:54:30 +0100 Subject: [PATCH 4/4] Correctly return errors --- src/index.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index 8f5f1c6..73fefc7 100644 --- a/src/index.js +++ b/src/index.js @@ -94,12 +94,10 @@ const createBundler = (esBuildUserOptions = {}) => { result = [ undefined, - await esbuild - .formatMessages(result.errors, { - kind: 'error', - color: false, - }) - .then((messages) => reject(new Error(messages.join('\n\n')))), + await esbuild.formatMessages(result.errors, { + kind: 'error', + color: false, + }), ] } else { result = [outputPath, undefined]