Some notes on difficult to debug Processing.js errors

Recently I converted some Processing sketches to Processing.js using Processing 2.0a4 Pre-Release with integrated Javascript mode. In resume it’s quite straight forward, they did a great job. But I had some troubles with code that works fine in Processing but not when exported to Javascript.

Sometimes it’s quite hard to detect errors yet the applet gets exported without error messages and shows up in the browser as an empty canvas. It’s recommended to use Firebug and Chrome javascript console Javascript console in parrallel as sometimes one gives a better description than the other. But sometimes none of them shows an error so it’s quite impossible to debug the sketches.

1. Division which is expected to produce an integer might need explicit casting

One of this errors is described in the Processing.js Quickstarter Guide and describes that you have to explicitly cast any division to an integer like this:

int center = int(width/2);

2. Don’t call function when defining a class variable

Another of this difficult to detect errors is that you can’t call a function when defining a class variable. This code works in Processing but not in Processing.js:

Calculator c = new Calculator();

void setup(){
  c.display();
}

class Calculator{
  float num = log10(10000.0);

  void display() {
    text(num,50,50);
  }

  float log10(float x) {
    return (log(x) / log(10));
  }
}

You have to call the function from the constructor and not from the class variable definition. Modify line 8 and insert the constructor into the code to make the example working:

Calculator c = new Calculator();

void setup(){
  c.display();
}

class Calculator{
  float num;

  Calculator(){
    num = log10(10000.0);
  }

  void display() {
    text(num,50,50);
  }

  float log10(float x) {
    return (log(x) / log(10));
  }
}

Firebug shows an unspecified error like this: “‘Processing.js: Unable to execute pjs sketch: TypeError: $this_1.$self is undefined’ when calling method: [nsIDOMEventListener::handleEvent]“.

3. Wrong use of function that works in Processing but not in Processing.js

Some functions produce an error in Processing.js but run fine in Processing. As described in the documentation, log() function expects the values greater than 0. A use of 0 works in Processing but produces an error in Processing.js when using it as input for text() function. This line of code crashes Processing.js without showing an error:

text(log(0),10,50);

Using an explicit cast to String makes the example working:

text(str(log(0)),10,50);

This seems to be a bug in text() function, mixing data parameter with text also works fine:

text("log(0)=="+log(0),10,50);

Update: Seems to be a bug in toP5String()

4. Different use of char

The use of chars is different than in Processing “Standar” mode:

  • Comparing chars you have to use double quotes like: if (key==”i”)  instead of if (key==’i’)
  • Take care of using String.charAt(), Processing.js implementation has a bug.

5. Funcitons

There are some differences to “Standard” Processing defining functions:

  • You can’t define two functions with the same name but different amount of parameters.
  • You should not use function names that are already used for defining variables or classes, using same name for variables, classes and functions confuses Processing.js.

6. Arrays

In “Standard” Processing it does work to define a array like int num[]; – arrays in Processing.js have to be declared like described in the reference: int[] num.

Tags: , ,

7 Responses to “Some notes on difficult to debug Processing.js errors”

  1. Dirk Says:

    One thing that caused me a bit of baggage was the fact that classes can have multiple constructors, but the NUMBER of arguments in a constructor (or any method I guess) was significant.

    In java:
    Point(float x, float y) {
    // …….
    }

    Point(float theta, Point newPoint) {
    // ……..
    }

    … is fine, but when you go over to processing.js (I guess because js is loosely typed) you can’t guarantee which function will be called. My crappy fix was to add dummy arguments to differentiate between constructors (methods) but it’s making me think processing.js might not be the best choice for larger applications that benefit from (java’s) OO abstractions.

  2. Albert Schueller Says:

    This is a great thread and I thought I’d add one:
    This fails:

    moveX = (int) mouseX/(Xcanvas/3);
    moveY = (int) mouseY/(Ycanvas/3);
    if(GameState[moveY][moveX] == 0){
    GameState[moveY][moveX] = 1;
    nummoves++;
    humanmove = false;
    CheckWin();
    }

    But, this works:

    moveX = (int) mouseX/(Xcanvas/3);
    moveY = (int) mouseY/(Ycanvas/3);
    if(GameState[(int)moveY][(int)moveX] == 0){
    GameState[(int)moveY][(int)moveX] = 1;
    nummoves++;
    humanmove = false;
    CheckWin();
    }

    Note the (int) casts in the array indices on the second snippet. This in spite of the fact that the two indices are explicitly cast to int just prior in the first snippet.

  3. Albert Schueller Says:

    Actually, this works too:

    moveX = (int) (mouseX/(Xcanvas/3));
    moveY = (int) (mouseY/(Ycanvas/3));
    if(GameState[moveY][moveX] == 0){
    GameState[moveY][moveX] = 1;
    nummoves++;
    humanmove = false;
    CheckWin();
    }

    which starts to make a bit more sense, but what I left out of the previous posting is that moveX and moveY are declared int.

  4. Pomax Says:

    “You can’t define two functions with the same name but different amount of parameters.” isn’t actually true (anymore?), you can. Functions with the same number of arguments but of different types, however, are a problem.

  5. Pomax Says:

    and in response to Albert, (int) applies to the very first argument, so “(int) mouseX/(Xcanvas/3);” turns mouseX into an int, then divides it. The result is almost guaranteed a float. You either wanted int(mouseX/(Xcanvas/3))” or (int)(mouseX/(Xcanvas/3))”. The (int) cast bejaviour is correct in this case, and simply how java works. (The absence of int-casting arithmetic, however, is a JavaScript consequence, so your solution to not having int math is almost correct, but your use of casting had an error)

  6. Andy Woodly Says:

    I was running into the variable / function issue (“number is not a function”) and the integer cast issue. Your post saved me some time! Thanks!!

  7. occasional mind dumps » Blog Archive » Educational processing JS Says:

    […] Unfortunately the JavaScript port differs form the native implementation. So you can’t expect to run your *.pde files smoothlessly in the browser. Fortunately I found a blog post listing the common caveats: go.yuri.at. […]

Leave a Reply