This tutorial shows you how to work with the JavaScript features in Acrobat 9. See what the all-new Acrobat DC can do for you.

Download a free trial of the new Acrobat.

How to debug your script using Acrobat 9

Learn how to debug Acrobat JavaScript code, including some of the common bugs you'll find.

By Thom Parker – July 29, 2010

 

Have you written or copied a script with high expectations of all the great things the script would do, only to find out that it doesn't work? Well, you have company. Judging from the Acrobat discussion forums, getting a script to work is one of the biggest problems around. The answer is to role up your sleeves and figure out what's wrong--something we call debugging.

The Golden Rule of debugging code

The name of the game in software debug is to isolate the issue. More often than not, just narrowing down the real source of the error is enough to identify the specific issue and fix it. It is very easy with complex forms and code to be misled by surface behavior. Everything we'll discuss in this article is about developing the skills and tools to correctly implement this one concept. Isolating the real source of an error is the first and most important step in finding and fixing a problem--it's the Golden Rule of debug.

It's not magic (use a reference)

It's about paying attention to the details and there is no substitute. Programming languages by their nature follow very strict rules. Acrobat JavaScript is much easier to work with and much more forgiving than other programming languages. But it is still a programming language, and thus has rules: Syntax rules, logic rules and general operational rules. In order to do debug, it is necessary to have some sense of these rules. You don't have to memorize anything. It's only important to have a sense of what's going on and a reference. The reference is where the details come from.

A programming reference can be very cryptic to the novice. But don't get intimidated. You absolutely need the reference. A reference is not like other books. You can't read it from beginning to end to make sense out of it. If you think you've found a "thing" in the code that is the source of the problem, you open up the reference to the entry for that thing and see what it has to say. The trick to using any reference is to only look at the things that already make sense to you. Don't think too hard about it. It's very easy to over-think or read too much into reference data. Reference entries usually provide very terse and incomplete information that assumes an overall knowledge of the topic. In other words, they aren't much good unless you already know what you're doing. That's why you don't want to look too hard. If you're new to the topic, then you just want to compare the reference entry to the "thing" in the code. After doing this a few times and skipping around in the reference, everything will become much clearer. But don't try to force it.

You'll need two references. The first one is a reference on Core JavaScript. This is the programming language used to script Acrobat. The reference will provide basic information on JavaScript keywords, syntax and usage. The second is the Acrobat JavaScript Reference, which contains a listing of all the Document Object Model functions and properties. This reference only contains information on the functions and properties specific to Acrobat. It does not contain any information on the core language. It is very important to understand the difference between what is core and what is Acrobat specific, and this is just the kind of thing you'll learn by using the two references.

The console window (the main debugging tool)

The discussion so far begs the question, "How exactly do you start isolating the bug?" The answer is that you need a tool that provides a window into the inner workings of the code as it runs in Acrobat. And that tool is the console window, for which I've already written an article and produced a video. It's that important.

Since I've already written about it, I won't provide the details here, but the console is important for three reasons. First, it's a place to test code. If a small section of code is problematic for any reason, you ought to be working out the kinks in the console window where you can quickly make changes and see the results. Second, Acrobat displays all unhandled exceptions in the console window. So if there is a problem, always look in the console window first to see if an exception has been reported. Third, you can add trace statements to your code that will display in the console window. This is the number-one way to isolate a problem. Pepper the code with trace statements and then watch them print in the console window as the code runs.

Here's the first code of the article:

console.println("this is a trace statement");

This line of code, when run, will print the words "this is a trace statement" in the console window. This is a trace statement, and placing lines like this one in various locations in your script will allow you to find the exact piece of problem code. A trace statement can print out a simple string so you know the code ran to at least that place, or it can print out a value being calculated by the script. Either way, this is the most powerful tool in your debug toolset.

Techniques

Our job is to narrow the problem to the smallest piece of code possible. There are several different techniques that can be used separately or combined. To see an example of this in action, I wrote an article that walks through a debug session on a single piece of code (that contains several common errors) called Why doesn't my script work? But here, I'll discuss each technique separately.

Technique #1: Look in the console window. Always do this first when something goes wrong. If Acrobat is throwing an unhandled exception, it will appear here. The exception message may provide an exact code location and information that makes the bug obvious.

If the preferences are set up correctly (see the articles on the console window), all exceptions will be displayed. Be careful though--handled exceptions can flood the console window with meaningless errors. Only display all exceptions when you are looking for something specific.

Technique #2: Examine intermediate steps. This is the most general-purpose technique and can be used in many different ways. The basic idea is to place trace statements at key locations within the code so you can see the operation of the code in real time. If a value is being calculated, then use the trace statements to display the intermediate values. If conditional statements or loops are used in the code, then place the trace statements to indicate which path the code takes. You can even write special conditional debug code that displays traces only under certain conditions. These trace messages will give you an inside look at how the code is actually working and usually allow you to quickly find the location of a bug.

Technique: #3: Isolate/test code segments in console. If a particular segment of code is not performing correctly, then it is much more efficient to develop/debug the code segment in the console window where you have immediate and direct control. The code can be run line by line or in groups.

The conditions on loops and "ifs" can be tested separately from the contents, and test conditions can be varied quickly and easily. This is especially important for developing a complex algorithm, or a piece of code such as a regular expression.

Technique: #4: Isolate code segments on a test document. If the script depends on Acrobat or form events, then it cannot be isolated in the console. Create a minimal test document for developing/debugging just the code in question. This technique isolates the code from events, scripts or other bugs in the main working PDF or script that may interfere with debug. It focuses your effort on the problem-at-hand and removes any misleading distractions.

Technique: #5: Block out code segments. Some errors can cause problems that can't be easily isolated by the techniques already discussed. A bug might close a document, lock up Acrobat, flood the console window with endless messages, do nothing at all, or even cause a crash. In these cases, the problem can be isolated by commenting out code so it is not executed. Use combinations of regular, //…, and block, /* … */, comments. Start by commenting out code from the bottom of the script a few lines at a time. Place a trace statement above the start of the comment so there is an indication the last line of active code was reached. Repeat the process of moving the top of the commented section and re-running the code to isolate the line on which the really bad error occurs.


Figure 1. Blocking out code is an effective method for finding a fatal error. For nested blocks of code, it is necessary to use a combination of line and block comments to both maintain structure and remove potential problems.

Common bugs

There are many kinds of coding errors that are repeated over and over, even by expert programmers. None of us are immune.

Some of the most common bugs:

  1. Spelling Errors
  2. Punctuation Errors
  3. Improper Operators
  4. Bad Names
  5. Invalid Data
  6. Thrown Exceptions

The first two items on the list are arguably the most common and most important. For the most part, these are Core JavaScript issues. These items go back to my earlier statement about rules.

Bug #1: JavaScript is case sensitive, so one of the rules is that keywords must be spelled exactly as defined in the Core JavaScript Reference, including upper and lower case letters. You also can't use keywords for anything other than the use for which they are defined. And in general, any name defined in one place must exactly match all the other places where that name is used.

Bug #2: In all programming languages, punctuation has special meaning and must be used in a very specific way. I once had an argument with a client over this line of code:

var cMsg = "Please fill out attached form";

She asserted that according to the rules of English, the semicolon at the end of the sentence needed to be inside the quotes, i.e., that it was incorrect to do it otherwise. To begin with, this is not a sentence, it's a text string, and secondly, it's not English, it's programming. The rules we follow are the rules laid out by the Core JavaScript Reference. The string is a single value assigned to a variable named cMsg using the = symbol, which is the assignment operator.

The quotes are used to delimit a text string. There must be one at the beginning of the string and a matching quote at the end of the string. In addition, these must be plain-text ASCII quotes, not the fancy curly quotes used in a word processor, like these “”. This actually happens to be one of the most common punctuation errors. It is caused by copying code from an e-mail message or word processor. Be very careful when copying code from a source that is not strictly plain text. Finally, the semicolon terminates the line of code. A misuse of any of these punctuation characters could easily result in a bug.

Like the quotes, there are many punctuation characters that come in matched pairs, for example: [ ] { } ( ) ' '. These characters are used to delimit nested entities, both code and data. It's very common when writing complex or long code to mismatch a bracket or quote, which will always result in a bug.

Bug #3: The most commonly used improper operator is the = symbol. This is the assignment operator. It is used to assign data to a variable, but is often mistakenly used as the equality operator, which is ==. There are other examples, but in general, if your code looks right, but doesn't work and doesn't throw an obvious error, it's possible you have an improper operator. Look closely and check the reference for the proper meaning of the operators you are using.

Bug #4: Bad names, or name paths, are very common with form scripting. In form scripting, each form field is named. It is critical that when used in a script, fields are properly referenced and spelled.

Bug #5: Another common form bug is invalid data. Empty fields can return a null value and calculations can result in non-numbers, such as infinity, or even text strings. A bad value in one place can cascade into other parts of the form where it's used in a calculation. To isolate this kind of error, you have to trace backward to find the original bad value. To fix it, you need to take steps to ensure the bad value is not propagated. For example, set the initial value of the field to 0, or write code to test calculation results for unacceptable values.

Bug #6: The last item on the common bug list, thrown exceptions, is not a bug in the same sense as the others listed. Obviously, there is a bug causing the exception to be thrown and it needs to be fixed. But the point here is that when a script throws an exception, the code execution stops at that point. Exceptions cause Acrobat to abort operation. To the user and the novice scripter, it may appear that one or more operations not related to the real problem are not working. Without digging deeper and isolating the real problem, the exception can be misleading.

Which brings us back to the original point: Do not make assumptions based on the surface behavior of the form. Check the console window first and then use one of the other debug techniques discussed above to dig deeper. Use your knowledge of scripting and the references to isolate the source of the real error.

My favorite Core JavaScript reference is:
"JavaScript:The Definitive Guide" by David Flanagan, O'Reilly publishers.

The official Core JavaScript web reference is here:
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference



Products covered:

Acrobat 9

Related topics:

JavaScript

Top Searches:


0 comments

Comments for this tutorial are now closed.

Comments for this tutorial are now closed.