birt icon indicating copy to clipboard operation
birt copied to clipboard

Execute Javascript error

Open fadeli1 opened this issue 2 years ago • 2 comments

birt version : 4.9.0

my expression: replaceSubScript(row["tp"])

A javascript file is referenced in the report

function replaceSubScript(str) {
	if (!str && typeof(str)!="undefined" && str!=0) {
		return "";
	}
	return str.replace("₂", "<SUB>2</SUB>");
}

Running the report gives an error: detail : org.eclipse.birt.report.engine.api.EngineException: Invalid javascript expression: TypeError: Cannot find default value for object.

i change

return str.replace("₂", "<SUB>2</SUB>");

to

return String(str).replace("₂", "<SUB>2</SUB>");

Running the report without errors

fadeli1 avatar Aug 04 '22 04:08 fadeli1

It looks like your if condition is wrong. You probably want to write:

function replaceSubScript(str) {
	if (!str) {
		return "";
	}
	return str.replace("₂", "<SUB>2</SUB>");
}

The ! operator will return true for an empty string, undefined and null.

Or dou you really want to compare a string to the number zero?

Besides, always be very careful when using string methods, in particular replace.

This is probably one of the cases where Rhino causes difficulties.

To recap: BIRT uses Javascript for logic inside the reports. BIRT uses Java internally. The Javascript engine is Rhino - a Javascript implementation written in Java. Rhino allows to acces Java objects from Javascript more or less seamlessly.

Not sure, but I think that the column bindings are actually Java objects, not Javascript objects.

This is a typical example of the "less" case.

Let us assume that the if condition is false and the expression str.replace(..., ...) is actually evaluated.

The replace methods of a Java string and a Javascript string differ significantly: The Javascript method expects a regular expression as the first argument (or a string). The Java method expects either a Java String or a Java CharSequence object as the first argument.

If str is null or a Javascript number object, e.g. 3.14 or whatever: Original code: Its replace method cannot be called. With String(str): The String constructor will always return a Javascript string "null" or "3.14", and then its (Javascript) replace method is called.

If str is a Javascript string, then String(str) is basically a no-op: Original code: The Javascript replace method is called. With String(str): ditto.

If str is a Java string: Original code: Rhino has to guess what you mean, because the Java String class has different replace methods. This probably results in an error message or an exception (I stumbled across this several times myself). With String(str): The String constructor returns an equivalent Javascript string, then its (Javascript) replace method is called.

If str is any other Java object: Original code: Will fail (if we assume that the Java class has no replace method) With String(str): I don't know what happens.

Note: I'm not absolutely sure here. Javascript as a programming language is still a kind of mystery to me.

I am using the following functions in our reports (comments are in german). They'll allow you to write "The chemical formula for water is H_2O. 3 <= Pi <= 4. A well-known constant is: 6.023 * 10^{23}'. This is a tiny subset of LaTeX syntax.

I am using ("" + text") therein which has more or less the same effect as String(text).

function escapeHtml(plaintext) {
    if (plaintext == null) {
    	return "";
    }
    return (""+plaintext).replace(/[&amp;<>"']/g, function (s) {
      var entityMap = {
          "&": "&amp;",
          "<": "&lt;",
          ">": "&gt;",
          '"': '&quot;',
          "'": '&#39;'
        };
      return entityMap[s];
    });
}

/**
*** Ersetzt gängige Formen mathematischer Operatoren durch die entsprechenden Unicode-Symbole.
**/
function math_symbols(text) {
	if (!text) {
		return text;
	}
	return (""+text).replace(/\>\=/g, "≥").replace(/\<\=/g, "≤").replace(/\!\=/g, "≠").replace(/\\sum/g, "\u2211");
}

/**
*** Mit _ und ^ können hoch- und tiefgestellte Texte erzeugt werden,
*** entweder einzelne Buchstaben/Ziffern oder Gruppen mit {}, Z.b H_2O oder H_{2}O.
*** Das ersetzt natürlich kein LaTeX.
*** Die Eingabe ist plaintext im o.g. Format, die Ausgabe HTML.
**/
function chem_formel(text) {
	if (!text) {
		return text;
	}
	var html = escapeHtml(math_symbols(text));
	var html = html.replace(/_{([^}]+)}/g, "<sub>$1</sub>"); 
	var html = html.replace(/_(.)/g, "<sub>$1</sub>"); 
	var html = html.replace(/\^{([^}]+)}/g, "<sup>$1</sup>"); 
	var html = html.replace(/\^(.)/g, "<sup>$1</sup>"); 
	log.debug("chem_formel " + text + " => " + html);
	return html;
}

hvbtup avatar Aug 04 '22 07:08 hvbtup

@hvbtup Well, there are some problems with if judgment, which has been fixed

fadeli1 avatar Aug 04 '22 09:08 fadeli1