GWT normalizes away JS null vs undefined so that Java code doesn't need to worry about the difference. There are two cases (that I can think of right now) where Java code can deal explicitly with undefined:
Js.undefined() gives Java the ability to ensure it has an undefined value, though it will show up as null in any Java == comparisons
Js.typeof(value) will return "undefined" when passed an undefined value (whereas null would result in "object"). The exception to this rule is document.all, due to a bug in IE that ended up being made into the spec.
To achieve this, Cast.maskUndefined is used in cases where the Java == or != operators could be used on a nullable reference.
|
static native Object maskUndefined(Object src) /*-{ |
|
return (src == null) ? null : src; |
|
}-*/; |
That is, if the compiler can't prove that one side or the other cannot be a null, it will replace the <reference> with maskUndefined(<reference>).
This means that when jsinterop returns an undefined into Java code (either as a property value, param to a method, return value from a method, etc), Java doesn't mind which, and can detect undefined (via value == null && Js.typeof(value).equals("undefined")). However, Java code that assigns properties, calls methods, or returns values to JS cannot guarantee that it is actually returning nulls vs undefineds - that is the topic of this issue.
This can be irritating for a few issues in JS - for example, === is usually the preferred comparison between objects in JS, yet while null === null and null == null both evaluate to true, null == undefined is true while null === undefined is false.
I propose that we add a configuration property (or compiler flag) to apply maskUndefined to any values as they are passed to native jsinterop. This will result in a small size increase in some cases, so probably should be opt-in.
GWT normalizes away JS null vs undefined so that Java code doesn't need to worry about the difference. There are two cases (that I can think of right now) where Java code can deal explicitly with undefined:
Js.undefined()gives Java the ability to ensure it has an undefined value, though it will show up as null in any Java==comparisonsJs.typeof(value)will return"undefined"when passed an undefined value (whereas null would result in"object"). The exception to this rule isdocument.all, due to a bug in IE that ended up being made into the spec.To achieve this, Cast.maskUndefined is used in cases where the Java
==or!=operators could be used on a nullable reference.gwt/dev/core/super/com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang/Cast.java
Lines 293 to 295 in 4e6ae10
That is, if the compiler can't prove that one side or the other cannot be a null, it will replace the
<reference>withmaskUndefined(<reference>).This means that when jsinterop returns an undefined into Java code (either as a property value, param to a method, return value from a method, etc), Java doesn't mind which, and can detect undefined (via
value == null && Js.typeof(value).equals("undefined")). However, Java code that assigns properties, calls methods, or returns values to JS cannot guarantee that it is actually returning nulls vs undefineds - that is the topic of this issue.This can be irritating for a few issues in JS - for example,
===is usually the preferred comparison between objects in JS, yet whilenull === nullandnull == nullboth evaluate to true,null == undefinedis true whilenull === undefinedis false.I propose that we add a configuration property (or compiler flag) to apply maskUndefined to any values as they are passed to native jsinterop. This will result in a small size increase in some cases, so probably should be opt-in.