Attempts to forbid the addition of any new properties to an object.

Syntax

// Added in SpiderMonkey 45

bool
JS_PreventExtensions(JSContext *cx, JS::HandleObject obj, JS::ObjectOpResult &result);

// Obsolete since JSAPI 39

bool
JS_PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded);
Name Type Description
cx JSContext * The context. Requires request. In a JS_THREADSAFE build, the caller must be in a request on this JSContext.
obj JS::HandleObject Object to be made non-extensible.
result JS::ObjectOpResult & (out parameter) Receives the result of the operation. Added in SpiderMonkey 45
succeeded bool * Outparam indicating, on JSAPI success, whether the object is now non-extensible. Obsolete since JSAPI 39

Description

All JavaScript objects recognize the concept of extensibility: whether new properties may be added to the object.  In some situations, it may be convenient to prohibit new properties.  In JavaScript this may be accomplished using the Object.preventExtensions method.  The similar JSAPI method is JS_PreventExtensions.

The failure-mode information below is new as of SpiderMonkey 36.  Before then, JS_PreventExtensions did not accept a succeeded argument; in those cases where *succeeded would be set to false, JS_PreventExtensions would throw a TypeError and return false.

Unlike Object.preventExtensions, JS_PreventExtensions doesn't necessarily throw a TypeError if the object couldn't be made non-extensible.  There are instead two modes of failure: through internal error, and because the object denied the attempt.

The first case occurs when something went wrong internally, not necessarily because the object chose not to become non-extensible.  For example, if making the object requires an allocation, and that allocation fails, out-of-memory might be reported, and JS_PreventExtensions would return false.  This might also occur if the object is a proxy, and some internal state of the proxy means that no coherent behavior is possible.  For example, if the object is a revocable proxy that has been revoked, it makes no sense to say that an attempt to prevent extensions either succeeded or failed: it's a category error.  Thus in this case JS_PreventExtensions will throw an error.

var target = {};
var handler = {};
var pair = Proxy.revocable(target, handler);

var proxy = pair.proxy;
var revoke = pair.revoke;

revoke();

// bool succeeded;
// bool rv = JS_PreventExtensions(cx, proxy, &succeeded);
// // rv == false, succeeded is indeterminate

The second case occurs when no internal error is encountered, but the object simply refuses to be made non-extensible.  For example, a proxy might refuse to be made non-extensible; this refusal would show up in the post-call value of *succeeded.

var target = {};
var handler = { preventExtensions: function(obj) { return false; } };
var obj = new Proxy(target, handler);

// bool succeeded;
// bool rv = JS_PreventExtensions(cx, obj, &succeeded);
// // rv == true, succeeded == false

Note that as with most JSAPI methods, *succeeded is only set if JS_PreventExtensions returns true (that is, does not fail).  Thus you should always check the return value of JS_PreventExtensions, and only if that is true check the value of *succeeded.

See Also