Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question / bug] Accessing .warnings and .errors from JS w/ plugins #745

Closed
zaydek opened this issue Feb 3, 2021 · 7 comments
Closed

[Question / bug] Accessing .warnings and .errors from JS w/ plugins #745

zaydek opened this issue Feb 3, 2021 · 7 comments

Comments

@zaydek
Copy link

zaydek commented Feb 3, 2021

(Similar to #665)

I’m having trouble accessing the .warnings and .errors values when plugins is active, for the JS API. When plugins is inactive, this works as expected. But once I enable plugins: [envPlugin], for example, I get undefined; undefined.

I assume this is because esbuild is exiting early, but I’m not sure how to capture the output still. I’ve been reading the JS source but I haven’t been able to figure this out for myself.

// https://esbuild.github.io/plugins/#using-plugins
const envPlugin = {
	names: "env",
	setup(build) {
		// Intercept import paths called "env" so esbuild doesn't attempt
		// to map them to a file system location. Tag them with the "env-ns"
		// namespace to reserve them for this plugin.
		build.onResolve({ filter: /^env$/ }, args => ({
			path: args.path,
			namespace: "env-ns",
		}))
		// Load paths tagged with the "env-ns" namespace and behave as if
		// they point to a JSON file containing the environment variables.
		build.onLoad({ filter: /.*/, namespace: "env-ns" }, () => ({
			contents: JSON.stringify(process.env),
			loader: "json",
		}))
	},
}

require("esbuild")
	.build({
		bundle: true,
		entryPoints: ["app.js"],
		logLevel: "silent",
		outfile: "out.js",
		// plugins: [envPlugin], // <- Uncomment here
	})
	.catch(err => {
		console.log(err.errors)
		console.log(err.warnings)
	})

Expected output:

[
  {
    detail: undefined,
    location: {
      column: 7,
      file: 'app.js',
      length: 1,
      line: 1,
      lineText: 'imports{ PATH } from "env"'
    },
    text: 'Expected ";" but found "{"'
  }
]
[]

Actual output (when plugins are enabled):

undefined
undefined
@evanw
Copy link
Owner

evanw commented Feb 3, 2021

What does the text of the error say? Is it perhaps not one of esbuild's errors? It's possible that a non-esbuild error was thrown and was captured by the promise.

@zaydek
Copy link
Author

zaydek commented Feb 4, 2021

Well when I uncomment there is no error, at least esbuild returns undefined and therefore there are no .errors or .warnings attached to the result. silent prevents the error from being logged to stderr but what I wanted is to interact with errors and warnings as a data structure.

I assume the plugin causes an internal error that isn’t passed back to the user.

@evanw
Copy link
Owner

evanw commented Feb 4, 2021

If this code:

	.catch(err => {
		console.log(err.errors)
		console.log(err.warnings)
	})

results in this output:

undefined
undefined

then presumably an error is being thrown somewhere and err is an object without the errors or warnings properties. It would be helpful for me to know what the error is to get a better idea of where it's coming from. Then I should be in a better position to do something about this problem.

@zaydek
Copy link
Author

zaydek commented Feb 4, 2021

Sorry that wasn’t more useful. I created a minimum repro here https://github.com/zaydek/esbuild-plugin-behavior.

The specific answer to your question; I get this error when plugins are enabled:

Error: Plugin at index 0 is missing a name
	at handlePlugins (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:642:15)
	at Object.buildOrServe (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:872:26)
	at /Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1344:17
	at new Promise (<anonymous>)
	at Object.build (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1343:14)
	at Object.build (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1204:26)
	at /Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1252:67
	at processTicksAndRejections (node:internal/process/task_queues:93:5)

In the repro, esbuild.js:

// Command: node esbuild.js

// https://esbuild.github.io/plugins/#using-plugins
const envPlugin = {
	// Intentionally uses names instead of name to break esbuild; the intent is to
	// make sure esbuild emits errors whether or not plugins are being used.
	names: "env",
	setup(build) {
		build.onResolve({ filter: /^env$/ }, args => ({
			path: args.path,
			namespace: "env-ns",
		}))
		build.onLoad({ filter: /.*/, namespace: "env-ns" }, () => ({
			contents: JSON.stringify(process.env),
			loader: "json",
		}))
	},
}

require("esbuild")
	.build({
		bundle: true,
		entryPoints: ["in/app.js"],
		logLevel: "silent",
		outfile: "out/out.js",
		// plugins: [envPlugin],
	})
	.catch(err => {
		console.log({ err })
	})

// I get expected output when plugins are disabled (commented out). This is
// what I expect; the error is an object that has properties .errors and
// .warnings which I can use.
//
// {
//   err: Error: Build failed with 1 error:
//   in/app.js:1:7: error: Expected ";" but found "{"
//       at failureErrorWithLog (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1124:15)
//       at buildResponseToResult (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:879:32)
//       at /Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:974:20
//       at /Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:541:9
//       at handleIncomingPacket (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:624:9)
//       at Socket.readFromStdout (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:508:7)
//       at Socket.emit (node:events:329:20)
//       at addChunk (node:internal/streams/readable:304:12)
//       at readableAddChunk (node:internal/streams/readable:279:9)
//       at Socket.Readable.push (node:internal/streams/readable:218:10) {
//     errors: [ [Object] ],
//     warnings: []
//   }
// }
//
// I get unexpected output when plugins are enabled. This is undesirable because
// I want to be able to introspect on .errors and .warnings.
//
// {
//   err: Error: Plugin at index 0 is missing a name
//       at handlePlugins (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:642:15)
//       at Object.buildOrServe (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:872:26)
//       at /Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1344:17
//       at new Promise (<anonymous>)
//       at Object.build (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1343:14)
//       at Object.build (/Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1204:26)
//       at /Users/zaydek/github/retro-plugin-arch/node_modules/esbuild/lib/main.js:1252:67
//       at processTicksAndRejections (node:internal/process/task_queues:93:5)
// }

Tested on 0.8.40.

@evanw
Copy link
Owner

evanw commented Feb 4, 2021

Thanks for the detail. That makes it much more clear what's happening. At one point I was trying to funnel all validation errors through esbuild's general error function, but clearly that's not happening here. This is something to fix.

@zaydek
Copy link
Author

zaydek commented Feb 4, 2021

Thank you Evan. I’m glad we’re synced up now. I’ll tag related issues for organizational purposes:

#665
#688

@evanw evanw closed this as completed in 4c4cf22 Feb 5, 2021
@zaydek
Copy link
Author

zaydek commented Feb 5, 2021

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants