You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

332 lines
12 KiB

name: duk_def_prop
proto: |
void duk_def_prop(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t flags);
stack: |
[ ... obj! ... key! ] -> [ ... obj! ... ] (if have no value, setter, getter)
[ ... obj! ... key! value! ] -> [ ... obj! ... ] (if have value)
[ ... obj! ... key! getter! ] -> [ ... obj! ... ] (if have getter, but no setter)
[ ... obj! ... key! setter! ] -> [ ... obj! ... ] (if have setter, but no getter)
[ ... obj! ... key! getter! setter! ] -> [ ... obj! ... ] (if have both getter and setter)
summary: |
<p>Create or alter the attributes of property <code>key</code> of object at
<code>obj_idx</code>, with semantics like
<code><a href="http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.3.6">Object.defineProperty()</a></code>.
When the requested change is not allowed (e.g. property is not configurable), a
<code>TypeError</code> is thrown. If the target is not an object (or the
index is invalid) an error is thrown.</p>
<p>The flags field provides "have" flags to indicate what property attributes
are changed, which models the partial property descriptors allowed by
<code>Object.defineProperty()</code>. Values for the writable, configurable,
and enumerable attributes are given in the flags field, while property value,
getter, and setter are given as value stack arguments. When creating a new
property, missing attribute values cause
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-8.6.1">Ecmascript defaults</a>
to be used (false for all boolean attributes, undefined for value, getter, setter);
when modifying an existing property missing attribute values mean that existing
attribute values are not touched.</p>
<p>As a concrete example:</p>
<pre class="ecmascript-code">
// Set value, set writable, clear enumerable, leave configurable untouched.
Object.defineProperty(obj, { value: 123, writable: true, enumerable: false });
</pre>
<p>Would map to:</p>
<pre class="c-code">
duk_push_uint(ctx, 123); /* value is taken from stack */
duk_def_prop(ctx, obj_idx,
DUK_DEFPROP_HAVE_VALUE | /* <=> value: 123 */
DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE | /* <=> writable: true */
DUK_DEFPROP_HAVE_ENUMERABLE); /* <=> enumerable: false */
</pre>
<p>With the <code>DUK_DEFPROP_FORCE</code> flag property changes can be forced
even when an operation would normally fail due to a non-extensible target object
or a non-configurable property. This cannot be done from Ecmascript code with
<code>Object.defineProperty()</code> and is useful for e.g. sandboxing setup.
In some cases even a forced change is not possible and will cause an error to be
thrown. For instance, properties implemented internally as virtual properties
may not be modifiable (such as string <code>.length</code> and index properties)
or may have limitations (such as array <code>.length</code> property which cannot
be made configurable or enumerable due to internal limitations).</p>
<p>The following base flags are defined:</p>
<table>
<tr>
<th>Define</th>
<th>Description</th>
</tr>
<tr>
<td>DUK_DEFPROP_WRITABLE</td>
<td>Set writable attribute, effective only if DUK_DEFPROP_HAVE_WRITABLE is set.</td>
</tr>
<tr>
<td>DUK_DEFPROP_ENUMERABLE</td>
<td>Set enumerable attribute, effective only if DUK_DEFPROP_HAVE_ENUMERABLE is set.</td>
</tr>
<tr>
<td>DUK_DEFPROP_CONFIGURABLE</td>
<td>Set configurable attribute, effective only if DUK_DEFPROP_HAVE_CONFIGURABLE is set.</td>
</tr>
<tr>
<td>DUK_DEFPROP_HAVE_WRITABLE</td>
<td>Set or clear writable attribute (no change if unset).</td>
</tr>
<tr>
<td>DUK_DEFPROP_HAVE_ENUMERABLE</td>
<td>Set or clear enumerable attribute (no change if unset).</td>
</tr>
<tr>
<td>DUK_DEFPROP_HAVE_CONFIGURABLE</td>
<td>Set or clear configurable attribute (no change if unset).</td>
</tr>
<tr>
<td>DUK_DEFPROP_HAVE_VALUE</td>
<td>Set value attribute, value is given on value stack.</td>
</tr>
<tr>
<td>DUK_DEFPROP_HAVE_GETTER</td>
<td>Set getter attribute, value is given on value stack.</td>
</tr>
<tr>
<td>DUK_DEFPROP_HAVE_SETTER</td>
<td>Set setter attribute, value is given on value stack.</td>
</tr>
<tr>
<td>DUK_DEFPROP_FORCE</td>
<td>Force attribute change if possible, even if property is non-configurable.</td>
</tr>
</table>
<p>There are a also convenience defines mapping to common flag combinations.
For example, DUK_DEFPROP_SET_WRITABLE is equivalent to DUK_DEFPROP_HAVE_WRITABLE
and DUK_DEFPROP_WRITABLE. Currently the following are defined:</p>
<table>
<tr>
<th>Define</th>
<th>Description</th>
</tr>
<tr>
<td>DUK_DEFPROP_{SET,CLEAR}_WRITABLE</td>
<td>Set or clear the 'writable' attribute.</td>
</tr>
<tr>
<td>DUK_DEFPROP_{SET,CLEAR}_ENUMERABLE</td>
<td>Set or clear the 'enumerable' attribute.</td>
</tr>
<tr>
<td>DUK_DEFPROP_{SET,CLEAR}_CONFIGURABLE</td>
<td>Set or clear the 'configurable' attribute.</td>
</tr>
<tr>
<td>DUK_DEFPROP_SET_{W,E,C,WE,WC,WEC}</td>
<td>Set one or more attributes, don't touch other attributes.</td>
</tr>
<tr>
<td>DUK_DEFPROP_CLEAR_{W,E,C,WE,WC,WEC}</td>
<td>Clear one or more attributes, don't touch other attributes.</td>
</tr>
<tr>
<td>DUK_DEFPROP_ATTR_{W,E,C,WE,WC,WEC}</td>
<td>Set or clear writable, enumerable, and configurable attributes.
For example, DUK_DEFPROP_ATTR_WC sets writable and configurable,
and clears enumerable.</td>
</tr>
<tr>
<td>DUK_DEFPROP_HAVE_{W,E,C,WE,WC,WEC}</td>
<td>Indicate one or more attributes are set/cleared, e.g.
DUK_DEFPROP_HAVE_WC is equivalent to
DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_CONFIGURABLE.</td>
</tr>
<tr>
<td>DUK_DEFPROP_{W,E,C,WE,WC,WEC}</td>
<td>Provide attribute values (effective if matching "have" flag is
set), e.g. DUK_DEFPROP_WE is equivalent to
DUK_DEFPROP_WRITABLE | DUK_DEFPROP_ENUMERABLE.</td>
</tr>
</table>
<p>Some examples (see more examples below):</p>
<ul>
<li>To set value, set writable, clear enumerable, and set configurable,
push the value onto the value stack and set flags to:
<ul>
<li>Base flags: <code>DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE</code>; or</li>
<li>Convenience: <code>DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_ATTR_WC</code>.</li>
</ul>
</li>
<li>To clear the writable attribute (leaving other attributes untouched), set flags to:
<ul>
<li>Base flags: <code>DUK_DEFPROP_HAVE_WRITABLE; or</li>
<li>Convenience: <code>DUK_DEFPROP_CLEAR_WRITABLE</code>; or</li>
<li>Convenience: <code>DUK_DEFPROP_CLEAR_W</code>.</li>
</ul>
</li>
<li>To set value, clear writable, and set enumerable (leaving other attributes untouched), push the value onto
the value stack and set flags to:
<ul>
<li>Base flags: <code>DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE</code>; or</li>
<li>Convenience: <code>DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_W | DUK_DEFPROP_SET_E</code>; or</li>
<li>Convenience: <code>DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WE | DUK_DEFPROP_E</code>.</li>
</ul>
</li>
</ul>
<p>This API call is useful for various things:</p>
<ul>
<li>To create properties with non-default attributes directly from C code.</li>
<li>To create accessor (getter/setter) properties directly from C code.</li>
<li>To modify the property attributes of existing properties directly from C code.</li>
</ul>
<p>See API testcase
<a href="https://github.com/svaarala/duktape/blob/master/tests/api/test-def-prop.c">test-def-prop.c</a>
for more examples.</p>
<div class="note">
If the target is a Proxy object which implements the <code>defineProperty</code>
trap, the trap should be invoked. However, Duktape doesn't currently support
the <code>defineProperty</code> trap, and the defineProperty() operation isn't
currently forwarded to the target. When support is added, this API call will
start invoking the trap or forwarding the operation to the target object.
</div>
example: |
duk_idx_t obj_idx = /* ... */;
/* Create an ordinary property which is writable and configurable, but
* not enumerable. Equivalent to:
*
* Object.defineProperty(obj, 'my_prop_1', {
* value: 123, writable: true, enumerable: false, configurable: true
* });
*/
duk_push_string(ctx, "my_prop_1");
duk_push_int(ctx, 123); /* prop value */
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_VALUE |
DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
DUK_DEFPROP_HAVE_ENUMERABLE | 0 |
DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
/* The same but more readable using convenience flags. */
duk_push_string(ctx, "my_prop_1");
duk_push_int(ctx, 123); /* prop value */
duk_def_prop(ctx, obj_idx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_ATTR_WC);
/* Change the property value and make it non-writable. Don't touch other
* attributes. Equivalent to:
*
* Object.defineProperty(obj, 'my_prop_1', {
* value: 321, writable: false
* });
*/
duk_push_string(ctx, "my_prop_1");
duk_push_int(ctx, 321);
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_VALUE |
DUK_DEFPROP_HAVE_WRITABLE | 0);
/* The same but more readable using convenience flags. */
duk_push_string(ctx, "my_prop_1");
duk_push_int(ctx, 321);
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_WRITABLE);
/* Make the property non-configurable, don't touch value or other attributes.
* Equivalent to:
*
* Object.defineProperty(obj, 'my_prop_1', {
* configurable: false
* });
*/
duk_push_string(ctx, "my_prop_1");
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_CONFIGURABLE | 0);
/* The same but more readable using convenience flags. */
duk_push_string(ctx, "my_prop_1");
duk_def_prop(ctx, obj_idx, DUK_DEFPROP_CLEAR_CONFIGURABLE);
/* Create an accessor property which is non-configurable and non-enumerable.
* Attribute flags are not given so they default to Ecmascript defaults
* (false) automatically. Equivalent to:
*
* object.defineproperty(obj, 'my_accessor_1', {
* get: my_getter, set: my_setter
* });
*/
duk_push_string(ctx, "my_accessor_1");
duk_push_c_function(ctx, my_getter, 0 /*nargs*/);
duk_push_c_function(ctx, my_setter, 1 /*nargs*/);
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_GETTER |
DUK_DEFPROP_HAVE_SETTER);
/* Create an accessor property which is non-configurable but enumerable.
* Attribute flags are given explicitly which is easier to read without
* knowing about Ecmascript attribute default values. Equivalent to:
*
* Object.defineProperty(obj, 'my_accessor_2', {
* get: my_getter, set: my_setter, enumerable: true, configurable: false
* });
*/
duk_push_string(ctx, "my_accessor_2");
duk_push_c_function(ctx, my_getter, 0 /*nargs*/);
duk_push_c_function(ctx, my_setter, 1 /*nargs*/);
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_GETTER |
DUK_DEFPROP_HAVE_SETTER |
DUK_DEFPROP_HAVE_CONFIGURABLE | /* clear */
DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE); /* set */
/* The same but more readable with convenience flags. */
duk_push_string(ctx, "my_accessor_2");
duk_push_c_function(ctx, my_getter, 0 /*nargs*/);
duk_push_c_function(ctx, my_setter, 1 /*nargs*/);
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_GETTER |
DUK_DEFPROP_HAVE_SETTER |
DUK_DEFPROP_HAVE_CLEAR_CONFIGURABLE |
DUK_DEFPROP_HAVE_SET_ENUMERABLE);
/* Change the value of a non-configurable property by force.
* No Ecmascript equivalent.
*/
duk_push_string(ctx, "my_nonconfigurable_prop");
duk_push_value(ctx, 321);
duk_def_prop(ctx,
obj_idx,
DUK_DEFPROP_HAVE_VALUE |
DUK_DEFPROP_FORCE);
tags:
- property
- sandbox
seealso:
- duk_get_prop_desc
introduced: 1.1.0