We have an app that allows to enter a scripts. These scripts can be in multiple files, so when there is an exception we want to be able to show a stack trace to the app admin so he can diagnose the issue.
Is there there a way to extract the stack trace from a Rhino exception?
First of all, in order to get a good stack trace, you need to be very careful when evaluating scripts in your scope. I've seen that this is overlooked by many developers where they always send the same params for sourceName and lineno, like:
ctx.evaluateString(scriptScope, script, "script", 0, null);
So in the 3rd and 4th params you have to send the file name of something that will help the developer identify the script. Then, the line number should be correct, in case you concatenate scripts.
So, once you evaluate all the scripts in your context correctly, you can be able to get a useful stack track. So just catch the exception and process the info in the stack trace:
try {
// execute script
} catch (RhinoException re) {
StackTraceElement[] stackTrace = re.getStackTrace();
if (stackTrace != null) {
for (StackTraceElement stackElement : stackTrace) {
// stackElement.getFileName();
// stackElement.getLineNumber();
}
}
}
Related
I inject content scripts into websites programmatically using browser.tabs.executeScript. This will return a Promise, but in case of its rejection there seems to be no way of differentiating between the following 2 cases:
The content script couldn't be injected (i.e. for missing host
permission)
An error occured on script updateparsingend:update(but the script was being injected)
I'm only interested in whether the script was being injected or not.
The argument passed to the catch is an Error object.
catch(e => console.log(e.toString()) will output the error message, which can either be a reason for an injection failure (i.e. Missing host permission) or an error that occurred updatereading the scriptend:update.
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.catch(e => console.log(e.toString()));
So, for example if the content script is as follows:
window.document.body.addEventListener('click', e => console.log('clicked body'), false);
bla.bla();
then the Promise is being rejected, since bla.bla is undefined - but the script was being injected successfully.
In case the content script couldn't be injected I'd like to notify the user with the corresponding error message.
But when an error occurred updatethat is unrelated to whether the script could be injectedend:update, while the script was being injected, I don't want to notify the user, but handle it silently.
Is there a way to differentiate between those 2 cases?
EDIT: I came up with an indirect solution: In case the returned Promise was rejected I try to send a message to the content script. If this fails then the background script "knows" that no content script was being injected -> notify user.
This is how the Promise works....
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.catch(e => console.log(e.toString()));
catch in above will catch errors if the tabs.executeScript failed to inject. It may also show some errors when parsing the file in order to inject, if the JS file has parsing errors (invalid JS). It has nothing to do with what '../path/to/content-script.js' will be doing afterwards.
So once it was injected, then above Promise is fulfilled.
If the injected script has a sync return, then it can be received by the tabs.executeScript via then() e.g.
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.then(result => {})
.catch(e => console.log(e.toString()));
In case of async functions such as .addEventListener which will happen later, then is nothing returned to tabs.executeScript
To catch errors in the content scripts, you can generate the error message within the content script or send a message to background script i.e. sendMessage & onMessage.addListener
tabs.executeScript()
A Promise that will be fulfilled with an array of objects,
representing the result of the script in every injected frame.
The result of the script is the last evaluated statement, which is
similar to what would be output (the results, not any console.log()
output) if you executed the script in the Web Console. For example,
consider a script like this:
var foo='my result';foo;
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.then(result => {
// result is returned by the Promise
if (result === []) {
// it was fine but there was nothing to return
}
else if (result[0]) {
// result[0] is return from the promise
}
})
.catch(e => console.log(e.toString()));
Now if you want a return (it must be sync or else you have to tie it to another Promise), return something from '../path/to/content-script.js'
I am building a jenkins pipeline plugin (methods to be invoked from a pipeline) and need to get retrieve information about the currently running job, which invoked my methods.
There are a couple of questions I found talking about it, for example here - Jenkins Plugin How to get Job information.
Yet I can't figure out how to use this information. I do have access to the Jenkins instance, but don't have any info about the current project, job, build, etc. How can I get hold of that info?
Note, this is a pipeline steps plugin, there is no perform method in it.
Ok, after search, I finally found the answer in the most obvious of all places - documentation for writing pipeline steps plugins and the corresponding API documentation.
The way to do it is from the Execution class. Inside it, just call getContext(), which returns StepContext, which then has .get method to get the rest of the things you need:
public class MyExecution extends SynchronousNonBlockingStepExecution<ReturnType> {
...
#Override
protected ReturnType run() throws Exception {
try {
StepContext context = getContex();
// get currently used workspace path
FilePath path = context.get(FilePath.class);
//get current run
Run run = context.get(Run.class);
// ... and so on ...
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
...
}
I'm writing a yeoman generator and want to check some prerequisites, for example a git being installed. I can easily check this using .exec, but how do i gracefully abort generator and report error to user? I searched docs, but it seems that i'm missing some obvious way to do it. Any hints?
Throwing exception will of course abort generator, but is it a best way? Maybe something more user friendly? Not all yeoman users are able to read js exceptions.
The current state of error handling in the popular generators is quite diverse:
in the most cases they just log the error and return from the action and let the subsequnt actions run and return 0 status code:
generator-karma's setupTravis method:
if (err) {
this.log.error('Could not open package.json for reading.', err);
done();
return;
}
or set a custom abort property on error and skip further actions with cheking on the abort property but still return 0 status code:
generator-jhipster's CloudFoundryGenerator:
CloudFoundryGenerator.prototype.checkInstallation = function checkInstallation() {
if(this.abort) return;
var done = this.async();
exec('cf --version', function (err) {
if (err) {
this.log.error('cloudfoundry\'s cf command line interface is not available. ' +
'You can install it via https://github.com/cloudfoundry/cli/releases');
this.abort = true;
}
done();
}.bind(this));
};
or manually end the process with process.exit:
generator-mobile's configuringmethod:
if (err) {
self.log.error(err);
process.exit(1);
}
However none of these methods provide a good way to signal to the environment that something went wrong except the last one but directly calling process.exit is a design smell.
Throwing an exception is also an option but this presents also the stackstrace to the user which is not always a good idea.
The best option would be use the Environment.error method, which has some nice advantages:
the Environment is exposed thorough the env property of the yeoman.generators.Base
an error event is emitted which is handled by the yo cli code
the execution will result in a non zero (error) status code which is override-able
by default yo will display only the message and no stacktrace
the stacktrace can be optionally displayed with providing the --debug built-in option when re-running the generator.
With using this technique your action method would look like this:
module.exports = generators.Base.extend({
method1: function () {
console.log('method 1 just ran');
this.env.error("something bad is happened");
console.log('this won't be executed');
},
method2: function () {
console.log('this won't be executed');
}
});
I am wondering if anyone knows what URL is required (as a GET or POST) that will get the status code (result) of the last Jenkins job (when the build# is not known by the client calling the GET request)? I just want to be able to detect if the result was RED or GREEN/BLUE .
I have this code sample, but I need to adjust it so that it works for Jenkins, for this purpose (as stated above):
public class Main {
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost/jenkins/api/xml");
Document dom = new SAXReader().read(url);
for( Element job : (List<Element>)dom.getRootElement().elements("job")) {
System.out.println(String.format("Name:%s\tStatus:%s",
job.elementText("name"), job.elementText("color")));
}
}
}
Once I figure out the answer, I will share a full example of how I used it. I want to create a job that collects information on a test suite of 20+ jobs and reports on all of them with an email.
You can use the symbolic descriptor lastBuild:
http://localhost/jenkins/job/<jobName>/lastBuild/api/xml
The result element contains a string describing the outcome of the build.
Say, I have the following code that I run as a .JS file using the Windows Script Host:
try
{
ProduceAnError();
}
catch(e)
{
//How to get an error line here?
}
Is there any way to know the error line where an error (exception) occurred?
Sorry for my other reply. It wasn't very helpful :P
I believe what you are looking for is the ReferenceError's stack property. You can access it with the argument that you pass to the catch:
try {
someUndefinedFunction("test");
} catch(e) {
console.log(e.stack)
}
example output:
ReferenceError: someUndefinedFunction is not defined
at message (http://example.com/example.html:4:3)
at <error: TypeError: Accessing selectionEnd on an input element that cannot have a selection.>
at HTMLInputElement.onclick (http://example.com/example.html:25:4)
There isn't really a way to get a stack or even catch the line number programmatically. One can only see the line number when throwing an error. At best you can get the error code and description or you can make your own errors.
Here's the documentation.
And an example
try {
produceAnError();
} catch(e) {
WScript.echo((e.number>>16 & 0x1FFF)); // Prints Facility Code
WScript.echo((e.number & 0xFFFF)); // Prints Error Code
WScript.echo(e.description); // Prints Description
throw e;
}