JS::Value

JS::Value (also accessible using the jsval typedef, although this is deprecated) is the type of JavaScript values in the JSAPI.

A C++ variable of type JS::Value represents a value in JavaScript: a string, number, object (including arrays and functions), boolean, null, or undefined.

JS::Value is a class whose internal structure is an implementation detail.  Embeddings should not rely on observed representation details or upon the size of JS::Value.

The data in a JS::Value can be accessed using these member functions:

JS type JS::Value type tests Constructor Accessors Mutators
null val.isNull() NullValue() N/A  val.setNull()
undefined val.isUndefined() UndefinedValue() N/A val.setUndefined()
boolean val.isBoolean(), val.isTrue(), val.isFalse() BooleanValue(bool), TrueValue(), FalseValue() val.toBoolean() val.setBoolean(bool)
number val.isInt32(), val.isDouble(), val.isNumber() NumberValue(any number type), Int32Value(int32_t), DoubleValue(double) val.toInt32(), value.toDouble(), val.toNumber() val.setInt32(int32_t), val.setNumber(uint32_t), val.setNumber(double)
string val.isString() StringValue(JSString *) val.toString() val.setString(JSString *)
object val.isObject() ObjectValue(JSObject &), ObjectOrNullValue(JSObject *) val.toObject() val.setObject(JSObject &)

Numbers are stored in a JS::Value either as a double or as an int32_t. The different representations are visible using the separate int32/double methods but do not affect observable semantics (ignoring performance).  The number mutators attempt to use int32_t representation for compatible input values, returning true when int32 could be used and false when double representation was required. Any double value may be stored in a JS::Value, in one of these two representations. The only exception is that only a single NaN value can be represented. (Note that both -0 and +0 are allowed, and the latter may sometimes be stored using the int32_t representation.)

JS::Value further provides these methods combining various aspects of the above methods:

  • ObjectOrNullValue(JSObject *) returns an object value corresponding to the given non-null pointer, or a null value if the pointer is null.
  • val.setObjectOrNull(JSObject *) sets the given value to the specified object, or to null if the pointer was null.
  • Correspondingly, val.toObjectOrNull() returns a non-null JSObject * if the value is an object, and NULL if the value is null.
  • val.isPrimitive() returns true iff the value is a primitive value -- that is, not an object.  It is equivalent to !val.isObject().

The are two major issues to be aware of when using JS::Value.

JS::Value is not inherently type-safe
It is an error to call any accessor method on a value of a non-matching type: val.toInt32() must only be called if val.isInt32(), val.toString() must only be called if val.isString(), and so on.
In particular, note that it is an error to call val.toObject() when val.isNull().  The now-deprecated jsval methods allowed JSVAL_TO_OBJECT(val) when JSVAL_IS_NULL(val), but this was a source of constant bugs.  val.toObject() is only permitted when val.isObject(). An assertion is thrown in the case that the type is not correct (val.isX() is called for each val.toX(), where X is the type).
It is highly recommended that you develop and test with an --enable-debug build to detect most JS::Value misuse.  Debug builds will assert correct JSAPI use in many other instances as well.
 
JS::Value is subject to garbage collection
A JS::Value can refer to a string or object located in SpiderMonkey's garbage-collected heap.
The garbage collector is designed to automatically free unreachable memory. It is rather eager about its job. It's like a robot that goes around picking up everything that isn't nailed down and putting it in the trash. If an application has a JS::Value variable that refers to a JSObject, the garbage collector might not know you're using the JSObject. So it might free it, leaving a dangling pointer. The solution is to tell SpiderMonkey that you're using the object, then tell it again when you're done.
In short, every JS::Value must be rooted or your program will randomly crash. In some places, SpiderMonkey provides already-rooted JS::Values which you can use for variables. See SpiderMonkey GC Rooting Guide.

The jsval typedef for JS::Value

JS::Value was historically known in the JSAPI as jsval.  SpiderMonkey 1.8.5 made jsval into a C struct and exposed it in C++ through the full-fledged JS::Value class.  As of SpiderMonkey 17, jsval is a typedef of JS::Value, and SpiderMonkey is gradually transitioning to a new C++ JSAPI, at whose heart lies JS::Value.

jsval is deprecated; new code should use JS::Value.  The old JSVAL_IS_* methods, JSVAL_* constants and *_TO_JSVAL methods, and JSVAL_TO_* methods are also deprecated; uses of each should be replaced with use of the corresponding val.is*(), *Value(), and val.to*() methods.

JS type jsval type tests jsval constants and constructors jsval accessors
null JSVAL_IS_NULL(v) JSVAL_NULL   
undefined JSVAL_IS_VOID(v) JSVAL_VOID   
boolean JSVAL_IS_BOOLEAN(v) JSVAL_TRUE, JSVAL_FALSE, BOOLEAN_TO_JSVAL(b) JSVAL_TO_BOOLEAN(v)
number JSVAL_IS_NUMBER(v), JSVAL_IS_INT(v), JSVAL_IS_DOUBLE(v) JSVAL_ZERO, JSVAL_ONE, INT_TO_JSVAL(i), DOUBLE_TO_JSVAL(d) JSVAL_TO_INT(v), JSVAL_TO_DOUBLE(v)
string JSVAL_IS_STRING(v) STRING_TO_JSVAL(str) JSVAL_TO_STRING(v), JS_GetStringChars(str), JS_GetStringLength(str)
object !JSVAL_IS_PRIMITIVE(v) OBJECT_TO_JSVAL(obj) JSVAL_TO_OBJECT(v)


There was also a further method, JSVAL_IS_OBJECT(v), which did not what you would expect -- return true if the value was an object -- but rather returned true if the value was an object or if it was null.  These confusing semantics led to this method being removed from the JSAPI in more recent releases, but older code might still use it.  Uses of this method should be replaced with v.isObjectOrNull().

Document Tags and Contributors

Contributors to this page: lordblackfox, sfink, lw, Jorend, Waldo, teoli, MarkGiffin, Michael.Earth4
Last updated by: teoli,