mirror of https://github.com/svaarala/duktape.git
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.
118 lines
5.0 KiB
118 lines
5.0 KiB
<h1 id="internalproperties">Internal properties</h1>
|
|
|
|
<p>Duktape supports non-standard <b>internal properties</b> which are
|
|
essentially hidden from user code. They can only be accessed by a
|
|
direct property read/write, and are never enumerated, serialized by
|
|
<code>JSON.stringify()</code> or returned from built-in functions such
|
|
as <code>Object.getOwnPropertyNames()</code>.</p>
|
|
|
|
<p>Duktape uses internal properties for various implementation specific
|
|
purposes, such as storing an object's finalizer reference, the internal
|
|
value held by <code>Number</code> and <code>Date</code>, etc. User code
|
|
can also use internal properties for its own purposes, e.g. to
|
|
store "hidden state" in objects, as long as the property names never
|
|
conflict with current or future Duktape internal keys (this is ensured
|
|
by the naming convention described below). User code should never try
|
|
to access Duktape's internal properties: the set of internal properties
|
|
used can change arbitrarily between versions.</p>
|
|
|
|
<p>Internal properties are distinguished from other properties by the
|
|
property key: if the byte representation of a property key begins with
|
|
a <code>0xFF</code> byte Duktape automatically treats the property as an
|
|
internal property. Such a string is referred to as an <b>internal string</b>.
|
|
The initial byte makes the key invalid UTF-8 (even invalid extended UTF-8),
|
|
which ensures that (1) internal properties never conflict with normal Unicode
|
|
property names and that (2) ordinary Ecmascript code cannot accidentally access
|
|
them. The initial prefix byte is often represented by an underscore in
|
|
documentation for readability, e.g. <code>_Value</code> is used instead
|
|
of <code>\xFFValue</code>.</p>
|
|
|
|
<p>The following naming convention is used. The convention ensures that
|
|
Duktape and user internal properties never conflict:</p>
|
|
<table>
|
|
<tr>
|
|
<th>Type</th>
|
|
<th>Example (C)</th>
|
|
<th>Bytes</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td>Duktape</td>
|
|
<td><code>"\xFF" "Value"</code></td>
|
|
<td><code>ff 56 61 6c 75 65</code></td>
|
|
<td>First character is always uppercase, followed by <code>[a-z0-9_]*</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>User</td>
|
|
<td><code>"\xFF" "myprop"</code></td>
|
|
<td><code>ff 6d 79 70 72 6f 70</code></td>
|
|
<td>First character must not be uppercase to avoid conflict with
|
|
current or future Duktape keys.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>User</td>
|
|
<td><code>"\xFF\xFF" <arbitrary></code></td>
|
|
<td><code>ff ff <arbitrary></code></td>
|
|
<td>Double <code>0xFF</code> prefix followed by arbitrary data.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p>In some cases the internal key needed by user code is not static, e.g.
|
|
it can be dynamically generated by serializing a pointer or perhaps the
|
|
bytes are from an external source. In this case it is safest to use
|
|
two <code>0xFF</code> prefix bytes as the example above shows.</p>
|
|
|
|
<div class="note">
|
|
Note that the <code>0xFF</code> prefix cannot be expressed as a valid
|
|
Ecmascript string. For example, the internal string <code>\xFFxyz</code>
|
|
would appear as the bytes <code>ff 78 79 7a</code> in memory, while the
|
|
Ecmascript string <code>"\u00ffxyz"</code> would be represented as the
|
|
CESU-8 bytes <code>c3 bf 78 79 7a</code> in memory.
|
|
</div>
|
|
|
|
<p>Creating an internal string is easy from C code:</p>
|
|
<pre class="c-code">
|
|
/* Create an internal string, which can then be used to read/write internal
|
|
* properties, and can be passed on to Ecmascript code like any other string.
|
|
* Terminating a string literal after a hex escape is safest to avoid some
|
|
* ambiguous cases like "\xffab".
|
|
*/
|
|
duk_push_string(ctx, "\xff" "myprop");
|
|
</pre>
|
|
|
|
<p>For more discussion on C string hex escaping, see
|
|
<a href="https://github.com/svaarala/duktape/blob/master/misc/c_hex_esc.c">c_hex_esc.c</a>.</p>
|
|
|
|
<p>Internal strings can also be created from Ecmascript code if one has access
|
|
to e.g. the Buffer constructor or <code>Duktape.dec()</code> (this must be considered
|
|
in sandboxing):</p>
|
|
<pre class="ecmascript-code">
|
|
// Using Duktape.Buffer()
|
|
var buf = new Duktape.Buffer(1);
|
|
buf[0] = 255;
|
|
var key1 = buf + 'myprop';
|
|
|
|
// Using Duktape.dec()
|
|
var key2 = Duktape.dec('hex', 'ff6d7970726f70'); // \xFFmyprop
|
|
</pre>
|
|
|
|
<p>There's no special access control for internal properties: if user code has
|
|
access to the property name (string), it can read/write the property value.
|
|
Any code with the ability to create or use buffers can potentially create an
|
|
internal string by converting a buffer into a string. However, standard Ecmascript
|
|
code with no access to buffer values or ability to create them cannot create internal
|
|
strings (or any invalid UTF-8 strings in general). When sandboxing, ensure that
|
|
the sandboxed code has no access to the <code>Duktape</code> built-in or any
|
|
buffer values.</p>
|
|
|
|
<p>As a concrete example, the internal value of a <code>Date</code> can be
|
|
accessed as follows:</p>
|
|
<pre class="ecmascript-code">
|
|
// Print the internal timestamp of a Date instance. User code should NEVER
|
|
// actually do this because the internal properties may change between
|
|
// versions in an arbitrary manner!
|
|
|
|
var key = Duktape.dec('hex', 'ff56616c7565'); // \xFFValue
|
|
var dt = new Date(123456);
|
|
print('internal value is:', dt[key]); // prints 123456
|
|
</pre>
|
|
|