forked from svaarala/duktape
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcustombehavior.html
More file actions
227 lines (182 loc) · 10.2 KB
/
custombehavior.html
File metadata and controls
227 lines (182 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
<h1 id="custombehavior">Custom behavior</h1>
<p>This section summarizes Duktape behavior which deviates from the E5.1 or
other relevant specifications.</p>
<h2>Duktape built-in and custom types</h2>
<p>The <code>Duktape</code> built-in is (of course) non-standard and provides
access to Duktape specific features. Also the buffer, pointer, and lightfunc
types are custom.</p>
<h2>Hidden Symbols</h2>
<p>Objects may have properties with <a href="#symbols">hidden Symbol</a> keys.
These are similar to ES2015 Symbols but won't be enumerated or returned from even
<code>Object.getOwnPropertySymbols()</code>. Ordinary ECMAScript code cannot
refer to such properties because the keys intentionally use an invalid (extended)
UTF-8 representation.</p>
<h2>"use duk notail" directive</h2>
<p>The <a href="#use-duk-notail">"use duk notail"</a> directive is non-standard.
It prevents a function from being tail called.</p>
<h2>"const" treated mostly like "var"</h2>
<p>The <code>const</code> keyword is supported with minimal non-standard
semantics (officially defined in ECMAScript 6). See
<a href="#es6-const">Const variables</a> for more detail.</p>
<h2>Additional Error and Function object properties</h2>
<p>See
<a href="#errorobjects">Error objects</a> and
<a href="functionobjects">Function objects</a>.</p>
<p>Non-strict function instances don't have a <code>caller</code> property in the
E5/E5.1 specification. Some real world code expects to have this property, so it
can be enabled with the config option <code>DUK_USE_NONSTD_FUNC_CALLER_PROPERTY</code>.</p>
<h2>Function statements</h2>
<p>E5.1 does not allow a function declaration to appear outside program or
function top level:</p>
<pre class="ecmascript-code">
function test() {
// point A
try {
throw new Error('test');
} catch (e) {
// This is a SyntaxError in E5.1
function func() {
print(typeof e);
}
// point B
}
// point C
}
</pre>
<p>These declarations are also referred to as "function statements", and appear
quite often in real world code (including the test262 test suite), so they are
allowed by Duktape. Unfortunately there are several semantics used by different
Javascript engines (<a href="http://www.ecma-international.org/ecma-262/6.0/index.html#sec-block-level-function-declarations-web-legacy-compatibility-semantics">ES2015</a>
unfortunately doesn't specify semantics for function statements either).
Duktape follows the V8 behavior for function statements:</p>
<ul>
<li>Strict function: a SyntaxError is thrown (standard behavior).</li>
<li>Non-strict function: treat a function statement like an ordinary function
declaration, conceptually "hoisting" it to the top of the function.</li>
</ul>
<p>As an illustration, the above example would behave as the following:</p>
<pre class="ecmascript-code">
function test() {
function func() {
print(typeof e);
}
try {
throw new Error('test');
} catch (e) {
}
}
</pre>
<p><code>func()</code> in the above example would already be declared
and callable in point A, and would not have access to the <code>e</code>
binding in any of the points A, B, or C.</p>
<h2>RegExp leniency</h2>
<p>Most ECMAScript engines support more syntax than guaranteed by the
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-15.10.1">ECMAScript
E5.1 specification (Section 15.10.1 Patterns)</a>. As a result there's quite
a lot of code that won't work with strict ECMAScript E5.1 regexp syntax. Much
of the additional syntax expected of web browser engines is documented in
<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns">ES2015 Annex B.1.4 Regular Expression Patterns</a>.
However, note that features in
<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-additional-ecmascript-features-for-web-browsers">Annex B Additional ECMAScript Features for Web Browsers</a> are
not recommended for new code:
"These features are not considered part of the core ECMAScript language.
Programmers should not use or assume the existence of these features and
behaviours when writing new ECMAScript code. ECMAScript implementations
are discouraged from implementing these features unless the implementation
is part of a web browser or is required to run the same legacy ECMAScript
code that web browsers encounter."</p>
<p>Duktape also allows some ES2015 Annex B syntax to better support existing
code. You can turn this non-standard behavior off using config options if
you prefer. Some examples of additional syntax supported:</p>
<pre>
/{(\d+)}/ // unescaped left curly, digits, unescaped right curly; ES2015 Annex B
/\{(\d+)\}/ // same, ES5 compliant
/]/ // unescaped right bracket; ES2015 Annex B
/\]/ // same, ES5 compliant
/\$/ // literal dollar using escape; ES2015 Annex B
/\u0024/ // same, ES5 compliant
</pre>
<h2>Setter/getter key argument</h2>
<p>ECMAScript standard behavior is that setters and getters are not given
the name of the property being accessed. This prevents reusing a single
setter or a getter for multiple properties; separate functions are needed
for each property which is sometimes inconvenient and wastes memory.</p>
<p>Duktape provides the property key name as a non-standard additional
argument to setter and getter functions. See
<a href="https://github.com/svaarala/duktape/blob/master/tests/ecmascript/test-dev-nonstd-setget-key-argument.js">test-dev-nonstd-setget-key-argument.js</a>
and <a href="#propertyvirtualization">Property virtualization</a>
for more discussion. The strict standards compliant behavior can be enabled
by disabling the config options <code>DUK_USE_NONSTD_GETTER_KEY_ARGUMENT</code>
and <code>DUK_USE_NONSTD_SETTER_KEY_ARGUMENT</code>.</p>
<h2>Object.setPrototypeOf and Object.prototype.__proto__ (ES2015)</h2>
<p>See <a href="#es6-proto">Object.setPrototypeOf and Object.prototype.__proto__</a>.</p>
<h2>Proxy object (ES2015)</h2>
<p>See <a href="#es6-proxy">Proxy object (subset)</a>.</p>
<h2>JSON.stringify() escapes U+2028 and U+2029</h2>
<p><code>JSON.stringify()</code> standard behavior is to output U+2028 and
U+2029 without escaping. This leads to counterintuitive behavior when the
output is used in a web page or parsed with <code>eval()</code>: the U+2028
and U+2029 characters are considered line terminators which leads to a syntax
error (unterminated string). Duktape escapes U+2028 and U+2029 by default
to avoid this issue; you can turn on the compliant behavior by disabling the
config option <code>DUK_USE_NONSTD_JSON_ESC_U2028_U2029</code>.</p>
<h2>String.fromCharCode() accepts 32-bit codepoints</h2>
<p><code>String.fromCharCode()</code> standard behavior is to use ToUInt16()
coercion for codepoint values. Duktape uses ToUint32() by default to better
support non-BMP strings. You can force the compliant behavior by disabling
the config optipn <code>DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT</code>.</p>
<h2>Array instance numeric index writes</h2>
<p>By default Duktape provides a fast path for writing to Array instances.
The fast path is active when numeric indices are used (e.g. <code>arr[7] = 'foo'</code>)
and a few internal conditions are met. When the fast path is taken, Duktape
doesn't check Array.prototype for conflicting properties (these are very rare in
practical code), which makes common array writes faster. The behavior is
non-compliant, but there's no outward difference unless Array.prototype has
properties with numeric keys. You can turn on the compliant behavior by
disaling the config options <code>DUK_USE_NONSTD_ARRAY_WRITE</code> and
<code>DUK_USE_ARRAY_PROP_FASTPATH</code>. See the following for more
details on the fast path behavior:
<a href="https://github.com/svaarala/duktape/blob/master/tests/ecmascript/test-misc-array-fast-write.js">test-misc-array-fast-write.js</a>.</p>
<h2 id="typedarray-custombehavior">TypedArray binding</h2>
<p>Duktape provides the ES2015 TypedArray binding, with some details yet
to be fixed, e.g. small differences in argument coercion e.g. for offset
and length values.</p>
<p>The plain buffer custom type behaves mostly like an Uint8Array object
for ECMAScript code, but has a separate type in the Duktape C API.</p>
<h2 id="nodejsbuffer-custombehavior">Node.js Buffer binding</h2>
<p>Duktape provides a Node.js-like <code>Buffer</code> binding. There are
some differences between the Node.js behavior and Duktape behavior. These
differences include:</p>
<ul>
<li>Interoperability with other buffer types: ArrayBuffer, DataView, or a
typed array (Uint8Array etc) is usually allowed wherever a Node.js Buffer
would be allowed.</li>
<li>Buffer data is always zeroed on allocation and when concatenation
<code>totalLength</code> exceeds combined size of input buffers.</li>
<li>Read/write offset and length arguments are always validated to ensure
memory safe behavior, even when <code>noAssert</code> is true. Failed
reads return NaN and failed writes return 0.</li>
<li>Partial read/writes are never done: if a read/write is partially
outside the valid buffer, it is rejected.</li>
<li>Small differences in argument coercion for e.g. offset and length
values.</li>
<li>Write calls coerce their value argument like TypedArray, e.g. when
writing 0x100 using <code>writeUInt8()</code> silently coerces to
0x00 rather than throwing a TypeError.</li>
<li>Duktape only supports the <code>"utf8"</code> encoding (and accepts no
spelling variants). Most API calls ignore an encoding argument, and
use UTF-8 implicitly for string-to-buffer coercion.</li>
<li>UTF-8 decoding replacement character approach follows
<a href="http://unicode.org/review/pr-121.html">Unicode Technical Committee Recommended Practice for Replacement Characters</a>
which matches WHATWG Encoding API specification but differs from Node.js
(at least up to version v6.9.1).</li>
</ul>
<h2>Shebang comment support</h2>
<p><code>duk_compile()</code> flag <code>DUK_COMPILE_SHEBANG</code> allows shebang
comment parsing: <code>#!</code> on the first column of the first line causes the
line to be treated as a comment. For example:</p>
<pre>
#!/usr/bin/duk
print('Hello world!');
</pre>
<p>The feature can be disabled by undefining <code>DUK_USE_SHEBANG_COMMENTS</code>.</p>