diff --git a/docs/hop-user-manual/modules/ROOT/pages/pipeline/transforms/javascript.adoc b/docs/hop-user-manual/modules/ROOT/pages/pipeline/transforms/javascript.adoc index 80ad0e901ab..5d6cfdc22c5 100644 --- a/docs/hop-user-manual/modules/ROOT/pages/pipeline/transforms/javascript.adoc +++ b/docs/hop-user-manual/modules/ROOT/pages/pipeline/transforms/javascript.adoc @@ -248,6 +248,47 @@ Fields must be added to the rows in the same order to keep the structure of the To add a field, define it as var in the Javascript pane, and add it as a field in the Fields table. +=== [[stream-fields]]Stream fields are Java objects + +Fields coming from the input stream are not plain JavaScript primitives: the transform hands them to the Rhino engine as *wrapped Java objects* (`java.lang.Boolean`, `java.lang.Long`, `java.lang.String`, and so on). Variables you declare yourself with `var` inside the script are plain JavaScript values instead. That difference explains a number of surprising results, and `typeof` makes it visible: + +[source, javascript] +---- +var myBoolean = false; + +typeof(myBoolean); // "boolean" - declared in the script +typeof(booleanField); // "object" - coming from the stream +---- + +Two consequences are worth knowing about. + +*A Boolean field is always truthy.* Rhino treats any wrapped object as `true`, so an `if` on a Boolean field never takes the else branch, even when the field is `false`. Comparing explicitly with `true` does work, because the equality operator unwraps the object: + +[source, javascript] +---- +if (booleanField) { ... } // ALWAYS true, even when the field is false +if (booleanField == true) { ... } // correct +if (booleanField.valueOf()) { ... } // correct +---- + +*Comparing two fields with `==` or `!=` compares object identity, not values.* Two Integer fields holding the same number are still two distinct Java objects, so `!=` reports them as different. Force a conversion to a JavaScript value first: + +[source, javascript] +---- +if (intFieldA != intFieldB) { ... } // WRONG: compares references +if (intFieldA.valueOf() != intFieldB.valueOf()) { ... } // correct +if (parseInt(intFieldA) != parseInt(intFieldB)) { ... } // correct +---- + +As a rule of thumb, call `.valueOf()` (or `parseInt()`, `parseFloat()`, `String()`) on a stream field whenever you use it in a comparison or in a boolean test. + +A field that is null in the stream is put in the script scope as `null`. Testing it with `fieldName == null` is safe, but calling any method on it - including `.valueOf()` - fails, so check for null first: + +[source, javascript] +---- +var flag = (booleanField != null) && booleanField.valueOf(); +---- + === [[numeric-values]]Numeric values Most values that are assigned in JavaScript are floating point values by default, even if you think you have assigned an integer value. If you are having trouble using == or switch/case on values that you know are integers, use the following constructs: