JSPropertyOp

JSPropertyOp and JSStrictPropertyOp are the type of property getter and setter callbacks in the JSAPI.

They are also the types of the JSClass.addProperty, getProperty, and setProperty callbacks, which are called during object property accesses.

Syntax

typedef bool
(* JSPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                 JS::MutableHandleValue vp);

typedef bool
(* JSStrictPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                       bool strict, JS::MutableHandleValue vp); // Added in SpiderMonkey 1.9.3
Name Type Description
cx JSContext *

The context in which the property access is taking place.

Provides request. In JS_THREADSAFE builds, the JavaScript engine calls this callback only from within an active request on cx. The callback does not need to call JS_BeginRequest()).

obj JS::HandleObject The object whose properties are being accessed.
id JS::HandleId The name or index of the property being accessed. This is either a string (Unicode property identifier) or an integer (element index).
strict bool (JSStrictPropertyOp only) If strict is true, treating the assignment as strict mode code.
vp JS::MutableHandleValue In/out parameter. Points to a JS::Value variable. The meaning of this variable is different for each of the hooks; see below.

Description

JSPropertyOp and JSStrictPropertyOp callbacks are hooks that applications may install to be called at some point during property access. A JSPropertyOp may be installed on an individual property as a getter or setter; or it may be installed on a JSClass to hook property gets, sets, or adds. These different cases are described in more detail in the sections below.

If a JSPropertyOp or JSStrictPropertyOp does nothing and returns true, then property get, set, or add is unaffected. It proceeds as normal.

Each of these callbacks may veto the ongoing property operation by optionally reporting an error or raising an exception and then returning false. The operation then fails, and the error is propagated to the caller. Otherwise the callback must return true, and the property operation proceeds.

Getters and setters

When a JSAPI application creates a property on an object (for example, using JS_DefineProperty or JS_DefineProperties) it can specify getter and setter callbacks for the new property.

Getters. The getter callback is called each time JavaScript code accesses the property's value using the syntax obj.prop or obj[propname]. It is also called when the property's value is accessed via JSAPI functions such as JS_GetProperty or (less obviously) JS_CallFunctionName. On entry, *vp contains the property's stored value or undefined if the property doesn't have a stored value. The callback may modify *vp. On success, the callback returns true and the value left in *vp is returned to the script or JSAPI caller.

Setters. The setter callback is called each time JavaScript code assigns to the property using any assignment operator (=, +=, etc.) or the ++ or -- operators. It is also called when the property is set via JSAPI functions such as JS_SetProperty. On entry, *vp contains the value being assigned to the property. The callback may modify *vp. On success, the callback returns true. If the property has a stored value, it is then updated to the value left in *vp after the callback.

As of SpiderMonkey 1.7, the value of a property assignment expression, like (a.length = x), is the value of *vp after the setter is called. This is typically the value of the left-hand side after assignment, as opposed to the value of the right-hand side, as required by ECMA 262-3 ยง11.13. This ECMAScript incompatibility is observable when assigning to the length property of an Array, for example. This incompatibility will be fixed in SpiderMonkey 1.8; see bug 312354.

Inherited properties. Note that in JavaScript, an object can inherit properties from its prototype. Getters (and sometimes setters; see JS_SetProperty for details) are called even when the property being accessed is found on a prototype and not on obj itself. In this case obj points to the object from which the property is being accessed, not the object on which the property was defined.

JSClass hooks

JSClass offers following hooks:

JSPropertyOp
  • JSClass.addProperty is called just after a new property is added to an object. This happens when a program sets a property that isn't already an own property of the target object. It also happens in JSAPI functions such as JS_DefineProperty. On entry, *vp contains the value provided by the code defining or setting the property. The callback may modify *vp. On success, the post-callback value of *vp becomes the initial stored value of the new property.

    In JS_THREADSAFE builds, this callback is called with obj locked. It is therefore dangerous for the callback to call JSAPI functions, particularly if obj may have been visible to more than one thread.

  • JSClass.getProperty is the default getter for new properties. See the section on getters and setters above.

    JSClass.getProperty is also called when a program attempts to get a property that does not exist on obj or any prototype.

    On entry, *vp contains the property's stored value, or undefined if the property doesn't exist or doesn't have a stored value. The callback may modify *vp. On success, the post-callback value of *vp is returned to the caller. This value also becomes the property's new stored value, if the property exists and has a stored value.

JSStrictPropertyOp
  • JSClass.setProperty is the default setter for new properties. See the section on getters and setters above.

    A property's setter is called each time the property is assigned. Hence when a script assigns to a nonexisting property, first the object's class's addProperty hook is called, then the setProperty hook.

See Also